diff --git a/.npmignore b/.npmignore index bf5fcafcb..2f26e1a02 100644 --- a/.npmignore +++ b/.npmignore @@ -51,3 +51,6 @@ CssMigrationWebpackPlugin.js .babelrc .prettierignore .eslintignore +/docs +.idea +yarn.lock diff --git a/docs/src/routes/linear-progress/sample.txt b/docs/src/routes/linear-progress/sample.txt index 72535cc65..caad3de3a 100644 --- a/docs/src/routes/linear-progress/sample.txt +++ b/docs/src/routes/linear-progress/sample.txt @@ -6,7 +6,7 @@ export default class SnackbarPage extends Component { render(){ return (
- +
); } diff --git a/package-lock.json b/package-lock.json index 8a8f9873f..11bcf1590 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "preact-material-components", - "version": "1.5.1-alpha3", + "version": "1.5.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1994,7 +1994,6 @@ "version": "7.0.0-beta.56", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0-beta.56.tgz", "integrity": "sha512-vP9XV2VP013UEyZdU9eWClCsm6rQPUYHVNCfmpcv5uKviW7mKmUZq71Y5cr5dYsFKfnGDxSo8h6plUGR60lwHg==", - "dev": true, "requires": { "regenerator-runtime": "^0.12.0" }, @@ -2002,8 +2001,7 @@ "regenerator-runtime": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", - "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==", - "dev": true + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" } } }, @@ -5616,12 +5614,12 @@ } }, "eslint-config-prettier": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz", - "integrity": "sha512-ag8YEyBXsm3nmOv1Hz991VtNNDMRa+MNy8cY47Pl4bw6iuzqKbJajXdqUpiw13STdLLrznxgm1hj9NhxeOYq0A==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-3.0.1.tgz", + "integrity": "sha512-vA0TB8HCx/idHXfKHYcg9J98p0Q8nkfNwNAoP7e+ywUidn6ScaFS5iqncZAHPz+/a0A/tp657ulFHFx/2JDP4Q==", "dev": true, "requires": { - "get-stdin": "^5.0.1" + "get-stdin": "^6.0.0" } }, "eslint-plugin-prettier": { @@ -6160,14 +6158,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6182,20 +6178,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -6312,8 +6305,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -6325,7 +6317,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6340,7 +6331,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6348,14 +6338,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -6374,7 +6362,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -6455,8 +6442,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -6468,7 +6454,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -6590,7 +6575,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6693,9 +6677,9 @@ "dev": true }, "get-stdin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", - "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", "dev": true }, "get-stream": { diff --git a/package.json b/package.json index 23703a0f4..3dab16f6b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "preact-material-components", - "version": "1.5.1-alpha3", + "version": "1.5.1", "description": "preact wrapper for \"Material Components for the web\"", "module": "index.js", "main": "dist", diff --git a/ts/Base/MaterialComponent.ts b/ts/Base/MaterialComponent.ts index 78e515361..019c88246 100644 --- a/ts/Base/MaterialComponent.ts +++ b/ts/Base/MaterialComponent.ts @@ -1,7 +1,8 @@ +import MDCComponent from '@material/base/component'; import {MDCRipple} from '@material/ripple'; import autobind from 'autobind-decorator'; import {Component, VNode} from 'preact'; -import {OmitAttrs} from './types'; +import {SoftMerge} from './types'; export interface IMaterialComponentOwnProps { ripple?: boolean; @@ -9,11 +10,15 @@ export interface IMaterialComponentOwnProps { export interface IMaterialComponentOwnState {} -type MaterialComponentProps = PropType & - IMaterialComponentOwnProps & - OmitAttrs; +export type MaterialComponentProps = SoftMerge< + PropType & IMaterialComponentOwnProps, + JSX.HTMLAttributes +>; -type MaterialComponentState = StateType & IMaterialComponentOwnState; +export type MaterialComponentState = StateType & + IMaterialComponentOwnState; + +const doNotRemoveProps = ['disabled']; /** * Base class for every Material component in this package @@ -38,15 +43,23 @@ export abstract class MaterialComponent< /** This will again be used to add apt classname to the component */ protected abstract componentName: string; + /** + * Props of which change the MDComponent will be informed. + * Override to use. + * When used do not forget to include this.afterComponentDidMount() at the end of your componentDidMount function. + * Requires this.MDComponent to be defined. + */ + protected mdcNotifyProps?: string[]; + /** The final class name given to the dom */ protected classText?: string | null; protected ripple?: MDCRipple | null; - protected control?: Element; + protected MDComponent?: MDCComponent; public render(props): VNode { if (!this.classText) { - this.classText = this.buildClassName(); + this.classText = this.buildClassName(props); } // Fetch a VNode const componentProps = props; @@ -75,6 +88,10 @@ export abstract class MaterialComponent< .join(' '); // Clean this shit of proxy attributes this.mdcProps.forEach(prop => { + // TODO: Fix this better + if (prop in doNotRemoveProps) { + return; + } delete element.attributes[prop]; }); return element; @@ -87,12 +104,37 @@ export abstract class MaterialComponent< } } + public componentWillUpdate(nextProps: MaterialComponentProps) { + if (this.MDComponent && this.mdcNotifyProps) { + for (const prop of this.mdcNotifyProps) { + if (this.props[prop] !== nextProps[prop]) { + this.MDComponent[prop] = nextProps[prop]; + } + } + } + for (const prop of this.mdcProps) { + if (this.props[prop] !== nextProps[prop]) { + this.classText = this.buildClassName(nextProps); + break; + } + } + } + public componentWillUnmount() { if (this.ripple) { this.ripple.destroy(); } } + @autobind + protected afterComponentDidMount() { + if (this.MDComponent && this.mdcNotifyProps) { + for (const prop of this.mdcNotifyProps) { + this.MDComponent[prop] = this.props[prop]; + } + } + } + // Shared setter for the root element ref @autobind protected setControlRef(control?: Element) { @@ -101,14 +143,14 @@ export abstract class MaterialComponent< /** Build the className based on component names and mdc props */ @autobind - protected buildClassName() { + protected buildClassName(props: MaterialComponentProps) { // Class name based on component name let classText = 'mdc-' + this.componentName; // Loop over mdcProps to turn them into classNames - for (const propKey in this.props) { - if (this.props.hasOwnProperty(propKey)) { - const prop = this.props[propKey]; + for (const propKey in props) { + if (props.hasOwnProperty(propKey)) { + const prop = props[propKey]; if (typeof prop === 'boolean' && prop) { if (this.mdcProps.indexOf(propKey) !== -1) { classText += ` mdc-${this.componentName}--${propKey}`; diff --git a/ts/Base/types.ts b/ts/Base/types.ts index 578702c21..2c6d7ae6b 100644 --- a/ts/Base/types.ts +++ b/ts/Base/types.ts @@ -1,11 +1,18 @@ -export type Diff< - T extends string | number | symbol, - U extends string | number | symbol -> = ({[P in T]: P} & {[P in U]: never} & {[x: string]: never})[T]; - -export type Omit = Pick>; - +/** + * Excludes all keys of the first type, that are also on the second type + * + * Example: + * type X = OmitAttrs<{b: () => void, c: any}, {a: number, b: string}>; // {c: any} + */ export type OmitAttrs< T extends {[attr: string]: any}, O extends {[attr: string]: any} -> = Pick>; +> = Pick>; + +/** + * Merge two types and any keys that are also in the first get deleted in the second + * + * Example: + * type Y = SoftMerge<{a: number, b: string}, {b: () => void, c: any}>; // {a: number, b: string, c: any} + */ +export type SoftMerge = A & OmitAttrs; diff --git a/ts/Checkbox/index.tsx b/ts/Checkbox/index.tsx index 356914f77..21eb4419b 100644 --- a/ts/Checkbox/index.tsx +++ b/ts/Checkbox/index.tsx @@ -27,13 +27,14 @@ export class Checkbox extends MaterialComponent< protected componentName = 'checkbox'; protected mdcProps = ['disabled']; protected MDComponent?: MDCCheckbox; + protected mdcNotifyProps = ['checked', 'indeterminate', 'disabled']; public componentDidMount() { super.componentDidMount(); if (this.control) { this.MDComponent = new MDCCheckbox(this.control); - toggleCheckbox(defaultProps, this.props, this.MDComponent); } + this.afterComponentDidMount(); } public componentWillUnmount() { @@ -43,10 +44,6 @@ export class Checkbox extends MaterialComponent< } } - public componentWillUpdate(nextProps) { - toggleCheckbox(this.props, nextProps, this.MDComponent); - } - @autobind protected materialDom(allprops) { return ( @@ -76,25 +73,4 @@ export class Checkbox extends MaterialComponent< } } -/* - * Function to add declarative opening/closing to drawer - */ -function toggleCheckbox(oldprops, newprops, cbox) { - if ( - 'checked' in oldprops && - 'checked' in newprops && - oldprops.checked !== newprops.checked - ) { - cbox.checked = newprops.checked; - } - - if ( - 'indeterminate' in oldprops && - 'indeterminate' in newprops && - oldprops.indeterminate !== newprops.indeterminate - ) { - cbox.indeterminate = newprops.indeterminate; - } -} - export default Checkbox; diff --git a/ts/Drawer/index.tsx b/ts/Drawer/index.tsx index 9fce2f85b..5e7aa69f0 100644 --- a/ts/Drawer/index.tsx +++ b/ts/Drawer/index.tsx @@ -16,13 +16,6 @@ export interface ITemporaryDrawerProps extends IDrawerProps {} export interface ITemporaryDrawerState extends IDrawerState {} -/** - * Default props for drawers - */ -const defaultProps = { - open: false -}; - export class TemporaryDrawer extends MaterialComponent< ITemporaryDrawerProps, ITemporaryDrawerState @@ -30,6 +23,7 @@ export class TemporaryDrawer extends MaterialComponent< protected componentName = 'drawer--temporary'; protected mdcProps = []; protected MDComponent?: MDCTemporaryDrawer; + protected mdcNotifyProps = ['open']; public componentDidMount() { super.componentDidMount(); @@ -37,8 +31,8 @@ export class TemporaryDrawer extends MaterialComponent< this.MDComponent = new MDCTemporaryDrawer(this.control); this.MDComponent.listen('MDCTemporaryDrawer:open', this.open); this.MDComponent.listen('MDCTemporaryDrawer:close', this.close); - toggleDrawer(defaultProps, this.props, this.MDComponent); } + this.afterComponentDidMount(); } public componentWillUnmount() { @@ -50,10 +44,6 @@ export class TemporaryDrawer extends MaterialComponent< } } - public componentWillUpdate(nextProps) { - toggleDrawer(this.props, nextProps, this.MDComponent); - } - @autobind protected open(e) { if (this.props.onOpen) { @@ -123,6 +113,7 @@ export class PersistentDrawer extends MaterialComponent< protected componentName = 'drawer--persistent'; protected mdcProps = []; protected MDComponent?: MDCPersistentDrawer; + protected mdcNotifyProps = ['open']; public componentDidMount() { super.componentDidMount(); @@ -130,7 +121,6 @@ export class PersistentDrawer extends MaterialComponent< this.MDComponent = new MDCPersistentDrawer(this.control); this.MDComponent.listen('MDCPersistentDrawer:open', this.open); this.MDComponent.listen('MDCPersistentDrawer:close', this.close); - toggleDrawer(defaultProps, this.props, this.MDComponent); } } @@ -141,10 +131,7 @@ export class PersistentDrawer extends MaterialComponent< this.MDComponent.unlisten('MDCPersistentDrawer:open', this.open); this.MDComponent.destroy(); } - } - - public componentWillUpdate(nextProps) { - toggleDrawer(this.props, nextProps, this.MDComponent); + this.afterComponentDidMount(); } @autobind @@ -243,19 +230,6 @@ export class DrawerItem extends ListLinkItem< } } -/** - * Function to add declarative opening/closing to drawer - */ -function toggleDrawer(oldprops, newprops, drawer) { - if ( - 'open' in oldprops && - 'open' in newprops && - oldprops.open !== newprops.open - ) { - drawer.open = newprops.open; - } -} - export class Drawer { public static readonly DrawerContent = DrawerContent; public static readonly DrawerHeader = DrawerHeader; diff --git a/ts/LinearProgress/index.tsx b/ts/LinearProgress/index.tsx index 73d1fac69..b928f6829 100644 --- a/ts/LinearProgress/index.tsx +++ b/ts/LinearProgress/index.tsx @@ -15,16 +15,31 @@ export class LinearProgress extends MaterialComponent< ILinearProgressProps, ILinearProgressState > { + public defaultProps = { + determinate: true + }; + protected componentName = 'linear-progress'; - protected mdcProps = ['indeterminate', 'reversed']; + protected mdcProps = ['reversed', 'indeterminate']; protected themeProps = ['primary', 'secondary']; protected MDComponent?: MDCLinearProgress; + protected mdcNotifyProps = ['progress']; public componentDidMount() { super.componentDidMount(); if (this.control) { this.MDComponent = new MDCLinearProgress(this.control); - updateProgress(this.props, this.MDComponent); + this.MDComponent.determinate = !this.props.indeterminate; + this.MDComponent.reverse = !!this.props.reversed; + } + this.afterComponentDidMount(); + } + + public componentWillUpdate(nextProps: ILinearProgressProps) { + super.componentWillUpdate(nextProps); + if (this.MDComponent) { + this.MDComponent.determinate = !this.props.indeterminate; + this.MDComponent.reverse = !!nextProps.reversed; } } @@ -35,10 +50,6 @@ export class LinearProgress extends MaterialComponent< } } - public componentWillUpdate(nextProps) { - updateProgress(nextProps, this.MDComponent); - } - @autobind protected materialDom(props) { // TODO: Fix theme props @@ -57,10 +68,4 @@ export class LinearProgress extends MaterialComponent< } } -function updateProgress(props, progressBar) { - if (!props.indeterminate && props.progress) { - progressBar.progress = props.progress; - } -} - export default LinearProgress; diff --git a/ts/Menu/index.tsx b/ts/Menu/index.tsx index ecc5135c2..7ce8c7c84 100644 --- a/ts/Menu/index.tsx +++ b/ts/Menu/index.tsx @@ -54,6 +54,7 @@ export class Menu extends MaterialComponent { 'open-from-bottom-right' ]; protected MDComponent?: MDCMenu; + protected mdcNotifyProps = ['open']; public componentDidMount() { super.componentDidMount(); @@ -61,8 +62,8 @@ export class Menu extends MaterialComponent { this.MDComponent = new MDCMenu(this.control); this.MDComponent.listen('MDCMenu:selected', this.select); this.MDComponent.listen('MDCMenu:cancel', this.cancel); - toggleMenu(Menu.defaultProps, this.props, this.MDComponent); } + this.afterComponentDidMount(); } public componentWillUnmount() { @@ -74,10 +75,6 @@ export class Menu extends MaterialComponent { } } - public componentWillUpdate(nextProps) { - toggleMenu(this.props, nextProps, this.MDComponent); - } - @autobind protected select(e) { if (this.props.onSelect) { @@ -113,17 +110,4 @@ export class Menu extends MaterialComponent { } } -/* - * Function to add declarative opening/closing to drawer - */ -function toggleMenu(oldprops, newprops, menu) { - if ( - 'open' in oldprops && - 'open' in newprops && - oldprops.open !== newprops.open - ) { - menu.open = newprops.open; - } -} - export default Menu; diff --git a/ts/Radio/index.tsx b/ts/Radio/index.tsx index 219eed534..ea376a382 100644 --- a/ts/Radio/index.tsx +++ b/ts/Radio/index.tsx @@ -14,19 +14,14 @@ export class Radio extends MaterialComponent { protected componentName = 'radio'; protected mdcProps = ['disabled']; protected MDComponent?: MDCRadio; + protected mdcNotifyProps = ['checked']; public componentDidMount() { super.componentDidMount(); if (this.control) { this.MDComponent = new MDCRadio(this.control); - toggleRadio( - { - checked: false - }, - this.props, - this.MDComponent - ); } + this.afterComponentDidMount(); } public componentWillUnmount() { @@ -36,10 +31,6 @@ export class Radio extends MaterialComponent { } } - public componentWillUpdate(nextProps) { - toggleRadio(this.props, nextProps, this.MDComponent); - } - @autobind protected materialDom(allprops) { const {className, ...props} = allprops; @@ -55,17 +46,4 @@ export class Radio extends MaterialComponent { } } -/* - * Function to add declarative checked to radio - */ -function toggleRadio(oldprops, newprops, radio) { - if ( - 'checked' in oldprops && - 'checked' in newprops && - oldprops.checked !== newprops.checked - ) { - radio.checked = newprops.checked; - } -} - export default Radio; diff --git a/ts/TabBar/index.tsx b/ts/TabBar/index.tsx index 5f1fd298c..56c44dea6 100644 --- a/ts/TabBar/index.tsx +++ b/ts/TabBar/index.tsx @@ -3,13 +3,6 @@ import autobind from 'autobind-decorator'; import {h} from 'preact'; import MaterialComponent from '../Base/MaterialComponent'; -/* - * Default props for tabs - */ -const defaultProps = { - activeTabIndex: 0 -}; - export interface ITabLabelProps {} export interface ITabLabelState {} export class TabLabel extends MaterialComponent< @@ -44,10 +37,13 @@ export class TabIcon extends MaterialComponent { export interface ITabProps { active?: boolean; } + export interface ITabState {} + export class Tab extends MaterialComponent { protected componentName = 'tab'; protected mdcProps = ['active']; + protected mdcNotifyProps = ['active']; @autobind protected materialDom(props) { @@ -72,24 +68,7 @@ export interface ITabsProps { export interface ITabsState {} -/* - * Function to add declarative opening/closing to drawer - */ -function setActiveTabIndex( - oldprops: ITabsProps, - newprops: ITabsProps, - tabs: MDCTabBar -) { - if ( - oldprops.activeTabIndex && - newprops.activeTabIndex && - oldprops.activeTabIndex !== newprops.activeTabIndex - ) { - tabs.activeTabIndex = newprops.activeTabIndex; - } -} - -export class Tabs extends MaterialComponent { +export class TabBar extends MaterialComponent { public static readonly Tab = Tab; public static readonly TabLabel = TabLabel; public static readonly TabIcon = TabIcon; @@ -97,13 +76,14 @@ export class Tabs extends MaterialComponent { protected componentName = 'tab-bar'; protected mdcProps = []; protected MDComponent?: MDCTabBar; + protected mdcNotifyProps = ['activeTabIndex']; public componentDidMount() { super.componentDidMount(); if (this.control) { this.MDComponent = new MDCTabBar(this.control); - setActiveTabIndex(defaultProps, this.props, this.MDComponent); } + this.afterComponentDidMount(); } public componentWillUnmount() { @@ -113,12 +93,6 @@ export class Tabs extends MaterialComponent { } } - public componentWillUpdate(nextProps) { - if (this.MDComponent) { - setActiveTabIndex(this.props, nextProps, this.MDComponent); - } - } - @autobind protected materialDom(props) { return ( @@ -133,4 +107,4 @@ export class Tabs extends MaterialComponent { } } -export default Tabs; +export default TabBar; diff --git a/ts/Tabs/index.tsx b/ts/Tabs/index.tsx index 1f466702f..94be3b1c3 100644 --- a/ts/Tabs/index.tsx +++ b/ts/Tabs/index.tsx @@ -178,13 +178,14 @@ export class Tabs extends MaterialComponent { protected componentName = 'tab-bar'; protected mdcProps = ['icon-tab-bar', 'icons-with-text']; protected MDComponent?: MDCTabBar; + protected mdcNotifyProps = ['activeTabIndex']; public componentDidMount() { super.componentDidMount(); if (this.control) { this.MDComponent = new MDCTabBar(this.control); - setActiveTabIndex(defaultProps, this.props, this.MDComponent); } + this.afterComponentDidMount(); } public componentWillUnmount() { @@ -194,12 +195,6 @@ export class Tabs extends MaterialComponent { } } - public componentWillUpdate(nextProps) { - if (this.MDComponent) { - setActiveTabIndex(this.props, nextProps, this.MDComponent); - } - } - @autobind protected materialDom(props) { return ( diff --git a/ts/TextField/index.tsx b/ts/TextField/index.tsx index 65107a97d..1396d26f3 100644 --- a/ts/TextField/index.tsx +++ b/ts/TextField/index.tsx @@ -1,7 +1,10 @@ import {MDCTextField} from '@material/textfield'; import autobind from 'autobind-decorator'; import {Component, h} from 'preact'; -import MaterialComponent from '../Base/MaterialComponent'; +import MaterialComponent, { + MaterialComponentProps +} from '../Base/MaterialComponent'; +import {SoftMerge} from '../Base/types'; import Icon from '../Icon'; export interface IHelperTextProps { @@ -53,7 +56,9 @@ export interface ITextFieldInputProps { leadingIcon?: string; trailingIcon?: string; outerStyle?: {[key: string]: string}; - onInit: (c: MDCTextField) => any | void; + onInit?: (c: MDCTextField) => any | void; + valid?: boolean; + value?: string; } export interface ITextFieldInputState { @@ -83,6 +88,8 @@ export class TextFieldInput extends MaterialComponent< 'outlined' ]; + protected mdcNotifyProps = ['valid', 'disabled']; + public componentDidMount() { super.componentDidMount(); this.setState( @@ -95,16 +102,15 @@ export class TextFieldInput extends MaterialComponent< if (this.props.onInit) { this.props.onInit(this.MDComponent); } - setValid({valid: true}, this.props, this.MDComponent); + if (this.props.value) { + this.MDComponent.value = this.props.value; + } } + this.afterComponentDidMount(); } ); } - public componentWillUpdate(nextProps) { - setValid(this.props, nextProps, this.MDComponent); - } - public componentWillUnmount() { super.componentWillUnmount(); if (this.MDComponent) { @@ -173,6 +179,17 @@ export class TextFieldInput extends MaterialComponent< ); } + + @autobind + protected buildClassName( + props: MaterialComponentProps + ) { + let cn: string = super.buildClassName(props); + if (this.MDComponent) { + cn += ' mdc-text-field--upgraded'; + } + return cn; + } } type input_type = @@ -200,7 +217,7 @@ type input_type = | 'url' | 'week'; -export interface ITextFieldProps extends JSX.HTMLAttributes { +export interface ITextFieldProps { fullwidth?: boolean; textarea?: boolean; type?: input_type; @@ -216,13 +233,17 @@ export interface ITextFieldProps extends JSX.HTMLAttributes { leadingIcon?: string; // TODO: Add to docs trailingIcon?: string; // TODO: Add to docs outerStyle?: {[key: string]: string}; + value?: string; } export interface ITextFieldState { showFloatingLabel: boolean; } -export class TextField extends Component { +export class TextField extends Component< + SoftMerge, + ITextFieldState +> { public static readonly defaultProps = { outerStyle: {} }; @@ -299,14 +320,4 @@ export class TextField extends Component { } } -function setValid(oldprops, newprops, textfield) { - if ( - 'valid' in oldprops && - 'valid' in newprops && - oldprops.valid !== newprops.valid - ) { - textfield.valid = newprops.valid; - } -} - export default TextField;