diff --git a/.gitignore b/.gitignore index 5aba682b..6be2ae85 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ node_modules npm-debug.log .idea .DS_Store +.vscode diff --git a/.travis.yml b/.travis.yml index a2133b95..73da3307 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,4 +8,5 @@ node_js: script: - npm run lint + - npm run ts - npm test diff --git a/README.md b/README.md index 6287e2da..ccc77ae6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# +# [![npm version](https://img.shields.io/npm/v/react-toolbox.svg?style=flat-square)](https://www.npmjs.com/package/react-toolbox) [![Build Status](http://img.shields.io/travis/react-toolbox/react-toolbox/master.svg?style=flat-square)](https://travis-ci.org/react-toolbox/react-toolbox) [![NPM Status](http://img.shields.io/npm/dm/react-toolbox.svg?style=flat-square)](https://www.npmjs.org/package/react-toolbox) [![Donate](https://img.shields.io/badge/donate-paypal-blue.svg?style=flat-square)](https://paypal.me/javivelasco) [![OpenCollective](https://opencollective.com/react-toolbox/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/react-toolbox/sponsors/badge.svg)](#sponsors) diff --git a/ROADMAP.md b/ROADMAP.md index 8e982121..9f09fa3a 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,4 +1,4 @@ -This document defines a manifesto and the main Roadmap 🚵 ideas for [React Toolbox](www.react-toolbox.com). It's not a fixed document and of course it's open to change. You can leave your feedback in [this gist](https://gist.github.com/javivelasco/259d2087c2a8c3e8f2c5c720d1fd3f2e) or you can also do it [through an issue](https://github.com/react-toolbox/react-toolbox/issues/new). +This document defines a manifesto and the main Roadmap 🚵 ideas for [React Toolbox](www.react-toolbox.io). It's not a fixed document and of course it's open to change. You can leave your feedback in [this gist](https://gist.github.com/javivelasco/259d2087c2a8c3e8f2c5c720d1fd3f2e) or you can also do it [through an issue](https://github.com/react-toolbox/react-toolbox/issues/new). ## The Manifesto diff --git a/components/autocomplete/Autocomplete.d.ts b/components/autocomplete/Autocomplete.d.ts index b7d98d82..9eddafa1 100644 --- a/components/autocomplete/Autocomplete.d.ts +++ b/components/autocomplete/Autocomplete.d.ts @@ -88,6 +88,14 @@ export interface AutocompleteProps extends InputProps { * Callback function that is fired when component is focused. */ onFocus?: Function; + /** + * Callback function that is fired when a key is pressed down. + */ + onKeyDown?: Function; + /** + * Callback function that is fired when a key is lifted up. + */ + onKeyUp?: Function; /** * Callback function that is fired when the components's query value changes. */ diff --git a/components/autocomplete/Autocomplete.js b/components/autocomplete/Autocomplete.js index 099a0337..16354852 100644 --- a/components/autocomplete/Autocomplete.js +++ b/components/autocomplete/Autocomplete.js @@ -35,6 +35,8 @@ const factory = (Chip, Input) => { onBlur: PropTypes.func, onChange: PropTypes.func, onFocus: PropTypes.func, + onKeyDown: PropTypes.func, + onKeyUp: PropTypes.func, onQueryChange: PropTypes.func, query: PropTypes.string, selectedPosition: PropTypes.oneOf(['above', 'below', 'none']), @@ -132,7 +134,7 @@ const factory = (Chip, Input) => { }; handleQueryFocus = (event) => { - this.suggestionsNode.scrollTop = 0; + event.target.scrollTop = 0; this.setState({ active: '', focus: true }); if (this.props.onFocus) this.props.onFocus(event); }; @@ -148,6 +150,8 @@ const factory = (Chip, Input) => { if (event.which === 13) { this.selectOrCreateActiveItem(event); } + + if(this.props.onKeyDown) this.props.onKeyDown(event); }; handleQueryKeyUp = (event) => { @@ -160,6 +164,8 @@ const factory = (Chip, Input) => { if (index >= suggestionsKeys.length) index = 0; this.setState({ active: suggestionsKeys[index] }); } + + if(this.props.onKeyUp) this.props.onKeyUp(event); }; handleSuggestionHover = (event) => { @@ -375,7 +381,6 @@ const factory = (Chip, Input) => { return ( diff --git a/components/autocomplete/readme.md b/components/autocomplete/readme.md index 5da6b8ba..cf87d226 100644 --- a/components/autocomplete/readme.md +++ b/components/autocomplete/readme.md @@ -45,7 +45,7 @@ If you want to provide a theme via context, the component key is `RTAutocomplete |:-----|:-----|:-----|:-----| | `allowCreate` | `Bool` | `false` | Determines if user can create a new option with the current typed value | | `className` | `String` | `''` | Sets a class to style of the Component.| -| `direction` | `String` | `auto` | Determines the opening direction. It can be `auto`, `top` or `down`. | +| `direction` | `String` | `auto` | Determines the opening direction. It can be `auto`, `up` or `down`. | | `disabled` | `Bool` | `false` | If true, component will be disabled. | | `error` | `String` or `Node` | | Sets the error string for the internal input element. | | `keepFocusOnChange` | `Bool` | `false` | Whether component should keep focus after value change. | @@ -53,8 +53,10 @@ If you want to provide a theme via context, the component key is `RTAutocomplete | `multiple` | `Bool` | `true` | If true, component can hold multiple values. | | `onBlur` | `Function` | | Callback function that is fired when component is blurred. | | `onChange` | `Function` | | Callback function that is fired when the components's value changes. | -| `onQueryChange` | `Function` | | Callback function that is fired when the components's query input value changes. | | `onFocus` | `Function` | | Callback function that is fired when component is focused. | +| `onKeyDown` | `Function` | | Callback function that is fired when a key is pressed down. | +| `onKeyUp` | `Function` | | Callback function that is fired when a key is lifted up. | +| `onQueryChange` | `Function` | | Callback function that is fired when the components's query input value changes. | | `query` | `String` | | This property has to be used in case the `source` is not static and will be changing during search for `multiple={false}` autocomplete, content of the `query` has to be managed by the `onQueryChange` callback. | | `source` | `Object` or `Array` | | Object of key/values or array representing all items suggested. | | `selectedPosition` | `String` | `above` | Determines if the selected list is shown above or below input. It can be `above`, `below` or `none`. | diff --git a/components/autocomplete/theme.css b/components/autocomplete/theme.css index 5a7f88c9..5b175727 100644 --- a/components/autocomplete/theme.css +++ b/components/autocomplete/theme.css @@ -13,8 +13,8 @@ & .suggestions { box-shadow: var(--zdepth-shadow-1); max-height: var(--autocomplete-overflow-max-height); + -ms-overflow-style: none; visibility: visible; - -ms-overflow-style:none; } } } diff --git a/components/avatar/Avatar.js b/components/avatar/Avatar.js index 9d9dd944..84e6ea5c 100644 --- a/components/avatar/Avatar.js +++ b/components/avatar/Avatar.js @@ -10,7 +10,7 @@ const factory = (FontIcon) => {
{children} {cover && typeof image === 'string' && } - {!cover && (typeof image === 'string' ? {alt} : image)} + {!cover && (typeof image === 'string' ? {alt} : image)} {typeof icon === 'string' ? : icon} {title ? {title[0]} : null}
diff --git a/components/button/BrowseButton.d.ts b/components/button/BrowseButton.d.ts index d1d2bb40..1485e804 100644 --- a/components/button/BrowseButton.d.ts +++ b/components/button/BrowseButton.d.ts @@ -37,6 +37,8 @@ export interface BrowseButtonProps extends ButtonBaseProps { * Classnames object defining the component style. */ theme?: BrowseButtonTheme; + + onChange?: Function; } export class BrowseButton extends React.Component { } diff --git a/components/button/BrowseButton.js b/components/button/BrowseButton.js index 8eb9e5b9..dbbfd0dc 100644 --- a/components/button/BrowseButton.js +++ b/components/button/BrowseButton.js @@ -23,6 +23,7 @@ const factory = (ripple, FontIcon) => { inverse: PropTypes.bool, label: PropTypes.string, mini: PropTypes.bool, + multiple: PropTypes.bool, neutral: PropTypes.bool, onChange: PropTypes.func, onMouseLeave: PropTypes.func, @@ -53,6 +54,7 @@ const factory = (ripple, FontIcon) => { flat: false, floating: false, mini: false, + multiple: false, neutral: true, primary: false, raised: false, @@ -96,6 +98,7 @@ const factory = (ripple, FontIcon) => { inverse, label, mini, + multiple, neutral, primary, // eslint-disable-line raised, // eslint-disable-line @@ -130,6 +133,7 @@ const factory = (ripple, FontIcon) => { className={classes} type="file" accept={accept} + multiple={multiple} onChange={this.handleFileChange} />, children, diff --git a/components/button/Button.d.ts b/components/button/Button.d.ts index 22eb2a69..6fcba2f7 100644 --- a/components/button/Button.d.ts +++ b/components/button/Button.d.ts @@ -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. */ diff --git a/components/button/Button.js b/components/button/Button.js index 90634ea8..26fe3f40 100644 --- a/components/button/Button.js +++ b/components/button/Button.js @@ -101,6 +101,10 @@ const factory = (ripple, FontIcon) => { const element = href ? 'a' : 'button'; const level = this.getLevel(); const shape = this.getShape(); + const mouseEvents = { + onMouseUp: this.handleMouseUp, + onMouseLeave: this.handleMouseLeave, + }; const classes = classnames(theme.button, [theme[shape]], { [theme[level]]: neutral, @@ -110,21 +114,24 @@ const factory = (ripple, FontIcon) => { const props = { ...others, + ...mouseEvents, href, ref: (node) => { this.buttonNode = node; }, className: classes, disabled: this.props.disabled, - onMouseUp: this.handleMouseUp, - onMouseLeave: this.handleMouseLeave, type: !href ? type : null, 'data-react-toolbox': 'button', }; - return React.createElement(element, props, + const buttonElement = React.createElement(element, props, icon ? : null, label, children, ); + + return others.onMouseEnter && this.props.disabled + ? {buttonElement} + : buttonElement; } } diff --git a/components/checkbox/config.css b/components/checkbox/config.css index fe33d1e8..7c3dff5a 100644 --- a/components/checkbox/config.css +++ b/components/checkbox/config.css @@ -8,6 +8,7 @@ --checkbox-focus-color: color(var(--color-black) a(1%)); --checkbox-focus-size: calc(var(--checkbox-size) * 2.3); --checkbox-text-color: var(--color-black); + --checkbox-border-color: var(--palette-grey-600); --checkbox-text-font-size: var(--font-size-small); --checkbox-total-height: calc(1.8 * var(--unit)); --checkbox-transition-duration: 0.2s; diff --git a/components/checkbox/readme.md b/components/checkbox/readme.md index 5f7e21f6..cb22eef5 100644 --- a/components/checkbox/readme.md +++ b/components/checkbox/readme.md @@ -47,7 +47,7 @@ If you want to provide a theme via context, the component key is `RTCheckbox`. | `children` | `String`, `Element` or `Array` | | Children to pass through the component. | | `className` | `String` | `''` | Sets a class to give customized styles to the checkbox field.| | `disabled` | `Boolean` | `false` | If true, the checkbox shown as disabled and cannot be modified.| -| `label` | `String` of `node` | | Text label to attach next to the checkbox element.| +| `label` | `String` or `node` | | Text label to attach next to the checkbox element.| | `name` | `String` | `false` | The name of the field to set in the input checkbox.| | `onBlur` | `Function` | | Callback called when the checkbox is blurred.| | `onChange` | `Function` | | Callback called when the checkbox value is changed.| diff --git a/components/checkbox/theme.css b/components/checkbox/theme.css index 748c0926..5ab7609c 100644 --- a/components/checkbox/theme.css +++ b/components/checkbox/theme.css @@ -57,7 +57,7 @@ } .check { - border-color: var(--checkbox-text-color); + border-color: var(--checkbox-border-color); border-radius: 2px; border-style: solid; border-width: 2px; diff --git a/components/drawer/Drawer.d.ts b/components/drawer/Drawer.d.ts index 37cd30d1..6ae297e4 100644 --- a/components/drawer/Drawer.d.ts +++ b/components/drawer/Drawer.d.ts @@ -28,7 +28,7 @@ export interface DrawerTheme { wrapper?: string; } -export interface DrawerProps extends ReactToolbox.Props { +export interface DrawerCommonProps { /** * If true, the drawer will be visible. * @default false @@ -47,10 +47,6 @@ export interface DrawerProps extends ReactToolbox.Props { * Callback function to be invoked when the overlay is clicked. */ onOverlayClick?: Function; - /** - * Classnames object defining the component style. - */ - theme?: DrawerTheme; /** * Type of drawer. It can be left or right to display the drawer on the left or right side of the screen. * @default left @@ -63,6 +59,13 @@ export interface DrawerProps extends ReactToolbox.Props { withOverlay?: boolean; } +export interface DrawerProps extends ReactToolbox.Props, DrawerCommonProps { + /** + * Classnames object defining the component style. + */ + theme?: DrawerTheme; +} + export class Drawer extends React.Component { } export default Drawer; diff --git a/components/dropdown/Dropdown.d.ts b/components/dropdown/Dropdown.d.ts index 4d14eeb7..3ed67817 100644 --- a/components/dropdown/Dropdown.d.ts +++ b/components/dropdown/Dropdown.d.ts @@ -30,10 +30,6 @@ export interface DropdownTheme { * Used for the the label element. */ label?: string; - /** - * Used for setting the label from source - */ - labelKey?: string; /** * Used when dropdown has required attribute. */ @@ -58,10 +54,6 @@ export interface DropdownTheme { * Used for the list of values. */ values?: string; - /** - * Used for setting the value from source - */ - valueKey: string; } export interface DropdownProps extends ReactToolbox.Props { @@ -88,6 +80,10 @@ export interface DropdownProps extends ReactToolbox.Props { * The text string to use for the floating label element. */ label?: string; + /** + * Used for setting the label from source + */ + labelKey?: string; /** * Name for the input field. */ @@ -104,6 +100,11 @@ export interface DropdownProps extends ReactToolbox.Props { * Callback function that is fired when the component is focused. */ onFocus?: Function; + /** + * If true, the dropdown has a required attribute. + * @default false + */ + required?: boolean; /** * Array of data objects with the data to represent in the dropdown. */ @@ -121,10 +122,9 @@ export interface DropdownProps extends ReactToolbox.Props { */ value?: string | number; /** - * If true, the dropdown has a required attribute. - * @default false + * Used for setting the value from source */ - required?: boolean; + valueKey?: string; } export class Dropdown extends React.Component { } diff --git a/components/hoc/Portal.js b/components/hoc/Portal.js index f1ca7273..1a9a5357 100644 --- a/components/hoc/Portal.js +++ b/components/hoc/Portal.js @@ -1,13 +1,14 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import ReactDOM from 'react-dom'; +import styleShape from 'react-style-proptype'; class Portal extends Component { static propTypes = { children: PropTypes.node, className: PropTypes.string, container: PropTypes.node, - style: PropTypes.style, + style: styleShape, } static defaultProps = { diff --git a/components/input/Input.d.ts b/components/input/Input.d.ts index 6bddadc5..dc12e0fc 100644 --- a/components/input/Input.d.ts +++ b/components/input/Input.d.ts @@ -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. */ diff --git a/components/input/config.css b/components/input/config.css index 58e389e5..5916deef 100644 --- a/components/input/config.css +++ b/components/input/config.css @@ -6,8 +6,9 @@ --input-label-font-size: calc(1.2 * var(--unit)); --input-focus-label-top: calc(0.6 * var(--unit)); --input-text-background-color: transparent; - --input-text-label-color: color(var(--color-black) a(26%)); - --input-text-bottom-border-color: color(var(--color-black) a(12%)); + --input-text-label-color: color(var(--color-text) a(26%)); + --input-text-input-element-color: var(--color-text); + --input-text-bottom-border-color: color(var(--color-text) a(12%)); --input-text-highlight-color: var(--color-primary); --input-text-disabled-color: var(--input-text-bottom-border-color); --input-text-disabled-text-color: var(--input-text-label-color); diff --git a/components/input/readme.md b/components/input/readme.md index d5e4a998..5130c41e 100644 --- a/components/input/readme.md +++ b/components/input/readme.md @@ -71,7 +71,7 @@ If you want to provide a theme via context, the component key is `RTInput`. ## Methods -The `Input` component has some imperative methods that are used as a bypass to the native rendered DOM element. To call this methods you will need to retrieve the instance of the component. Check the [Install](http://react-toolbox.com/#/install) section for details on how to do this. The methods included for the `Input` are: +The `Input` component has some imperative methods that are used as a bypass to the native rendered DOM element. To call this methods you will need to retrieve the instance of the component. Check the [Install](http://react-toolbox.io/#/install) section for details on how to do this. The methods included for the `Input` are: - `blur` used to blur the `input` element. - `focus` used to focus the `input` element. diff --git a/components/input/theme.css b/components/input/theme.css index a39cb874..700abbaf 100644 --- a/components/input/theme.css +++ b/components/input/theme.css @@ -34,13 +34,17 @@ border-radius: 0; border-right: 0; border-top: 0; - color: var(--color-text); + color: var(--input-text-input-element-color); display: block; font-size: var(--input-field-font-size); outline: none; padding: var(--input-field-padding) 0; width: 100%; + &:required { + box-shadow: none; + } + &:focus:not([disabled]):not([readonly]) { & ~ .bar::before, & ~ .bar::after { @@ -158,7 +162,7 @@ } .disabled > .inputElement { - border-bottom-style: dotted; + border-bottom-style: dashed; color: var(--input-text-disabled-text-color); } diff --git a/components/layout/Layout.d.ts b/components/layout/Layout.d.ts index 477b57b9..afc943e7 100644 --- a/components/layout/Layout.d.ts +++ b/components/layout/Layout.d.ts @@ -1,8 +1,5 @@ import * as React from "react"; import ReactToolbox from "../index"; -import { NavDrawer } from './NavDrawer'; -import { Panel } from './Panel'; -import { Sidebar } from './Sidebar'; export interface LayoutTheme { appbarFixed?: string; @@ -54,7 +51,7 @@ export interface LayoutProps extends ReactToolbox.Props { /** * Children to pass through the component. */ - children?: [NavDrawer | Panel | Sidebar]; + children?: JSX.Element | JSX.Element[]; /** * Classnames object defining the component style. */ diff --git a/components/layout/NavDrawer.d.ts b/components/layout/NavDrawer.d.ts index c6cb5650..16e78173 100644 --- a/components/layout/NavDrawer.d.ts +++ b/components/layout/NavDrawer.d.ts @@ -1,5 +1,5 @@ import * as React from "react"; -import { DrawerProps } from '../drawer/Drawer'; +import { DrawerCommonProps } from '../drawer/Drawer'; export interface NavDrawerTheme { /** @@ -12,7 +12,7 @@ export interface NavDrawerTheme { clipped?: string; } -export interface NavDrawerProps extends DrawerProps { +export interface NavDrawerProps extends DrawerCommonProps { /** * If true, the drawer will be shown as an overlay. * @default false diff --git a/components/layout/Sidebar.d.ts b/components/layout/Sidebar.d.ts index 56d2075c..e8c2a5b6 100644 --- a/components/layout/Sidebar.d.ts +++ b/components/layout/Sidebar.d.ts @@ -1,5 +1,5 @@ import * as React from "react"; -import { DrawerProps } from '../drawer/Drawer'; +import { DrawerCommonProps } from '../drawer/Drawer'; export interface SidebarTheme { /** @@ -12,7 +12,7 @@ export interface SidebarTheme { pinned?: string; } -export interface SidebarProps extends DrawerProps { +export interface SidebarProps extends DrawerCommonProps { /** * If true, when the `AppBar` gets pinned, it will stand over the `Drawer`. * @default false diff --git a/components/list/ListItem.d.ts b/components/list/ListItem.d.ts index eb8cf066..c1e7739f 100644 --- a/components/list/ListItem.d.ts +++ b/components/list/ListItem.d.ts @@ -3,6 +3,7 @@ import ReactToolbox from '../index'; import { ListItemContentTheme } from './ListItemContent'; import { ListItemActionsTheme } from './ListItemActions'; import { ListItemLayoutProps, ListItemLayoutTheme } from './ListItemLayout'; +import { ListItemTextTheme } from './ListItemText'; export interface ListItemTheme { /** @@ -29,7 +30,7 @@ export interface ListItemProps extends ReactToolbox.Props { * Classnames object defining the component style. * @default false */ - theme?: ListItemTheme & ListItemActionsTheme & ListItemContentTheme & ListItemLayoutTheme; + theme?: ListItemTheme & ListItemActionsTheme & ListItemContentTheme & ListItemLayoutTheme & ListItemTextTheme; /** * In case you want to provide the item as a link, you can pass this property to specify the href. */ diff --git a/components/list/readme.md b/components/list/readme.md index 54b5a1ac..804fb7e4 100644 --- a/components/list/readme.md +++ b/components/list/readme.md @@ -71,7 +71,7 @@ Represents a list item that can have avatar, icons, title, subtitle, etc. Note: | `leftActions` | `Array of Elements` | | A list of elements that are placed on the left side of the item and after the avatar attribute.| | `leftIcon` | `String` or `Element` | | A string key of a font icon or element to display an icon in the left side of the item. | | `legend` | `String` or `Element` | | Secondary text to display under the caption.| -| `onClick` | `Function` | | Callback the is invoked when the item is clicked if it's not disabled. | +| `onClick` | `Function` | | Callback that is invoked when the item is clicked if it's not disabled. | | `rightIcon` | `String` or `Element` | | The same as the `leftIcon` but in this case the icon is displayed in the right side.| | `rightActions` | `Array of Elements` | | A list of elements that are placed on the right side of the item and after the rightIcon attribute.| | `ripple` | `Boolean` | `false` | If true, the item displays a ripple effect on click. By default it's inherited from the parent element.| diff --git a/components/list/theme.css b/components/list/theme.css index 862ff19e..cce1de5b 100644 --- a/components/list/theme.css +++ b/components/list/theme.css @@ -64,6 +64,9 @@ min-height: var(--list-item-min-height); padding: 0 var(--list-horizontal-padding); position: relative; + transition-duration: 0.28s; + transition-property: background-color; + transition-timing-function: var(--animation-curve-default); &.selectable:not(.disabled):hover { background-color: var(--list-item-hover-color); diff --git a/components/menu/MenuItem.d.ts b/components/menu/MenuItem.d.ts index 265f0576..325e8505 100644 --- a/components/menu/MenuItem.d.ts +++ b/components/menu/MenuItem.d.ts @@ -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 { } diff --git a/components/radio/readme.md b/components/radio/readme.md index 78f8df4f..78120b34 100644 --- a/components/radio/readme.md +++ b/components/radio/readme.md @@ -56,7 +56,7 @@ The inner component to compose radio selectors. They will be rendered as radio i | `checked` | `Boolean` | `false` | If true, the input element will be selected by default. Transferred from the parent. | | `className` | `String` | `''` | Set a class to give custom styles to the radio button.| | `disabled` | `Boolean` | `false` | If true, the item will be displayed as disabled.| -| `label` | `String` of `node` | `''` | Label for the radio button.| +| `label` | `String` or `node` | `''` | Label for the radio button.| | `name` | `String` | | Name for the input element. | | `onBlur` | `Function` | | Callback function that will be invoked when the input is blurred. | | `onChange` | `Function` | | Callback function that will be invoked when the value changes. | diff --git a/components/snackbar/Snackbar.d.ts b/components/snackbar/Snackbar.d.ts index 9286938d..a3d40cca 100644 --- a/components/snackbar/Snackbar.d.ts +++ b/components/snackbar/Snackbar.d.ts @@ -49,7 +49,7 @@ export interface SnackbarProps extends ReactToolbox.Props { /** * Text to display in the content. */ - label?: string; + label?: string | JSX.Element; /** * Callback function that will be called when the button action is clicked. */ diff --git a/components/table/theme.css b/components/table/theme.css index 985380d6..e73c23a9 100644 --- a/components/table/theme.css +++ b/components/table/theme.css @@ -40,7 +40,8 @@ transition-property: background-color; transition-timing-function: var(--animation-curve-default); - &:hover { background-color: var(--table-hover-color); } + &:hover, + &.selected:hover { background-color: var(--table-hover-color); } &.selected { background-color: var(--table-selection-color); } } diff --git a/components/tabs/Tab.d.ts b/components/tabs/Tab.d.ts index c7cf99b2..59c1e027 100644 --- a/components/tabs/Tab.d.ts +++ b/components/tabs/Tab.d.ts @@ -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. */ diff --git a/components/tabs/Tabs.js b/components/tabs/Tabs.js index 603c6799..16abf525 100644 --- a/components/tabs/Tabs.js +++ b/components/tabs/Tabs.js @@ -59,6 +59,8 @@ const factory = (Tab, TabContent, FontIcon) => { if (index !== prevIndex || children !== prevChildren) { this.updatePointer(index); } + + this.updateArrows(); } componentWillUnmount() { @@ -83,7 +85,7 @@ const factory = (Tab, TabContent, FontIcon) => { updatePointer = (idx) => { if (this.navigationNode && this.navigationNode.children[idx]) { - this.updatePointerAnimationFrame = requestAnimationFrame(() => { + this.updatePointerAnimationFrame = window.requestAnimationFrame(() => { const nav = this.navigationNode.getBoundingClientRect(); const label = this.navigationNode.children[idx].getBoundingClientRect(); const scrollLeft = this.navigationNode.scrollLeft; @@ -105,13 +107,18 @@ const factory = (Tab, TabContent, FontIcon) => { const scrollLeft = this.navigationNode.scrollLeft; const nav = this.navigationNode.getBoundingClientRect(); const lastLabel = this.navigationNode.children[idx].getBoundingClientRect(); + const left = scrollLeft > 0; + const right = nav.right < (lastLabel.right - 5); + const { left: prevLeft, right: prevRight } = this.state.arrows; - this.setState({ - arrows: { - left: scrollLeft > 0, - right: nav.right < (lastLabel.right - 5), - }, - }); + if (left !== prevLeft || right !== prevRight) { + this.setState({ + arrows: { + left, + right, + }, + }); + } } } diff --git a/components/tooltip/index.d.ts b/components/tooltip/index.d.ts index 3b4cfae1..ad93abab 100644 --- a/components/tooltip/index.d.ts +++ b/components/tooltip/index.d.ts @@ -70,10 +70,21 @@ declare class TooltipComponent extends React.Component { props: P & TooltipProps; } -interface TooltippedComponentClass

extends TooltipProps { +declare interface TooltippedComponentClass

extends TooltipProps { new (props?: P, context?: any): TooltipComponent; } -export function Tooltip

(componentClass: React.ComponentClass

): TooltippedComponentClass

; +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

= (componentClass: React.ComponentClass

) => TooltippedComponentClass

+ +export function tooltipFactory

(options?: TooltipOptions): tooltipHOC

; + +export default function Tooltip

(component: React.ReactType): TooltippedComponentClass

; diff --git a/components/tooltip/readme.md b/components/tooltip/readme.md index 98c4e3a3..f790bae3 100644 --- a/components/tooltip/readme.md +++ b/components/tooltip/readme.md @@ -5,8 +5,9 @@ A Tooltip is useful to show information on hover in any kind of component. We ha ```jsx import Button from 'react-toolbox/lib/button'; -import Tooltip from 'react-toolbox/lib/tooltip'; +import Input from 'react-toolbox/lib/input'; import Link from 'react-toolbox/lib/link'; +import Tooltip from 'react-toolbox/lib/tooltip'; const TooltipButton = Tooltip(Button); const TooltipInput = Tooltip(Input); diff --git a/docs/app/components/layout/main/modules/examples/input_example_1.txt b/docs/app/components/layout/main/modules/examples/input_example_1.txt index c16db922..89865b2a 100644 --- a/docs/app/components/layout/main/modules/examples/input_example_1.txt +++ b/docs/app/components/layout/main/modules/examples/input_example_1.txt @@ -1,5 +1,5 @@ class InputTest extends React.Component { - state = { name: '', phone: '', multiline: '', email: '', hint: '', label: '' }; + state = { name: '', phone: '', multiline: '', email: '', hint: '', label: '', error: '' }; handleChange = (value, ev) => { this.setState({[ev.target.name]: value}); @@ -16,7 +16,7 @@ class InputTest extends React.Component { {/* Just an example. Defining functions in a property, such as onClick, is a bad idea: */} - Error!! { e.preventDefault(); console.log('some help'); }}>?} /> + Error!! { e.preventDefault(); console.log('some help'); }}>?} /> ); } diff --git a/docs/www/index.html b/docs/www/index.html index a875ef4b..404bc941 100644 --- a/docs/www/index.html +++ b/docs/www/index.html @@ -15,18 +15,18 @@ - + - + - + diff --git a/docs/www/other/CNAME b/docs/www/other/CNAME index 4c40b7bf..ab3068c5 100644 --- a/docs/www/other/CNAME +++ b/docs/www/other/CNAME @@ -1 +1 @@ -react-toolbox.com +react-toolbox.io diff --git a/package.json b/package.json index 4081c22d..dec1a98a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "react-toolbox", "description": "A set of React components implementing Google's Material Design specification with the power of CSS Modules.", - "homepage": "http://www.react-toolbox.com", + "homepage": "http://www.react-toolbox.io", "version": "2.0.0-beta.11", "main": "./lib", "module": "./components", @@ -15,7 +15,7 @@ "url": "git+https://github.com/react-toolbox/react-toolbox.git" }, "bugs": { - "email": "issues@react-toolbox.com", + "email": "issues@react-toolbox.io", "url": "https://github.com/react-toolbox/react-toolbox/issues" }, "keywords": [ @@ -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,10 +88,12 @@ "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" @@ -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" }, diff --git a/spec/components/input.js b/spec/components/input.js index d3e40c41..52e67e99 100644 --- a/spec/components/input.js +++ b/spec/components/input.js @@ -30,7 +30,7 @@ class InputTest extends React.Component { /> - + diff --git a/spec/components/tooltip.js b/spec/components/tooltip.js index 691df86e..456c8862 100644 --- a/spec/components/tooltip.js +++ b/spec/components/tooltip.js @@ -20,6 +20,7 @@ const TooltipTest = () => (

Tooltip

Give information on :hover

+ diff --git a/spec/root.js b/spec/root.js index a0aa44f4..11b8eabd 100644 --- a/spec/root.js +++ b/spec/root.js @@ -52,7 +52,7 @@ class Root extends Component { > = () => ( +
+
AppBar
+
+ +
+ +
+ +
+ + Custom content + +
+ +
+) + +export default AppBarTest; diff --git a/spec/ts/autocomplete.tsx b/spec/ts/autocomplete.tsx new file mode 100644 index 00000000..edcfc42e --- /dev/null +++ b/spec/ts/autocomplete.tsx @@ -0,0 +1,96 @@ +import * as React from 'react'; +import Autocomplete from 'components/autocomplete'; + +class AutocompleteTest extends React.Component { + 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) => { + 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 ( +
+
Autocomplete
+

You can have a multiple or simple autocomplete.

+ + + + + + + + +
+ ); + } +} + +export default AutocompleteTest; diff --git a/spec/ts/avatar.tsx b/spec/ts/avatar.tsx new file mode 100644 index 00000000..87dfab0e --- /dev/null +++ b/spec/ts/avatar.tsx @@ -0,0 +1,22 @@ +import * as React from 'react'; +import Avatar from '../../components/avatar'; +import GithubIcon from './github_icon'; + +const AvatarTest = () => ( +
+
Avatars
+

Provide an image source or object, a font icon, children or a title to use its first letter.

+ + } /> + foobar + + + + +
+); + +export default AvatarTest; diff --git a/spec/ts/button.tsx b/spec/ts/button.tsx new file mode 100644 index 00000000..9a7c51ac --- /dev/null +++ b/spec/ts/button.tsx @@ -0,0 +1,51 @@ +import * as React from 'react'; +import GithubIcon from './github_icon'; +import { Button, IconButton, BrowseButton } from '../../components/button'; + +const ButtonTest = () => ( +
+
Buttons
+

lorem ipsum...

+ + +
+); + +function rippleEnded() { + console.log('Ripple animation ended!'); +} + +export default ButtonTest; diff --git a/spec/ts/card.tsx b/spec/ts/card.tsx new file mode 100644 index 00000000..a119f7aa --- /dev/null +++ b/spec/ts/card.tsx @@ -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 = () =>
; +const CardList: React.SFC = ({ children }) =>
    {children}
; +const CardListItem: React.SFC = ({ component, name }) => ( +
  • +
    {component}
    +
    {name}
    +
  • +); + +const cards: any = { + basic: [{ + name: 'Basic Card', + component: ( + + + {dummyText} + +