From e79e14a7b8cb5bb48e9c75cb2faab6434b77dea3 Mon Sep 17 00:00:00 2001 From: James Brantly Date: Thu, 3 Sep 2015 23:07:28 -0400 Subject: [PATCH] Fixup the global definitions. Originally had renamed react-global.d.ts to react-namespace.d.ts. After thinking about it further I don't think a rename really benefits anyone and would just cause confusion with people trying to upgrade. Also I had missed the `.d` in the original rename. Additionally adding some tests for the global version since there were none. --- react/README.md | 2 +- react/react-global-tests.ts | 367 ++++++++++++++++++ .../{react-namespace.ts => react-global.d.ts} | 0 3 files changed, 368 insertions(+), 1 deletion(-) create mode 100644 react/react-global-tests.ts rename react/{react-namespace.ts => react-global.d.ts} (100%) diff --git a/react/README.md b/react/README.md index c17ccaebe0..b7ff4b55e6 100644 --- a/react/README.md +++ b/react/README.md @@ -2,4 +2,4 @@ This folder contains the following `.d.ts` files: * `react.d.ts` declares the module `"react"` and `"react/addons"` -* `react-namespace.d.ts` declares the global namespace `React` (only include this if you are actually using the global `React`) +* `react-global.d.ts` declares the global namespace `React` (only include this if you are actually using the global `React`) diff --git a/react/react-global-tests.ts b/react/react-global-tests.ts new file mode 100644 index 0000000000..a3f4a14849 --- /dev/null +++ b/react/react-global-tests.ts @@ -0,0 +1,367 @@ +/// + +interface Props extends React.Props { + hello: string; + world?: string; + foo: number; + bar: boolean; +} + +interface State { + inputValue?: string; + seconds?: number; +} + +interface Context { + someValue?: string; +} + +interface ChildContext { + someOtherValue: string; +} + +interface MyComponent extends React.Component { + reset(): void; +} + +var props: Props = { + key: 42, + ref: "myComponent42", + hello: "world", + foo: 42, + bar: true +}; + +var container: Element; + +// +// Top-Level API +// -------------------------------------------------------------------------- + +var ClassicComponent: React.ClassicComponentClass = + React.createClass({ + getDefaultProps() { + return { + hello: undefined, + world: "peace", + foo: undefined, + bar: undefined, + }; + }, + getInitialState() { + return { + inputValue: this.context.someValue, + seconds: this.props.foo + }; + }, + reset() { + this.replaceState(this.getInitialState()); + }, + render() { + return React.DOM.div(null, + React.DOM.input({ + ref: input => this._input = input, + value: this.state.inputValue + })); + } + }); + +class ModernComponent extends React.Component + implements React.ChildContextProvider { + + static propTypes: React.ValidationMap = { + foo: React.PropTypes.number + } + + static contextTypes: React.ValidationMap = { + someValue: React.PropTypes.string + } + + static childContextTypes: React.ValidationMap = { + someOtherValue: React.PropTypes.string + } + + context: Context; + + getChildContext() { + return { + someOtherValue: 'foo' + } + } + + state = { + inputValue: this.context.someValue, + seconds: this.props.foo + } + + reset() { + this.setState({ + inputValue: this.context.someValue, + seconds: this.props.foo + }); + } + + private _input: React.HTMLComponent; + + render() { + return React.DOM.div(null, + React.DOM.input({ + ref: input => this._input = input, + value: this.state.inputValue + })); + } +} + +// React.createFactory +var factory: React.Factory = + React.createFactory(ModernComponent); +var factoryElement: React.ReactElement = + factory(props); + +var classicFactory: React.ClassicFactory = + React.createFactory(ClassicComponent); +var classicFactoryElement: React.ClassicElement = + classicFactory(props); + +var domFactory: React.DOMFactory = + React.createFactory("foo"); +var domFactoryElement: React.DOMElement = + domFactory(); + +// React.createElement +var element: React.ReactElement = + React.createElement(ModernComponent, props); +var classicElement: React.ClassicElement = + React.createElement(ClassicComponent, props); +var domElement: React.HTMLElement = + React.createElement("div"); + +// React.cloneElement +var clonedElement: React.ReactElement = + React.cloneElement(element, props); +var clonedClassicElement: React.ClassicElement = + React.cloneElement(classicElement, props); +var clonedDOMElement: React.HTMLElement = + React.cloneElement(domElement); + +// React.render +var component: React.Component = + React.render(element, container); +var classicComponent: React.ClassicComponent = + React.render(classicElement, container); +var domComponent: React.DOMComponent = + React.render(domElement, container); + +// Other Top-Level API +var unmounted: boolean = React.unmountComponentAtNode(container); +var str: string = React.renderToString(element); +var markup: string = React.renderToStaticMarkup(element); +var notValid: boolean = React.isValidElement(props); // false +var isValid = React.isValidElement(element); // true +React.initializeTouchEvents(true); +var domNode: Element = React.findDOMNode(component); +domNode = React.findDOMNode(domNode); + +// +// React Elements +// -------------------------------------------------------------------------- + +var type = element.type; +var elementProps: Props = element.props; +var key = element.key; + +// +// React Components +// -------------------------------------------------------------------------- + +var displayName: string = ClassicComponent.displayName; +var defaultProps: Props = ClassicComponent.getDefaultProps(); +var propTypes: React.ValidationMap = ClassicComponent.propTypes; + +// +// Component API +// -------------------------------------------------------------------------- + +// modern +var componentState: State = component.state; +component.setState({ inputValue: "!!!" }); +component.forceUpdate(); + +// classic +var htmlElement: Element = classicComponent.getDOMNode(); +var divElement: HTMLDivElement = classicComponent.getDOMNode(); +var isMounted: boolean = classicComponent.isMounted(); +classicComponent.setProps(elementProps); +classicComponent.replaceProps(props); +classicComponent.replaceState({ inputValue: "???", seconds: 60 }); + +var myComponent = component; +myComponent.reset(); + +// +// Attributes +// -------------------------------------------------------------------------- + +var children: any[] = ["Hello world", [null], React.DOM.span(null)]; +var divStyle: React.CSSProperties = { // CSSProperties + flex: "1 1 main-size", + backgroundImage: "url('hello.png')" +}; +var htmlAttr: React.HTMLAttributes = { + key: 36, + ref: "htmlComponent", + children: children, + className: "test-attr", + style: divStyle, + onClick: (event: React.MouseEvent) => { + event.preventDefault(); + event.stopPropagation(); + }, + dangerouslySetInnerHTML: { + __html: "STRONG" + } +}; +React.DOM.div(htmlAttr); +React.DOM.span(htmlAttr); +React.DOM.input(htmlAttr); + +React.DOM.svg({ viewBox: "0 0 48 48" }, + React.DOM.rect({ + x: 22, + y: 10, + width: 4, + height: 28 + }), + React.DOM.rect({ + x: 10, + y: 22, + width: 28, + height: 4 + })); + + +// +// React.PropTypes +// -------------------------------------------------------------------------- + +var PropTypesSpecification: React.ComponentSpec = { + propTypes: { + optionalArray: React.PropTypes.array, + optionalBool: React.PropTypes.bool, + optionalFunc: React.PropTypes.func, + optionalNumber: React.PropTypes.number, + optionalObject: React.PropTypes.object, + optionalString: React.PropTypes.string, + optionalNode: React.PropTypes.node, + optionalElement: React.PropTypes.element, + optionalMessage: React.PropTypes.instanceOf(Date), + optionalEnum: React.PropTypes.oneOf(["News", "Photos"]), + optionalUnion: React.PropTypes.oneOfType([ + React.PropTypes.string, + React.PropTypes.number, + React.PropTypes.instanceOf(Date) + ]), + optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number), + optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number), + optionalObjectWithShape: React.PropTypes.shape({ + color: React.PropTypes.string, + fontSize: React.PropTypes.number + }), + requiredFunc: React.PropTypes.func.isRequired, + requiredAny: React.PropTypes.any.isRequired, + customProp: function(props: any, propName: string, componentName: string) { + if (!/matchme/.test(props[propName])) { + return new Error("Validation failed!"); + } + return null; + } + }, + render: (): React.ReactElement => { + return null; + } +}; + +// +// ContextTypes +// -------------------------------------------------------------------------- + +var ContextTypesSpecification: React.ComponentSpec = { + contextTypes: { + optionalArray: React.PropTypes.array, + optionalBool: React.PropTypes.bool, + optionalFunc: React.PropTypes.func, + optionalNumber: React.PropTypes.number, + optionalObject: React.PropTypes.object, + optionalString: React.PropTypes.string, + optionalNode: React.PropTypes.node, + optionalElement: React.PropTypes.element, + optionalMessage: React.PropTypes.instanceOf(Date), + optionalEnum: React.PropTypes.oneOf(["News", "Photos"]), + optionalUnion: React.PropTypes.oneOfType([ + React.PropTypes.string, + React.PropTypes.number, + React.PropTypes.instanceOf(Date) + ]), + optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number), + optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number), + optionalObjectWithShape: React.PropTypes.shape({ + color: React.PropTypes.string, + fontSize: React.PropTypes.number + }), + requiredFunc: React.PropTypes.func.isRequired, + requiredAny: React.PropTypes.any.isRequired, + customProp: function(props: any, propName: string, componentName: string) { + if (!/matchme/.test(props[propName])) { + return new Error("Validation failed!"); + } + return null; + } + }, + render: (): React.ReactElement => { + return null; + } +}; + +// +// React.Children +// -------------------------------------------------------------------------- + +var childMap: { [key: string]: number } = + React.Children.map(children, (child) => { return 42; }); +React.Children.forEach(children, (child) => {}); +var nChildren: number = React.Children.count(children); +var onlyChild = React.Children.only([null, [[["Hallo"], true]], false]); + +// +// Example from http://facebook.github.io/react/ +// -------------------------------------------------------------------------- + +interface TimerState { + secondsElapsed: number; +} +class Timer extends React.Component<{}, TimerState> { + state = { + secondsElapsed: 0 + } + private _interval: number; + tick() { + this.setState((prevState, props) => ({ + secondsElapsed: prevState.secondsElapsed + 1 + })); + } + componentDidMount() { + this._interval = setInterval(() => this.tick(), 1000); + } + componentWillUnmount() { + clearInterval(this._interval); + } + render() { + return React.DOM.div( + null, + "Seconds Elapsed: ", + this.state.secondsElapsed + ); + } +} +React.render(React.createElement(Timer), container); + diff --git a/react/react-namespace.ts b/react/react-global.d.ts similarity index 100% rename from react/react-namespace.ts rename to react/react-global.d.ts