├── src └── gwt │ └── react │ ├── todo_mvc │ ├── client │ │ ├── utils.java │ │ ├── Classnames.java │ │ ├── App.java │ │ ├── TodoModel.java │ │ ├── Footer.java │ │ ├── TodoItem.java │ │ └── TodoList.java │ └── todomvc.gwt.xml │ ├── api_sanity_test │ ├── client │ │ ├── ComponentDidCatchBadComponent.java │ │ ├── ComponentDidCatchExample.java │ │ ├── ChildApiTests.java │ │ ├── App.java │ │ └── StatefulExample.java │ └── apisanitytest.gwt.xml │ ├── widget_interop │ ├── client │ │ ├── ReactPanel.java │ │ ├── App.java │ │ └── StatefulExample.java │ └── widget_interop.gwt.xml │ ├── js_react_component_interop │ ├── jsReactComponentInterop.gwt.xml │ └── client │ │ ├── FineUploader.java │ │ └── App.java │ └── preact_sanity_test │ ├── preactsanitytest.gwt.xml │ └── client │ ├── ChildApiTests.java │ ├── App.java │ ├── StatefulExample2.java │ └── StatefulExample.java ├── web ├── WEB-INF │ └── web.xml ├── widgetInterop.html ├── todomvc.html ├── apiSanityTest.html ├── jsReactComponentInteropTest.html ├── preactSanityTest.html ├── css │ ├── base.css │ ├── gwt.css │ └── index.css └── dist │ ├── gwt-preact-bundle.min.js │ └── gwt-preact-bundle.js ├── .gitignore ├── LICENSE └── README.md /src/gwt/react/todo_mvc/client/utils.java: -------------------------------------------------------------------------------- 1 | package gwt.react.todo_mvc.client; 2 | 3 | public class utils { 4 | static String pluralize(int count, String word) { 5 | return count == 1 ? word : word + 's'; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /web/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /web/widgetInterop.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Widget Interop example 5 | 6 | 7 | 8 | 9 |
10 |
11 |
12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/gwt/react/api_sanity_test/client/ComponentDidCatchBadComponent.java: -------------------------------------------------------------------------------- 1 | package gwt.react.api_sanity_test.client; 2 | 3 | import gwt.interop.utils.client.plainobjects.JsPlainObj; 4 | import gwt.react.client.components.Component; 5 | import gwt.react.client.elements.ReactElement; 6 | import gwt.react.client.proptypes.BaseProps; 7 | import jsinterop.annotations.JsType; 8 | 9 | @JsType 10 | public class ComponentDidCatchBadComponent extends Component { 11 | 12 | public ComponentDidCatchBadComponent(BaseProps props) { 13 | super(props); 14 | } 15 | 16 | @Override 17 | protected ReactElement render() { 18 | 19 | throw new NullPointerException(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | .DS_Store 3 | 4 | # Package Files # 5 | *.jar 6 | *.war 7 | war 8 | 9 | # Gradle stuff 10 | .gradle/ 11 | build/ 12 | 13 | # gwt caches and compiled units # 14 | war/gwt_bree/ 15 | gwt-unitCache/ 16 | 17 | # boilerplate generated classes # 18 | .apt_generated/ 19 | 20 | # more caches and things from deploy # 21 | war/WEB-INF/deploy/ 22 | war/WEB-INF/classes/ 23 | 24 | #compilation logs 25 | .gwt/ 26 | 27 | #caching for already compiled files 28 | gwt-unitCache/ 29 | 30 | #gwt junit compilation files 31 | www-test/ 32 | 33 | #old GWT (1.5) created this dir 34 | .gwt-tmp/ 35 | 36 | # Eclipse specific files and directories 37 | bin/ 38 | .settings/ 39 | .classpath 40 | .project 41 | -------------------------------------------------------------------------------- /web/todomvc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React • TodoMVC 6 | 7 | 8 | 9 | 10 |
11 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /web/apiSanityTest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React API Test 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 23 | 24 |
25 | 26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /src/gwt/react/widget_interop/client/ReactPanel.java: -------------------------------------------------------------------------------- 1 | package gwt.react.widget_interop.client; 2 | 3 | import com.google.gwt.dom.client.DivElement; 4 | import com.google.gwt.dom.client.Document; 5 | import com.google.gwt.user.client.ui.Widget; 6 | import gwt.react.client.api.ReactDOM; 7 | import gwt.react.client.elements.ReactElement; 8 | 9 | 10 | public class ReactPanel extends Widget { 11 | DivElement container; 12 | ReactElement elementToRender; 13 | 14 | public ReactPanel(ReactElement elementToRender) { 15 | this.elementToRender = elementToRender; 16 | container = Document.get().createDivElement(); 17 | setElement(container); 18 | } 19 | 20 | @Override 21 | public void onAttach() { 22 | super.onAttach(); 23 | ReactDOM.render(elementToRender, container); 24 | 25 | } 26 | 27 | @Override 28 | public void onDetach() { 29 | ReactDOM.unmountComponentAtNode(container); 30 | super.onDetach(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /web/jsReactComponentInteropTest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React API Test 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 23 | 24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /web/preactSanityTest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React API Test 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /src/gwt/react/widget_interop/widget_interop.gwt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/gwt/react/todo_mvc/todomvc.gwt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | --> 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/gwt/react/js_react_component_interop/jsReactComponentInterop.gwt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | --> 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/gwt/react/api_sanity_test/apisanitytest.gwt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/gwt/react/preact_sanity_test/preactsanitytest.gwt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 GWT React 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gwt-react-examples 2 | Examples for the various GWT React projects 3 | 4 | ## Introduction 5 | 6 | gwt-react-examples provides examples of how to use the various GWTReact projects including: 7 | 8 | * [gwt-react](https://github.com/GWTReact/gwt-react) - example [todomvc](https://github.com/GWTReact/gwt-react) 9 | * [gwt-react-router](https://github.com/GWTReact/gwt-react-router) - example [todomvc](https://github.com/GWTReact/gwt-react) 10 | * GWT interop with existing Widgets. 11 | * Using Preact instead of React. 12 | 13 | If you click on the example links above, you can see the Javascript projects the examples where ported from. 14 | 15 | ## Getting Started 16 | 17 | 1. Download and install Gradle from [gradle.org](http://gradle.org/) 18 | 19 | 2. cd to the top level of gwt-react-examples 20 | 21 | 3. Type gradle jettyDraftWar 22 | 23 | 4. You can then go to the following url's for each sample 24 | 25 | * http://localhost:8080/gwt-react-examples/apiSanityTest.html 26 | * http://localhost:8080/gwt-react-examples/todomvc.html 27 | * http://localhost:8080/gwt-react-examples/widgetInterop.html 28 | * http://localhost:8080/gwt-react-examples/preactSanityTest.html 29 | -------------------------------------------------------------------------------- /src/gwt/react/api_sanity_test/client/ComponentDidCatchExample.java: -------------------------------------------------------------------------------- 1 | package gwt.react.api_sanity_test.client; 2 | 3 | import gwt.interop.utils.client.plainobjects.JsPlainObj; 4 | import gwt.react.client.api.React; 5 | import gwt.react.client.components.Component; 6 | import gwt.react.client.components.lifecycle.ComponentDidCatch; 7 | import gwt.react.client.elements.ReactElement; 8 | import gwt.react.client.proptypes.BaseProps; 9 | import jsinterop.annotations.JsType; 10 | 11 | import static gwt.interop.utils.client.plainobjects.JsPlainObj.$jsPlainObj; 12 | import static gwt.react.client.api.React.DOM.div; 13 | 14 | @JsType 15 | public class ComponentDidCatchExample extends Component implements ComponentDidCatch { 16 | 17 | public ComponentDidCatchExample(BaseProps props) { 18 | super(props); 19 | state = $jsPlainObj("errorInfo", ""); 20 | } 21 | 22 | @Override 23 | protected ReactElement render() { 24 | 25 | if (state.getStr("errorInfo").length() > 0) 26 | return div(null, "Caught error in sub component, component stack = " + state.getStr("errorInfo")); 27 | else { 28 | return React.createElement(ComponentDidCatchBadComponent.class, null); 29 | } 30 | } 31 | 32 | @Override 33 | public void componentDidCatch(Object error, ErrorInfo info) { 34 | setState($jsPlainObj("errorInfo", info.getComponentStack())); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/gwt/react/todo_mvc/client/Classnames.java: -------------------------------------------------------------------------------- 1 | package gwt.react.todo_mvc.client; 2 | 3 | /** 4 | * A class for combining css classnames based on specific conditions 5 | */ 6 | public class Classnames { 7 | public static String get(String className, boolean condition) { 8 | 9 | return condition ? className : ""; 10 | } 11 | 12 | public static String get(String className1, boolean condition1, 13 | String className2, boolean condition2) { 14 | String cls = condition1 ? className1 : ""; 15 | 16 | if (condition2) { 17 | if (!cls.isEmpty()) { 18 | cls += " "; 19 | } 20 | cls += className2; 21 | } 22 | return cls; 23 | } 24 | 25 | public static String get(String className1, boolean condition1, 26 | String className2, boolean condition2, 27 | String className3, boolean condition3) { 28 | String cls = condition1 ? className1 : ""; 29 | 30 | if (condition2) { 31 | if (!cls.isEmpty()) { 32 | cls += " "; 33 | } 34 | cls += className2; 35 | } 36 | 37 | if (condition3) { 38 | if (!cls.isEmpty()) { 39 | cls += " "; 40 | } 41 | cls += className3; 42 | } 43 | return cls; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/gwt/react/js_react_component_interop/client/FineUploader.java: -------------------------------------------------------------------------------- 1 | package gwt.react.js_react_component_interop.client; 2 | 3 | import gwt.interop.utils.client.plainobjects.JsPlainObj; 4 | import gwt.react.client.api.React; 5 | import gwt.react.client.components.ComponentConstructorFn; 6 | import gwt.react.client.elements.ReactElement; 7 | import gwt.react.client.proptypes.BaseProps; 8 | import jsinterop.annotations.*; 9 | 10 | @JsType(isNative = true, namespace = JsPackage.GLOBAL) 11 | public class FineUploader { 12 | 13 | @JsProperty 14 | public static ComponentConstructorFn Gallery; 15 | 16 | 17 | @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object") 18 | static class GalleryProps extends BaseProps { 19 | public FineUploaderTraditional uploader; 20 | 21 | } 22 | 23 | @JsOverlay 24 | public static ReactElement Gallery(GalleryProps props) { 25 | return React.createElement(Gallery, props); 26 | } 27 | 28 | @JsType(isNative = true, namespace = "FineUploader", name = "FineUploaderTraditional") 29 | static class FineUploaderTraditional { 30 | public FineUploaderTraditional(JsPlainObj options) {} 31 | 32 | public native void on(String name, UploaderCallback callback); 33 | public native void off(String name, UploaderCallback callback); 34 | 35 | @JsFunction 36 | interface UploaderCallback { 37 | void onCall(Object id, String name, Object response); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/gwt/react/widget_interop/client/App.java: -------------------------------------------------------------------------------- 1 | package gwt.react.widget_interop.client; 2 | 3 | import com.google.gwt.core.client.EntryPoint; 4 | import com.google.gwt.user.client.ui.Button; 5 | import com.google.gwt.user.client.ui.PopupPanel; 6 | import com.google.gwt.user.client.ui.RootPanel; 7 | import gwt.react.client.api.React; 8 | 9 | 10 | public class App implements EntryPoint { 11 | private PopupPanel dialog; 12 | 13 | @Override 14 | public void onModuleLoad() { 15 | final Button button = new Button("Show embedded React view"); 16 | 17 | button.addClickHandler((event) -> { 18 | //Show a React component in a popup panel 19 | dialog = new PopupPanel(true); 20 | 21 | StatefulExample.Props statefulComp1Props = new StatefulExample.Props(); 22 | statefulComp1Props.aProp = "Embedded React component 1"; 23 | 24 | ReactPanel reactPanel = new ReactPanel(React.createElement(StatefulExample.class, statefulComp1Props)); 25 | reactPanel.setWidth("700px"); 26 | reactPanel.setHeight("700px"); 27 | 28 | dialog.add(reactPanel); 29 | dialog.setGlassEnabled(true); 30 | dialog.center(); 31 | }); 32 | 33 | RootPanel.get("replaceme").add(button); 34 | 35 | //Add React component to Root Panel 36 | StatefulExample.Props statefulComp2Props = new StatefulExample.Props(); 37 | statefulComp2Props.aProp = "Embedded React component 2"; 38 | 39 | ReactPanel reactPanel = new ReactPanel(React.createElement(StatefulExample.class, statefulComp2Props)); 40 | RootPanel.get("replaceme2").add(reactPanel); 41 | } 42 | } -------------------------------------------------------------------------------- /src/gwt/react/preact_sanity_test/client/ChildApiTests.java: -------------------------------------------------------------------------------- 1 | package gwt.react.preact_sanity_test.client; 2 | 3 | import gwt.interop.utils.shared.collections.Array; 4 | import gwt.react.client.api.React; 5 | import gwt.react.client.elements.ReactElement; 6 | import gwt.react.client.proptypes.BaseProps; 7 | import gwt.react.client.proptypes.html.CssProps; 8 | import gwt.react.client.proptypes.html.HtmlProps; 9 | 10 | import static gwt.react.client.api.GwtReact.castAsReactElement; 11 | import static gwt.react.client.api.React.DOM.br; 12 | import static gwt.react.client.api.React.DOM.div; 13 | 14 | class ChildApiTests { 15 | static ReactElement countChildrenComponent(BaseProps props) { 16 | int countChildren = React.Children.count(props.children); 17 | 18 | return 19 | div(null, 20 | div(null, "There are " + countChildren + " child components"), 21 | castAsReactElement(props.children), 22 | br(null) 23 | ); 24 | } 25 | 26 | static ReactElement updatePropsOfChildrenComponent(BaseProps props) { 27 | 28 | Array newChildren = React.Children.map(props.children, (child) -> { 29 | HtmlProps propsToMerge = new HtmlProps() 30 | .style(new CssProps() 31 | .color("red")); 32 | 33 | return React.cloneElement(child, propsToMerge); 34 | }); 35 | 36 | return 37 | div(null, 38 | castAsReactElement(newChildren), 39 | br(null)); 40 | } 41 | 42 | static ReactElement childArrayTestComponent(BaseProps props) { 43 | Array existingChildren = React.Children.toArray(props.children); 44 | 45 | return 46 | div(null, 47 | castAsReactElement(existingChildren), 48 | br(null)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/gwt/react/preact_sanity_test/client/App.java: -------------------------------------------------------------------------------- 1 | package gwt.react.preact_sanity_test.client; 2 | 3 | import com.google.gwt.core.client.EntryPoint; 4 | import elemental2.dom.DomGlobal; 5 | import gwt.react.client.api.React; 6 | import gwt.react.client.api.ReactDOM; 7 | import gwt.react.client.api.ReactDOMServer; 8 | import gwt.react.client.elements.ReactElement; 9 | 10 | import static gwt.react.client.api.React.DOM.div; 11 | 12 | public class App implements EntryPoint { 13 | 14 | @Override 15 | public void onModuleLoad() { 16 | 17 | StatefulExample.Props statefulCompProps = new StatefulExample.Props(); 18 | statefulCompProps.aProp = "aPropValue"; 19 | 20 | ReactElement appComp = 21 | div(null, 22 | React.createElement(ChildApiTests::countChildrenComponent, null, 23 | div(null, "Child 1"), 24 | div(null, "Child 2") 25 | ), 26 | React.createElement(ChildApiTests::childArrayTestComponent, null, 27 | div(null, "Array Child 1"), 28 | div(null, "Array Child 2"), 29 | div(null, "Array Child 3 (should be the last child)") 30 | ), 31 | React.createElement(ChildApiTests::updatePropsOfChildrenComponent, null, 32 | div(null, "Child 1 should be red"), 33 | div(null, "Child 2 should be red (should be the last child)") 34 | ), 35 | React.createElement(StatefulExample.class, statefulCompProps), 36 | //The following creates an element using a class 37 | React.createElement(StatefulExample2.class, null) 38 | ); 39 | 40 | ReactDOM.render(appComp, DomGlobal.document.getElementById("mainCont"), () -> DomGlobal.alert("Rendered")); 41 | 42 | DomGlobal.alert("renderToString returned: '" + ReactDOMServer.renderToString(div(null, "a div")) + "'"); 43 | } 44 | } -------------------------------------------------------------------------------- /src/gwt/react/api_sanity_test/client/ChildApiTests.java: -------------------------------------------------------------------------------- 1 | package gwt.react.api_sanity_test.client; 2 | 3 | import gwt.interop.utils.shared.collections.Array; 4 | import gwt.react.client.api.React; 5 | import gwt.react.client.components.StatelessComponent; 6 | import gwt.react.client.elements.ReactElement; 7 | import gwt.react.client.proptypes.BaseProps; 8 | import gwt.react.client.proptypes.html.CssProps; 9 | import gwt.react.client.proptypes.html.HtmlProps; 10 | 11 | import static gwt.react.client.api.GwtReact.castAsReactElement; 12 | import static gwt.react.client.api.React.DOM.br; 13 | import static gwt.react.client.api.React.DOM.div; 14 | 15 | class ChildApiTests { 16 | static StatelessComponent countChildrenComponent = (props) -> { 17 | int countChildren = React.Children.count(props.children); 18 | 19 | return 20 | div(null, 21 | div(null, "There are " + countChildren + " child components"), 22 | castAsReactElement(props.children), 23 | br(null) 24 | ); 25 | }; 26 | 27 | static StatelessComponent updatePropsOfChildrenComponent = (props) -> { 28 | 29 | Array newChildren = React.Children.map(props.children, (child) -> { 30 | HtmlProps propsToMerge = new HtmlProps() 31 | .style(new CssProps() 32 | .color("red")); 33 | 34 | return React.cloneElement(child, propsToMerge); 35 | }); 36 | 37 | return 38 | div(null, 39 | castAsReactElement(newChildren), 40 | br(null)); 41 | }; 42 | 43 | static StatelessComponent childArrayTestComponent = (props) -> { 44 | Array existingChildren = React.Children.toArray(props.children); 45 | 46 | return 47 | div(null, 48 | castAsReactElement(existingChildren), 49 | br(null)); 50 | }; 51 | } 52 | -------------------------------------------------------------------------------- /src/gwt/react/todo_mvc/client/App.java: -------------------------------------------------------------------------------- 1 | package gwt.react.todo_mvc.client; 2 | 3 | import com.google.gwt.core.client.EntryPoint; 4 | import elemental2.dom.DomGlobal; 5 | import gwt.interop.utils.client.collections.JsArray; 6 | import gwt.interop.utils.shared.collections.Array; 7 | import gwt.react.client.api.React; 8 | import gwt.react.client.api.ReactDOM; 9 | import gwt.react.client.components.ComponentUtils; 10 | import gwt.react.client.elements.ReactElement; 11 | import gwt.react_router.client.ReactRouter; 12 | import gwt.react_router.client.RouteProps; 13 | import gwt.react_router.client.RouterProps; 14 | 15 | import static gwt.react.client.api.GwtReact.castAsReactElement; 16 | import static gwt.react_router.client.ReactRouter.Route; 17 | import static gwt.react_router.client.ReactRouter.Router; 18 | 19 | public class App implements EntryPoint { 20 | 21 | static final int ESCAPE_KEY = 27; 22 | static final int ENTER_KEY = 13; 23 | 24 | static TodoModel model = new TodoModel(); 25 | private static Array routes = JsArray.create(); 26 | 27 | private void render() { 28 | ReactDOM.render( 29 | React.createElement(Router, new RouterProps().History(ReactRouter.hashHistory), 30 | castAsReactElement(routes)), DomGlobal.document.getElementById("todoapp")); 31 | } 32 | 33 | @Override 34 | public void onModuleLoad() { 35 | //React Router now requires that you only create the Routes once so define them statically 36 | routes.push(React.createElement(Route, 37 | new RouteProps() 38 | .path("/") 39 | .component(ComponentUtils.getCtorFn(TodoList.class)) 40 | .key("1"))); 41 | 42 | routes.push(React.createElement(Route, 43 | new RouteProps() 44 | .path("/:nowShowing") 45 | .component(ComponentUtils.getCtorFn(TodoList.class)) 46 | .key("2"))); 47 | 48 | model.subscribe(this::render); 49 | render(); 50 | } 51 | } -------------------------------------------------------------------------------- /src/gwt/react/js_react_component_interop/client/App.java: -------------------------------------------------------------------------------- 1 | package gwt.react.js_react_component_interop.client; 2 | 3 | import com.google.gwt.core.client.EntryPoint; 4 | import elemental2.dom.DomGlobal; 5 | import gwt.interop.utils.client.plainobjects.JsPlainObj; 6 | import gwt.react.client.api.ReactDOM; 7 | import gwt.react.js_react_component_interop.client.FineUploader.FineUploaderTraditional; 8 | 9 | import static gwt.interop.utils.client.plainobjects.JsPlainObj.$jsPlainObj; 10 | 11 | public class App implements EntryPoint { 12 | 13 | @Override 14 | public void onModuleLoad() { 15 | 16 | FineUploader.GalleryProps galProps = new FineUploader.GalleryProps(); 17 | 18 | /* 19 | We want to pass an Object literal of the following form. 20 | 21 | { 22 | options: { 23 | chunking: { 24 | enabled: true 25 | }, 26 | deleteFile: { 27 | enabled: true, 28 | endpoint: '/uploads' 29 | }, 30 | request: { 31 | endpoint: '/uploads' 32 | }, 33 | retry: { 34 | enableAuto: true 35 | } 36 | } 37 | } 38 | 39 | Without defining all the types we can use $jsPlainObj 40 | */ 41 | 42 | 43 | JsPlainObj uploaderConfig = 44 | 45 | $jsPlainObj( 46 | "options", 47 | $jsPlainObj( 48 | "chunking", 49 | $jsPlainObj( 50 | "enabled", true 51 | ), 52 | "deleteFile", 53 | $jsPlainObj( 54 | "enabled", true, 55 | "endpoint", "/uploads" 56 | ), 57 | "request", 58 | $jsPlainObj( 59 | "endpoint", "/uploads" 60 | ), 61 | "retry", 62 | $jsPlainObj( 63 | "enableAuto", false 64 | ) 65 | ) 66 | ); 67 | 68 | galProps.uploader = new FineUploaderTraditional(uploaderConfig); 69 | 70 | ReactDOM.render(FineUploader.Gallery(galProps), DomGlobal.document.getElementById("mainCont")); 71 | } 72 | } 73 | 74 | 75 | -------------------------------------------------------------------------------- /src/gwt/react/widget_interop/client/StatefulExample.java: -------------------------------------------------------------------------------- 1 | package gwt.react.widget_interop.client; 2 | 3 | import elemental2.dom.HTMLInputElement; 4 | import gwt.interop.utils.client.plainobjects.JsPlainObj; 5 | import gwt.react.client.components.Component; 6 | import gwt.react.client.elements.ReactElement; 7 | import gwt.react.client.events.FormEvent; 8 | import gwt.react.client.proptypes.BaseProps; 9 | import gwt.react.client.proptypes.html.BtnProps; 10 | import gwt.react.client.proptypes.html.InputProps; 11 | import jsinterop.annotations.JsOverlay; 12 | import jsinterop.annotations.JsPackage; 13 | import jsinterop.annotations.JsType; 14 | 15 | import static gwt.react.client.api.React.DOM.*; 16 | 17 | @JsType 18 | class StatefulExample extends Component { 19 | 20 | @JsType(isNative = true, namespace = JsPackage.GLOBAL, name="Object") 21 | static class Props extends BaseProps { 22 | String aProp; 23 | } 24 | 25 | @JsType(isNative = true, namespace = JsPackage.GLOBAL, name="Object") 26 | static class State extends JsPlainObj { 27 | String aStateVar; 28 | 29 | @JsOverlay 30 | static State make(String aStateVar) { 31 | State o = new State(); 32 | o.aStateVar = aStateVar; 33 | return o; 34 | } 35 | } 36 | 37 | public StatefulExample(StatefulExample.Props props) { 38 | super(props); 39 | state = State.make("Initial Value"); 40 | } 41 | 42 | private void doChange(FormEvent event) { 43 | HTMLInputElement e = (HTMLInputElement)event.target; 44 | String val = e.value; 45 | setState(State.make(val)); 46 | } 47 | 48 | public ReactElement render() { 49 | return 50 | div(null, 51 | button(new BtnProps() 52 | .title("Some title") 53 | .onClick((e) -> setState(State.make("Updated Value"))), 54 | getDescription()), 55 | 56 | input(new InputProps() 57 | .placeholder("What needs to be done?") 58 | .value(state.aStateVar) 59 | .onChange(this::doChange)) 60 | ); 61 | } 62 | 63 | private String getDescription() { 64 | return "Click Me (state=" + state.aStateVar + ", props=" + props.aProp + ")"; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/gwt/react/preact_sanity_test/client/StatefulExample2.java: -------------------------------------------------------------------------------- 1 | package gwt.react.preact_sanity_test.client; 2 | 3 | 4 | import gwt.interop.utils.client.collections.JsArray; 5 | import gwt.interop.utils.client.plainobjects.JsPlainObj; 6 | import gwt.interop.utils.shared.collections.Array; 7 | import gwt.react.client.components.Component; 8 | import gwt.react.client.elements.ReactElement; 9 | import gwt.react.client.events.MouseEvent; 10 | import gwt.react.client.proptypes.BaseProps; 11 | import gwt.react.client.proptypes.html.InputProps; 12 | import gwt.react.client.proptypes.html.LabelProps; 13 | import gwt.react.client.proptypes.html.attributeTypes.InputType; 14 | import jsinterop.annotations.JsPackage; 15 | import jsinterop.annotations.JsType; 16 | 17 | import static gwt.interop.utils.client.plainobjects.JsPlainObj.$; 18 | import static gwt.react.client.api.GwtReact.castAsReactElement; 19 | import static gwt.react.client.api.React.DOM.*; 20 | 21 | /** 22 | * This example shows a stateful component where we have renamed the JsType and added it to the global scope 23 | */ 24 | @JsType(name = "RenamedStatefulExample2", namespace = JsPackage.GLOBAL) 25 | public class StatefulExample2 extends Component{ 26 | 27 | @JsType(isNative = true, namespace = JsPackage.GLOBAL, name="Object") 28 | static class State extends JsPlainObj { 29 | public boolean checked; 30 | } 31 | 32 | public StatefulExample2(BaseProps props) { 33 | super(props); 34 | } 35 | 36 | void onClicked(MouseEvent e) { 37 | //React recommends using the setState function if you are setting the new state based on the old state. 38 | //possibly set state calls could be batched up and updated asynchronously 39 | setState((prevState, props) -> $(new State(), "checked", !prevState.checked)); 40 | } 41 | 42 | @Override 43 | protected ReactElement render() { 44 | Array testLiItems = JsArray.create("Item1", "Item2", "Item3"); 45 | 46 | return 47 | div(null, 48 | label(new LabelProps() 49 | .htmlFor("checkField"), 50 | "Click me " 51 | ), 52 | input(new InputProps() 53 | .id("checkField") 54 | .type(InputType.checkbox) 55 | .checked(state.checked) 56 | .onClick(this::onClicked) 57 | ), 58 | //The following doesn't work with Preact 7.2.0 without a patch (included in gwt-react), due to iFrame JS loading issues 59 | ul(null, 60 | castAsReactElement(testLiItems.map(i -> li(null, i))) 61 | ) 62 | ); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/gwt/react/api_sanity_test/client/App.java: -------------------------------------------------------------------------------- 1 | package gwt.react.api_sanity_test.client; 2 | 3 | import static gwt.react.client.api.React.DOM.div; 4 | import static gwt.react.client.api.React.DOM.fragment; 5 | import static gwt.react.client.api.React.DOM.strictMode; 6 | 7 | import com.google.gwt.core.client.EntryPoint; 8 | 9 | import elemental2.dom.DomGlobal; 10 | import gwt.react.client.api.React; 11 | import gwt.react.client.api.ReactDOM; 12 | import gwt.react.client.api.ReactDOMServer; 13 | import gwt.react.client.elements.ReactElement; 14 | import gwt.react.client.proptypes.FragmentProps; 15 | 16 | public class App implements EntryPoint { 17 | 18 | @Override 19 | public void onModuleLoad() { 20 | 21 | StatefulExample.Props statefulCompProps = new StatefulExample.Props(); 22 | statefulCompProps.aProp = "aPropValue"; 23 | 24 | ReactElement appComp = 25 | strictMode( 26 | div(null, 27 | ReactDOM.createPortal( 28 | div(null, "This is in a portal!"), DomGlobal.document.getElementById("portalCont") 29 | ), 30 | 31 | React.createElement(ChildApiTests.countChildrenComponent, null, 32 | div(null, "Child 1"), 33 | div(null, "Child 2") 34 | ), 35 | React.createElement(ChildApiTests.childArrayTestComponent, null, 36 | div(null, "Array Child 1"), 37 | div(null, "Array Child 2"), 38 | div(null, "Array Child 3 (should be the last child)") 39 | ), 40 | React.createElement(ChildApiTests.updatePropsOfChildrenComponent, null, 41 | div(null, "Child 1 should be red"), 42 | div(null, "Child 2 should be red (should be the last child)") 43 | ), 44 | React.createElement(StatefulExample.class, statefulCompProps), 45 | 46 | React.createElement(ComponentDidCatchExample.class, statefulCompProps), 47 | fragment( 48 | div(null, "Child of fragment") 49 | ), 50 | fragment(new FragmentProps().key("1"), 51 | div(null, "Child of fragment with key") 52 | ) 53 | ) 54 | ); 55 | 56 | ReactDOM.render(appComp, DomGlobal.document.getElementById("mainCont"), () -> DomGlobal.alert("Rendered")); 57 | 58 | DomGlobal.alert("renderToString returned: '" + ReactDOMServer.renderToString(div(null, "a div")) + "'"); 59 | } 60 | } -------------------------------------------------------------------------------- /src/gwt/react/todo_mvc/client/TodoModel.java: -------------------------------------------------------------------------------- 1 | package gwt.react.todo_mvc.client; 2 | 3 | import gwt.interop.utils.client.collections.JsArray; 4 | import gwt.interop.utils.shared.functional.JsRunnable; 5 | import gwt.interop.utils.shared.collections.Array; 6 | 7 | import java.util.Date; 8 | 9 | class TodoModel { 10 | // Generic "model" object. You can use whatever 11 | // framework you want. For this application it 12 | // may not even be worth separating this logic 13 | // out, but we do this to demonstrate one way to 14 | // separate out parts of your application. 15 | static class Todo { 16 | String id; 17 | String title; 18 | boolean completed; 19 | 20 | Todo(String id, String title, boolean completed) { 21 | this.id = id; 22 | this.title = title; 23 | this.completed = completed; 24 | } 25 | } 26 | 27 | Array todos = JsArray.create(); 28 | private Array onChanges = JsArray.create(); 29 | 30 | void subscribe(JsRunnable onChange) { 31 | onChanges.push(onChange); 32 | } 33 | 34 | private void inform() { 35 | //Utils.store(this.key, this.todos); 36 | onChanges.forEachElem((v, index, theArray) -> v.run()); 37 | } 38 | 39 | void addTodo(String title) { 40 | todos = todos.concatValue(new Todo(Long.toString(new Date().getTime()), title, false)); 41 | 42 | inform(); 43 | 44 | } 45 | 46 | void toggleAll(boolean checked) { 47 | // Note: it's usually better to use immutable data structures since they're 48 | // easier to reason about and React works very well with them. That's why 49 | // we use map() and filter() everywhere instead of mutating the array or 50 | // todo items themselves. 51 | 52 | todos = todos.map((v, index, theArray) -> new Todo(v.id, v.title, checked)); 53 | 54 | inform(); 55 | } 56 | 57 | void toggle(Todo todoToToggle) { 58 | todos = todos.map((v, index, theArray) -> (v == todoToToggle) ? new Todo(v.id, v.title, !v.completed) : v); 59 | 60 | inform(); 61 | } 62 | 63 | void destroy(Todo todo) { 64 | todos = todos.filter((v, index, theArray) -> (v != todo)); 65 | 66 | inform(); 67 | } 68 | 69 | void save(Todo todoToSave, String newTitle) { 70 | todos = todos.map((v, index, theArray) -> (v == todoToSave) ? new Todo(v.id, newTitle, v.completed) : v); 71 | 72 | inform(); 73 | } 74 | 75 | void clearCompleted() { 76 | todos = todos.filter((v, index, theArray) -> !v.completed); 77 | 78 | inform(); 79 | } 80 | } -------------------------------------------------------------------------------- /src/gwt/react/todo_mvc/client/Footer.java: -------------------------------------------------------------------------------- 1 | package gwt.react.todo_mvc.client; 2 | 3 | import gwt.react.client.components.*; 4 | import gwt.react.client.elements.ReactElement; 5 | import gwt.react.client.events.MouseEventHandler; 6 | import gwt.react.client.proptypes.*; 7 | import gwt.react.client.proptypes.html.AnchorProps; 8 | import gwt.react.client.proptypes.html.BtnProps; 9 | import gwt.react.client.proptypes.html.HtmlProps; 10 | import jsinterop.annotations.JsPackage; 11 | import jsinterop.annotations.JsType; 12 | import static gwt.react.client.api.React.DOM.*; 13 | 14 | class Footer { 15 | 16 | @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object") 17 | static class FooterProps extends BaseProps { 18 | int count; 19 | int completedCount; 20 | String nowShowing; 21 | MouseEventHandler onClearCompleted; 22 | } 23 | 24 | public static StatelessComponent component = (props) -> { 25 | 26 | String activeTodoWord = utils.pluralize(props.count, "item"); 27 | ReactElement clearButton = null; 28 | 29 | if (props.completedCount > 0) { 30 | clearButton = button( 31 | new BtnProps() 32 | .className("clear-completed") 33 | .onClick(props.onClearCompleted), 34 | "Clear Completed" 35 | ); 36 | } 37 | String nowShowing = props.nowShowing; 38 | 39 | return 40 | footer(new HtmlProps().className("footer"), 41 | span(new HtmlProps().className("todo-count"), 42 | strong(null, Integer.toString(props.count)), 43 | activeTodoWord + " left" 44 | ), 45 | ul(new HtmlProps().className("filters"), 46 | li(null, 47 | a(new AnchorProps() 48 | .className(Classnames.get("selected", nowShowing == null)) 49 | .href("#/"), "All") 50 | ), 51 | li(null, 52 | a(new AnchorProps() 53 | .className(Classnames.get("selected", TodoList.NOW_SHOWING_ACTIVE_TODOS.equals(nowShowing))) 54 | .href("#/active"), "Active") 55 | ), 56 | li(null, 57 | a(new AnchorProps() 58 | .className(Classnames.get("selected", TodoList.NOW_SHOWING_COMPLETED_TODOS.equals(nowShowing))) 59 | .href("#/completed"), "Completed") 60 | ) 61 | ), 62 | clearButton 63 | ); 64 | }; 65 | } -------------------------------------------------------------------------------- /web/css/base.css: -------------------------------------------------------------------------------- 1 | hr { 2 | margin: 20px 0; 3 | border: 0; 4 | border-top: 1px dashed #c5c5c5; 5 | border-bottom: 1px dashed #f7f7f7; 6 | } 7 | 8 | .learn a { 9 | font-weight: normal; 10 | text-decoration: none; 11 | color: #b83f45; 12 | } 13 | 14 | .learn a:hover { 15 | text-decoration: underline; 16 | color: #787e7e; 17 | } 18 | 19 | .learn h3, 20 | .learn h4, 21 | .learn h5 { 22 | margin: 10px 0; 23 | font-weight: 500; 24 | line-height: 1.2; 25 | color: #000; 26 | } 27 | 28 | .learn h3 { 29 | font-size: 24px; 30 | } 31 | 32 | .learn h4 { 33 | font-size: 18px; 34 | } 35 | 36 | .learn h5 { 37 | margin-bottom: 0; 38 | font-size: 14px; 39 | } 40 | 41 | .learn ul { 42 | padding: 0; 43 | margin: 0 0 30px 25px; 44 | } 45 | 46 | .learn li { 47 | line-height: 20px; 48 | } 49 | 50 | .learn p { 51 | font-size: 15px; 52 | font-weight: 300; 53 | line-height: 1.3; 54 | margin-top: 0; 55 | margin-bottom: 0; 56 | } 57 | 58 | #issue-count { 59 | display: none; 60 | } 61 | 62 | .quote { 63 | border: none; 64 | margin: 20px 0 60px 0; 65 | } 66 | 67 | .quote p { 68 | font-style: italic; 69 | } 70 | 71 | .quote p:before { 72 | content: '“'; 73 | font-size: 50px; 74 | opacity: .15; 75 | position: absolute; 76 | top: -20px; 77 | left: 3px; 78 | } 79 | 80 | .quote p:after { 81 | content: '”'; 82 | font-size: 50px; 83 | opacity: .15; 84 | position: absolute; 85 | bottom: -42px; 86 | right: 3px; 87 | } 88 | 89 | .quote footer { 90 | position: absolute; 91 | bottom: -40px; 92 | right: 0; 93 | } 94 | 95 | .quote footer img { 96 | border-radius: 3px; 97 | } 98 | 99 | .quote footer a { 100 | margin-left: 5px; 101 | vertical-align: middle; 102 | } 103 | 104 | .speech-bubble { 105 | position: relative; 106 | padding: 10px; 107 | background: rgba(0, 0, 0, .04); 108 | border-radius: 5px; 109 | } 110 | 111 | .speech-bubble:after { 112 | content: ''; 113 | position: absolute; 114 | top: 100%; 115 | right: 30px; 116 | border: 13px solid transparent; 117 | border-top-color: rgba(0, 0, 0, .04); 118 | } 119 | 120 | .learn-bar > .learn { 121 | position: absolute; 122 | width: 272px; 123 | top: 8px; 124 | left: -300px; 125 | padding: 10px; 126 | border-radius: 5px; 127 | background-color: rgba(255, 255, 255, .6); 128 | transition-property: left; 129 | transition-duration: 500ms; 130 | } 131 | 132 | @media (min-width: 899px) { 133 | .learn-bar { 134 | width: auto; 135 | padding-left: 300px; 136 | } 137 | 138 | .learn-bar > .learn { 139 | left: 8px; 140 | } 141 | } -------------------------------------------------------------------------------- /src/gwt/react/preact_sanity_test/client/StatefulExample.java: -------------------------------------------------------------------------------- 1 | package gwt.react.preact_sanity_test.client; 2 | 3 | import elemental2.dom.DomGlobal; 4 | import elemental2.dom.HTMLInputElement; 5 | import gwt.interop.utils.client.plainobjects.JsPlainObj; 6 | import gwt.react.client.components.PureComponent; 7 | import gwt.react.client.elements.ReactElement; 8 | import gwt.react.client.events.FormEvent; 9 | import gwt.react.client.proptypes.BaseProps; 10 | import gwt.react.client.proptypes.html.BtnProps; 11 | import gwt.react.client.proptypes.html.InputProps; 12 | import jsinterop.annotations.JsOverlay; 13 | import jsinterop.annotations.JsPackage; 14 | import jsinterop.annotations.JsType; 15 | 16 | import static gwt.react.client.api.React.DOM.*; 17 | 18 | @JsType 19 | class StatefulExample extends PureComponent { 20 | 21 | @JsType(isNative = true, namespace = JsPackage.GLOBAL, name="Object") 22 | static class Props extends BaseProps { 23 | String aProp; 24 | } 25 | 26 | @JsType(isNative = true, namespace = JsPackage.GLOBAL, name="Object") 27 | static class State extends JsPlainObj { 28 | String aStateVar; 29 | 30 | @JsOverlay 31 | static State make(String aStateVar) { 32 | State o = new State(); 33 | o.aStateVar = aStateVar; 34 | return o; 35 | } 36 | } 37 | 38 | public StatefulExample(StatefulExample.Props props) { 39 | super(props); 40 | this.state = State.make("Initial Value"); 41 | } 42 | 43 | private void doChange(FormEvent event) { 44 | HTMLInputElement e = (HTMLInputElement)event.target; 45 | String val = e.value; 46 | setState(State.make(val)); 47 | } 48 | 49 | public ReactElement render() { 50 | return 51 | div(null, 52 | button(new BtnProps() 53 | .title("Some title") 54 | .onClick((e) -> setState(State.make("Updated Value"))), 55 | getDescription()), 56 | 57 | input(new InputProps() 58 | .placeholder("What needs to be done?") 59 | .value(state.aStateVar) 60 | .onChange(this::doChange)) 61 | ); 62 | } 63 | 64 | //Optional lifecycle methods 65 | 66 | public void componentWillMount() { 67 | DomGlobal.alert("componentWillMount called"); 68 | } 69 | 70 | public void componentDidMount() { 71 | DomGlobal.alert("componentDidMount called"); 72 | } 73 | 74 | public void componentWillReceiveProps(Props nextProps) { 75 | DomGlobal.alert("componentWillReceiveProps called (nextProps "+ nextProps.toJSONString() + ")"); 76 | } 77 | 78 | public boolean shouldComponentUpdate(Props nextProps, State nextState) { 79 | DomGlobal.alert("shouldComponentUpdate called (nextProps "+ nextProps.toJSONString() + " nextState " + nextState.toJSONString() + ")"); 80 | return true; 81 | } 82 | 83 | public void componentWillUpdate(Props nextProps, State nextState) { 84 | DomGlobal.alert("componentWillUpdate called (nextProps "+ nextProps.toJSONString() + " nextState " + nextState.toJSONString() + ")"); 85 | } 86 | 87 | public void componentDidUpdate(Props prevProps, State prevState) { 88 | DomGlobal.alert("componentDidUpdate called (prevProps "+ prevProps.toJSONString() + " prevState " + prevState.toJSONString() + ")"); 89 | } 90 | 91 | public void componentWillUnmount() { 92 | DomGlobal.alert("componentWillUnmount called"); 93 | } 94 | 95 | private String getDescription() { 96 | return "Click Me (state=" + state.aStateVar + ", props=" + props.aProp + ")"; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/gwt/react/api_sanity_test/client/StatefulExample.java: -------------------------------------------------------------------------------- 1 | package gwt.react.api_sanity_test.client; 2 | 3 | import com.google.gwt.core.client.GWT; 4 | import elemental2.dom.DomGlobal; 5 | import elemental2.dom.HTMLButtonElement; 6 | import elemental2.dom.HTMLInputElement; 7 | import gwt.interop.utils.client.plainobjects.JsPlainObj; 8 | import gwt.react.client.api.React; 9 | import gwt.react.client.api.ReactRef; 10 | import gwt.react.client.components.Component; 11 | import gwt.react.client.components.lifecycle.*; 12 | import gwt.react.client.elements.ReactElement; 13 | import gwt.react.client.events.FormEvent; 14 | import gwt.react.client.proptypes.BaseProps; 15 | import gwt.react.client.proptypes.html.BtnProps; 16 | import gwt.react.client.proptypes.html.InputProps; 17 | import jsinterop.annotations.*; 18 | 19 | import static gwt.react.client.api.React.DOM.*; 20 | 21 | /** 22 | * This shows the optional use of lifecycle interfaces. They aren't strictly necessary, however, 23 | * they help with type checking 24 | */ 25 | @JsType 26 | class StatefulExample extends Component implements 27 | ComponentWillMount, 28 | ComponentDidMount, 29 | ComponentWillReceiveProps, 30 | ShouldComponentUpdate, 31 | ComponentDidUpdate, 32 | ComponentWillUnmount, 33 | GetSnapshotBeforeUpdate{ 34 | 35 | 36 | @JsType(isNative = true, namespace = JsPackage.GLOBAL, name="Object") 37 | static class Props extends BaseProps { 38 | String aProp; 39 | } 40 | 41 | @JsType(isNative = true, namespace = JsPackage.GLOBAL, name="Object") 42 | static class State extends JsPlainObj { 43 | String aStateVar; 44 | 45 | @JsOverlay 46 | static State make(String aStateVar) { 47 | State o = new State(); 48 | o.aStateVar = aStateVar; 49 | return o; 50 | } 51 | } 52 | 53 | private ReactRef btnRef = React.createRef(); 54 | 55 | public StatefulExample(StatefulExample.Props props) { 56 | super(props); 57 | this.state = State.make("Initial Value"); 58 | } 59 | 60 | private void doChange(FormEvent event) { 61 | HTMLInputElement e = (HTMLInputElement) event.target; 62 | String val = e.value; 63 | setState(State.make(val)); 64 | } 65 | 66 | public ReactElement render() { 67 | GWT.log("btnRef = " + btnRef.current); 68 | 69 | return 70 | div(null, 71 | button(new BtnProps() 72 | .ref(btnRef) 73 | .title("Some title") 74 | .onClick((e) -> setState(State.make("Updated Value"))), 75 | getDescription()), 76 | 77 | input(new InputProps() 78 | .placeholder("What needs to be done?") 79 | .value(state.aStateVar) 80 | .onChange(this::doChange)) 81 | ); 82 | } 83 | 84 | //Optional lifecycle methods 85 | 86 | public static State getDerivedStateFromProps(Props nextProps, State prevState) { 87 | DomGlobal.alert("getDerivedStateFromProps called (nextProps "+ nextProps.toJSONString() + " nextState " + prevState.toJSONString() + ")"); 88 | return null; //Do nothing 89 | } 90 | 91 | public void componentWillMount() { 92 | DomGlobal.alert("componentWillMount called"); 93 | } 94 | 95 | public void componentDidMount() { 96 | DomGlobal.alert("componentDidMount called"); 97 | } 98 | 99 | public void componentWillReceiveProps(Props nextProps) { 100 | DomGlobal.alert("componentWillReceiveProps called (nextProps "+ nextProps.toJSONString() + ")"); 101 | } 102 | 103 | public boolean shouldComponentUpdate(Props nextProps, State nextState) { 104 | DomGlobal.alert("shouldComponentUpdate called (nextProps "+ nextProps.toJSONString() + " nextState " + nextState.toJSONString() + ")"); 105 | return true; 106 | } 107 | 108 | public void componentWillUpdate(Props nextProps, State nextState) { 109 | DomGlobal.alert("componentWillUpdate called (nextProps "+ nextProps.toJSONString() + " nextState " + nextState.toJSONString() + ")"); 110 | } 111 | 112 | public void componentDidUpdate(Props prevProps, State prevState, Object snapshotValue) { 113 | DomGlobal.alert("componentDidUpdate called (prevProps "+ prevProps.toJSONString() + " prevState " + prevState.toJSONString() + "snapshot " + snapshotValue + ")"); 114 | } 115 | 116 | public Object getSnapshotBeforeUpdate(Props prevProps, State prevState) { 117 | return "TestSnapshot"; 118 | } 119 | 120 | public void componentWillUnmount() { 121 | DomGlobal.alert("componentWillUnmount called"); 122 | } 123 | 124 | private String getDescription() { 125 | return "Click Me (state=" + state.aStateVar + ", props=" + props.aProp + ")"; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/gwt/react/todo_mvc/client/TodoItem.java: -------------------------------------------------------------------------------- 1 | package gwt.react.todo_mvc.client; 2 | 3 | import elemental2.dom.HTMLInputElement; 4 | import gwt.interop.utils.client.plainobjects.JsPlainObj; 5 | import gwt.interop.utils.shared.functional.JsBiConsumer; 6 | import gwt.react.client.components.Component; 7 | import gwt.react.client.elements.ReactElement; 8 | import gwt.react.client.events.FocusEvent; 9 | import gwt.react.client.events.FormEvent; 10 | import gwt.react.client.events.KeyboardEvent; 11 | import gwt.react.client.events.MouseEvent; 12 | import gwt.react.client.proptypes.BaseProps; 13 | import gwt.react.client.proptypes.html.BtnProps; 14 | import gwt.react.client.proptypes.html.HtmlProps; 15 | import gwt.react.client.proptypes.html.InputProps; 16 | import gwt.react.client.proptypes.html.LabelProps; 17 | import gwt.react.client.proptypes.html.attributeTypes.InputType; 18 | import jsinterop.annotations.JsPackage; 19 | import jsinterop.annotations.JsType; 20 | 21 | import static gwt.interop.utils.client.plainobjects.JsPlainObj.$; 22 | import static gwt.react.client.api.React.DOM.*; 23 | 24 | @JsType 25 | class TodoItem extends Component { 26 | 27 | @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object") 28 | static class TodoItemProps extends BaseProps { 29 | TodoModel.Todo todo; 30 | boolean isEditing; 31 | JsBiConsumer doSave; 32 | JsBiConsumer doAction; 33 | } 34 | 35 | @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object") 36 | static class TodoState extends JsPlainObj { 37 | String editText; 38 | } 39 | 40 | private TodoState newTodoItemState(String editText) { 41 | return $(new TodoState(), "editText", editText); 42 | } 43 | 44 | public TodoItem(TodoItem.TodoItemProps props) { 45 | super(props); 46 | 47 | state = newTodoItemState(props.todo.title); 48 | } 49 | 50 | private void submitTodo(FocusEvent event) { 51 | String val = state.editText; 52 | if (val != null && !val.isEmpty()) { 53 | props.doSave.accept(props.todo, val); 54 | 55 | setState(newTodoItemState(val)); 56 | } else { 57 | props.doAction.accept(TodoList.Action.DESTROY, props.todo); 58 | } 59 | } 60 | 61 | private void handleEdit(MouseEvent event) { 62 | props.doAction.accept(TodoList.Action.EDIT, props.todo); 63 | setState(newTodoItemState(props.todo.title)); 64 | } 65 | 66 | private void handleKeyDown(KeyboardEvent event) { 67 | if (event.which == App.ESCAPE_KEY) { 68 | setState(newTodoItemState(props.todo.title)); 69 | props.doAction.accept(TodoList.Action.CANCEL, props.todo); 70 | } else if (event.which == App.ENTER_KEY) { 71 | submitTodo(null); 72 | } 73 | } 74 | 75 | private void handleChange(FormEvent event) { 76 | if (props.isEditing) { 77 | setState(newTodoItemState(((HTMLInputElement)event.target).value)); 78 | } 79 | } 80 | 81 | 82 | /** 83 | * This is a completely optional performance enhancement that you can 84 | * implement on any React component. If you were to delete this method 85 | * the app would still work correctly (and still be very performant!), we 86 | * just use it as an example of how little code it takes to getCtorFn an order 87 | * of magnitude performance improvement. 88 | */ 89 | public boolean shouldComponentUpdate(TodoItemProps nextProps, TodoState nextState) { 90 | return (nextProps.todo != props.todo || 91 | nextProps.isEditing != props.isEditing || 92 | !nextState.editText.equals(state.editText)); 93 | } 94 | 95 | /** 96 | * Safely manipulate the DOM after updating the state when invoking 97 | * `props.onEdit()` in the `handleEdit` method above. 98 | * For more info refer to notes at https://facebook.github.io/react/docs/component-api.html#setstate 99 | * and https://facebook.github.io/react/docs/component-specs.html#updating-componentdidupdate 100 | */ 101 | public void componentDidUpdate(TodoItemProps prevProps, TodoItemProps prevState) { 102 | 103 | if (!prevProps.isEditing && props.isEditing) { 104 | HTMLInputElement inputEl = (HTMLInputElement)this.refs.get("editField"); 105 | inputEl.focus(); 106 | inputEl.select(); 107 | } 108 | } 109 | 110 | public ReactElement render() { 111 | return 112 | li(new HtmlProps() 113 | .className(Classnames.get("completed", props.todo.completed, "editing", props.isEditing)), 114 | div(new HtmlProps().className("view"), 115 | input(new InputProps() 116 | .className("toggle") 117 | .type(InputType.checkbox).checked(props.todo.completed) 118 | .onChange((event) -> props.doAction.accept(TodoList.Action.TOGGLE, props.todo))), 119 | label(new LabelProps() 120 | .onDoubleClick(this::handleEdit), props.todo.title), 121 | button(new BtnProps() 122 | .className("destroy") 123 | .onClick((event) -> props.doAction.accept(TodoList.Action.DESTROY, props.todo))) 124 | ), 125 | input(new InputProps() 126 | .ref("editField") 127 | .className("edit") 128 | .defaultValue(state.editText) 129 | .onBlur(this::submitTodo) 130 | .onChange(this::handleChange) 131 | .onKeyDown(this::handleKeyDown)) 132 | ); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /web/css/gwt.css: -------------------------------------------------------------------------------- 1 | /** 2 | * The file contains styles for GWT widgets in the Clean theme. 3 | * 4 | * In order to maintain cross-browser compatibility, the following syntax is 5 | * used to create IE6 specific style rules: 6 | * .gwt-Widget { 7 | * property: rule applies to all browsers 8 | * -property: rule applies only to IE6 (overrides previous rule) 9 | * } 10 | * * html .gwt-Widget { 11 | * property: rule applies to all versions of IE 12 | * } 13 | */ 14 | 15 | body, table td, select, button { 16 | font-family: Arial Unicode MS, Arial, sans-serif; 17 | font-size: small; 18 | } 19 | pre { 20 | font-family: "courier new", courier; 21 | font-size: small; 22 | } 23 | body { 24 | color: black; 25 | margin: 0px; 26 | border: 0px; 27 | padding: 0px; 28 | background: #fff; 29 | direction: ltr; 30 | } 31 | a, a:visited { 32 | color: #0066cc; 33 | text-decoration:none; 34 | } 35 | 36 | a:hover { 37 | cursor: hand; 38 | color: #0066cc; 39 | text-decoration:underline; 40 | } 41 | 42 | select { 43 | background: white; 44 | } 45 | 46 | /** 47 | * The reference theme can be used to determine when this style sheet has 48 | * loaded. Create a hidden div element with absolute position, assign the style 49 | * name below, and attach it to the DOM. Use a timer to detect when the 50 | * element's height and width are set to 5px. 51 | */ 52 | .gwt-Reference-clean { 53 | height: 5px; 54 | width: 5px; 55 | zoom: 1; 56 | } 57 | 58 | .gwt-FileUpload { 59 | } 60 | 61 | .gwt-Frame { 62 | border-top: 2px solid #666; 63 | border-left: 2px solid #666; 64 | border-right: 2px solid #bbb; 65 | border-bottom: 2px solid #bbb; 66 | } 67 | 68 | .gwt-HTML { 69 | padding: 0 0px; 70 | } 71 | 72 | .gwt-Hyperlink { 73 | } 74 | 75 | .gwt-Image { 76 | } 77 | 78 | .gwt-Label { 79 | } 80 | 81 | .gwt-ListBox { 82 | } 83 | 84 | .gwt-PopupPanel { 85 | border: 3px solid #e7e7e7; 86 | padding: 3px; 87 | background: white; 88 | } 89 | 90 | .gwt-DecoratedPopupPanel .popupContent { 91 | } 92 | .gwt-DecoratedPopupPanel .popupMiddleCenter { 93 | padding: 3px; 94 | background: #f1f1f1; 95 | } 96 | .gwt-DecoratedPopupPanel .popupTopLeftInner { 97 | width: 6px; 98 | height: 5px; 99 | zoom: 1; 100 | } 101 | .gwt-DecoratedPopupPanel .popupTopRightInner { 102 | width: 6px; 103 | height: 5px; 104 | zoom: 1; 105 | } 106 | .gwt-DecoratedPopupPanel .popupBottomLeftInner { 107 | width: 6px; 108 | height: 6px; 109 | zoom: 1; 110 | } 111 | .gwt-DecoratedPopupPanel .popupBottomRightInner { 112 | width: 6px; 113 | height: 6px; 114 | zoom: 1; 115 | } 116 | * html .gwt-DecoratedPopupPanel .popupTopLeftInner { 117 | width: 6px; 118 | height: 5px; 119 | overflow: hidden; 120 | } 121 | * html .gwt-DecoratedPopupPanel .popupTopRightInner { 122 | width: 6px; 123 | height: 5px; 124 | overflow: hidden; 125 | } 126 | * html .gwt-DecoratedPopupPanel .popupBottomLeftInner { 127 | width: 6px; 128 | height: 6px; 129 | overflow: hidden; 130 | } 131 | * html .gwt-DecoratedPopupPanel .popupBottomRightInner { 132 | width: 6px; 133 | height: 6px; 134 | overflow: hidden; 135 | } 136 | 137 | .gwt-PopupPanelGlass { 138 | background-color: #000; 139 | opacity: 0.3; 140 | filter: alpha(opacity=30); 141 | } 142 | 143 | .gwt-RadioButton { 144 | } 145 | .gwt-RadioButton-disabled { 146 | color: #888; 147 | } 148 | 149 | .gwt-RichTextArea { 150 | } 151 | 152 | .gwt-TextArea { 153 | padding: 4px; 154 | border: 1px solid #ccc; 155 | border-top: 1px solid #666; 156 | font-size: 100%; 157 | font-family: Arial Unicode MS, Arial, sans-serif; 158 | } 159 | .gwt-TextArea-readonly { 160 | color: #888; 161 | } 162 | 163 | .gwt-TextBox { 164 | padding: 2px 1px; 165 | border: 1px solid #ccc; 166 | border-top: 1px solid #999; 167 | font-size: small; 168 | font-family: Arial Unicode MS, Arial, sans-serif; 169 | } 170 | .gwt-TextBox-readonly { 171 | color: #888; 172 | } 173 | 174 | .gwt-Tree .gwt-TreeItem { 175 | padding: 1px 0px; 176 | margin: 0px; 177 | white-space: nowrap; 178 | cursor: hand; 179 | cursor: pointer; 180 | } 181 | .gwt-Tree .gwt-TreeItem-selected { 182 | background: #ebeff9; 183 | } 184 | .gwt-TreeItem .gwt-RadioButton input, 185 | .gwt-TreeItem .gwt-CheckBox input { 186 | margin-left: 0px; 187 | } 188 | * html .gwt-TreeItem .gwt-RadioButton input, 189 | * html .gwt-TreeItem .gwt-CheckBox input { 190 | margin-left: -4px; 191 | } 192 | 193 | .gwt-DateBox { 194 | padding: 5px 4px; 195 | border: 1px solid #ccc; 196 | border-top: 1px solid #999; 197 | font-size: 100%; 198 | } 199 | .gwt-DateBox input { 200 | width: 8em; 201 | } 202 | .dateBoxFormatError { 203 | background: #ffcccc; 204 | } 205 | .dateBoxPopup { 206 | z-index: 1000000; 207 | } 208 | 209 | .gwt-DatePicker { 210 | border: 1px solid #ccc; 211 | border-top:1px solid #999; 212 | cursor: default; 213 | } 214 | .gwt-DatePicker td, 215 | .datePickerMonthSelector td:focus { 216 | outline: none; 217 | } 218 | .datePickerDays { 219 | width: 100%; 220 | background: white; 221 | } 222 | .datePickerDay, 223 | .datePickerWeekdayLabel, 224 | .datePickerWeekendLabel { 225 | font-size: 85%; 226 | text-align: center; 227 | padding: 4px; 228 | outline: none; 229 | font-weight:bold; 230 | color:#333; 231 | border-right: 1px solid #EDEDED; 232 | border-bottom: 1px solid #EDEDED; 233 | } 234 | .datePickerWeekdayLabel, 235 | .datePickerWeekendLabel { 236 | background: #fff; 237 | padding: 0px 4px 2px; 238 | cursor: default; 239 | color:#666; 240 | font-size:70%; 241 | font-weight:normal; 242 | } 243 | .datePickerDay { 244 | padding: 4px 7px; 245 | cursor: hand; 246 | cursor: pointer; 247 | } 248 | .datePickerDayIsWeekend { 249 | background: #f7f7f7; 250 | } 251 | .datePickerDayIsFiller { 252 | color: #999; 253 | font-weight:normal; 254 | } 255 | .datePickerDayIsValue { 256 | background: #d7dfe8; 257 | } 258 | .datePickerDayIsDisabled { 259 | color: #AAAAAA; 260 | font-style: italic; 261 | } 262 | .datePickerDayIsHighlighted { 263 | background: #F0E68C; 264 | } 265 | .datePickerDayIsValueAndHighlighted { 266 | background: #d7dfe8; 267 | } 268 | .datePickerDayIsToday { 269 | padding: 3px; 270 | color: #fff; 271 | } 272 | 273 | .datePickerMonthSelector { 274 | width: 100%; 275 | padding: 1px 0 5px 0; 276 | background: #fff; 277 | } 278 | td.datePickerMonth { 279 | text-align: center; 280 | vertical-align: middle; 281 | white-space: nowrap; 282 | font-size: 100%; 283 | font-weight: bold; 284 | color: #333; 285 | } 286 | .datePickerPreviousButton, 287 | .datePickerNextButton { 288 | font-size: 120%; 289 | line-height: 1em; 290 | color: #3a6aad; 291 | cursor: hand; 292 | cursor: pointer; 293 | font-weight: bold; 294 | padding: 0px 4px; 295 | outline: none; 296 | } 297 | 298 | /* Application styles */ 299 | -------------------------------------------------------------------------------- /src/gwt/react/todo_mvc/client/TodoList.java: -------------------------------------------------------------------------------- 1 | package gwt.react.todo_mvc.client; 2 | 3 | import elemental2.dom.HTMLInputElement; 4 | import gwt.interop.utils.client.plainobjects.JsPlainObj; 5 | import gwt.interop.utils.shared.collections.Array; 6 | import gwt.react.client.api.React; 7 | import gwt.react.client.components.Component; 8 | import gwt.react.client.elements.ReactElement; 9 | import gwt.react.client.events.FormEvent; 10 | import gwt.react.client.events.KeyboardEvent; 11 | import gwt.react.client.events.MouseEvent; 12 | import gwt.react.client.proptypes.BaseProps; 13 | import gwt.react.client.proptypes.html.HtmlProps; 14 | import gwt.react.client.proptypes.html.InputProps; 15 | import gwt.react.client.proptypes.html.attributeTypes.InputType; 16 | import gwt.react_router.client.HistoryLocation; 17 | import gwt.react_router.client.RouterEnhancedProps; 18 | import jsinterop.annotations.JsPackage; 19 | import jsinterop.annotations.JsProperty; 20 | import jsinterop.annotations.JsType; 21 | 22 | import java.util.Objects; 23 | 24 | import static gwt.interop.utils.client.plainobjects.JsPlainObj.$; 25 | import static gwt.react.client.api.GwtReact.castAsReactElement; 26 | import static gwt.react.client.api.React.DOM.*; 27 | 28 | @JsType 29 | class TodoList extends Component { 30 | 31 | final static String NOW_SHOWING_ACTIVE_TODOS = "active"; 32 | final static String NOW_SHOWING_COMPLETED_TODOS = "completed"; 33 | 34 | enum Action { EDIT, DESTROY, TOGGLE, CANCEL } 35 | 36 | @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object") 37 | static class TodoRouterParams { 38 | String nowShowing; 39 | } 40 | 41 | @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object") 42 | static class TodoListProps extends BaseProps implements RouterEnhancedProps{ 43 | 44 | //Having to define the JsProperty annotations again when implementing an interface 45 | //has been logged as an issue that should be fixed in the future 46 | @JsProperty(name="location") 47 | public native HistoryLocation getRouterLocation(); 48 | 49 | @JsProperty(name="params") 50 | public native TodoRouterParams getRouterParams(); 51 | } 52 | 53 | @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object") 54 | static class TodoListState extends JsPlainObj { 55 | String editingId; 56 | String newTodo; 57 | } 58 | 59 | public TodoList(TodoList.TodoListProps props) { 60 | super(props); 61 | state = $(new TodoListState(), "editingId",null, "newTodo",""); 62 | } 63 | 64 | private void handleDoAction(Action action, TodoModel.Todo todo) { 65 | switch(action) { 66 | case TOGGLE : 67 | App.model.toggle(todo); 68 | break; 69 | case CANCEL: 70 | setState($(new TodoListState(),"editingId", null)); 71 | break; 72 | case DESTROY: 73 | App.model.destroy(todo); 74 | break; 75 | case EDIT: 76 | setState($(new TodoListState(),"editingId", todo.id)); 77 | } 78 | } 79 | 80 | private void handleSave(TodoModel.Todo todoToSave, String text) { 81 | App.model.save(todoToSave, text); 82 | setState($(new TodoListState(),"editingId", null)); 83 | } 84 | 85 | private void handleClearCompleted(MouseEvent event) { 86 | App.model.clearCompleted(); 87 | } 88 | 89 | private void handleToggleAll(FormEvent event) { 90 | App.model.toggleAll(((HTMLInputElement)event.target).checked); 91 | } 92 | 93 | private void handleNewTodoKeyDown(KeyboardEvent event) { 94 | if (event.keyCode != App.ENTER_KEY) { 95 | return; 96 | } 97 | 98 | event.preventDefault(); 99 | 100 | String val = state.newTodo.trim(); 101 | 102 | if (val.length() > 0) { 103 | App.model.addTodo(val); 104 | setState($(new TodoListState(), "newTodo", "")); 105 | } 106 | } 107 | 108 | private void handleChange(FormEvent event) { 109 | setState($(new TodoListState(),"newTodo", (((HTMLInputElement)event.target).value))); 110 | } 111 | 112 | public ReactElement render() { 113 | ReactElement footer = null; 114 | ReactElement main = null; 115 | Array todos = App.model.todos; 116 | String nowShowing = props.getRouterParams().nowShowing; 117 | 118 | Array shownTodos = todos.filter((todo, index, theArray) -> { 119 | if (nowShowing == null) { 120 | return true; 121 | }else if (nowShowing.equals(NOW_SHOWING_ACTIVE_TODOS)){ 122 | return !todo.completed; 123 | }else { 124 | return todo.completed; 125 | } 126 | }); 127 | 128 | Array todoItems = shownTodos.map((todo, index, theArray) -> { 129 | TodoItem.TodoItemProps todoProps = new TodoItem.TodoItemProps(); 130 | 131 | todoProps.key = todo.id; 132 | todoProps.todo = todo; 133 | todoProps.doAction = this::handleDoAction; 134 | todoProps.doSave = this::handleSave; 135 | todoProps.isEditing = Objects.equals(state.editingId, todo.id); 136 | 137 | return React.createElement(TodoItem.class, todoProps); 138 | }); 139 | 140 | Integer activeTodoCount = todos.reduce((accum, currentValue, index, theArray) -> 141 | currentValue.completed ? accum : accum + 1, 0); 142 | 143 | int completedCount = todos.getLength() - activeTodoCount; 144 | 145 | if (activeTodoCount > 0 || completedCount > 0) { 146 | Footer.FooterProps footerProps = new Footer.FooterProps(); 147 | footerProps.count = activeTodoCount; 148 | footerProps.completedCount = completedCount; 149 | footerProps.nowShowing = props.getRouterParams().nowShowing; 150 | footerProps.onClearCompleted = this::handleClearCompleted; 151 | 152 | footer = React.createElement(Footer.component, footerProps); 153 | } 154 | 155 | if (todos.getLength() > 0) { 156 | main = section(new HtmlProps() 157 | .className("header"), 158 | input(new InputProps() 159 | .className("toggle-all") 160 | .type(InputType.checkbox) 161 | .onChange(this::handleToggleAll)), 162 | ul(new HtmlProps() 163 | .className("todo-list"), 164 | castAsReactElement(todoItems) 165 | ) 166 | ); 167 | } 168 | 169 | return 170 | div(null, 171 | header(new HtmlProps() 172 | .className("header"), 173 | h1(null, "todos"), 174 | input(new InputProps() 175 | .className("new-todo") 176 | .placeholder("What needs to be done?") 177 | .value(state.newTodo) 178 | .onKeyDown(this::handleNewTodoKeyDown) 179 | .onChange(this::handleChange) 180 | .autoFocus(true)) 181 | ), 182 | main, 183 | footer 184 | ); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /web/css/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | button { 8 | margin: 0; 9 | padding: 0; 10 | border: 0; 11 | background: none; 12 | font-size: 100%; 13 | vertical-align: baseline; 14 | font-family: inherit; 15 | font-weight: inherit; 16 | color: inherit; 17 | -webkit-appearance: none; 18 | appearance: none; 19 | -webkit-font-smoothing: antialiased; 20 | -moz-font-smoothing: antialiased; 21 | font-smoothing: antialiased; 22 | } 23 | 24 | body { 25 | font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; 26 | line-height: 1.4em; 27 | background: #f5f5f5; 28 | color: #4d4d4d; 29 | min-width: 230px; 30 | max-width: 550px; 31 | margin: 0 auto; 32 | -webkit-font-smoothing: antialiased; 33 | -moz-font-smoothing: antialiased; 34 | font-smoothing: antialiased; 35 | font-weight: 300; 36 | } 37 | 38 | button, 39 | input[type="checkbox"] { 40 | outline: none; 41 | } 42 | 43 | .hidden { 44 | display: none; 45 | } 46 | 47 | .todoapp { 48 | background: #fff; 49 | margin: 130px 0 40px 0; 50 | position: relative; 51 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 52 | 0 25px 50px 0 rgba(0, 0, 0, 0.1); 53 | } 54 | 55 | .todoapp input::-webkit-input-placeholder { 56 | font-style: italic; 57 | font-weight: 300; 58 | color: #e6e6e6; 59 | } 60 | 61 | .todoapp input::-moz-placeholder { 62 | font-style: italic; 63 | font-weight: 300; 64 | color: #e6e6e6; 65 | } 66 | 67 | .todoapp input::input-placeholder { 68 | font-style: italic; 69 | font-weight: 300; 70 | color: #e6e6e6; 71 | } 72 | 73 | .todoapp h1 { 74 | position: absolute; 75 | top: -155px; 76 | width: 100%; 77 | font-size: 100px; 78 | font-weight: 100; 79 | text-align: center; 80 | color: rgba(175, 47, 47, 0.15); 81 | -webkit-text-rendering: optimizeLegibility; 82 | -moz-text-rendering: optimizeLegibility; 83 | text-rendering: optimizeLegibility; 84 | } 85 | 86 | .new-todo, 87 | .edit { 88 | position: relative; 89 | margin: 0; 90 | width: 100%; 91 | font-size: 24px; 92 | font-family: inherit; 93 | font-weight: inherit; 94 | line-height: 1.4em; 95 | border: 0; 96 | outline: none; 97 | color: inherit; 98 | padding: 6px; 99 | border: 1px solid #999; 100 | box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); 101 | box-sizing: border-box; 102 | -webkit-font-smoothing: antialiased; 103 | -moz-font-smoothing: antialiased; 104 | font-smoothing: antialiased; 105 | } 106 | 107 | .new-todo { 108 | padding: 16px 16px 16px 60px; 109 | border: none; 110 | background: rgba(0, 0, 0, 0.003); 111 | box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); 112 | } 113 | 114 | .main { 115 | position: relative; 116 | z-index: 2; 117 | border-top: 1px solid #e6e6e6; 118 | } 119 | 120 | label[for='toggle-all'] { 121 | display: none; 122 | } 123 | 124 | .toggle-all { 125 | position: absolute; 126 | top: -55px; 127 | left: -12px; 128 | width: 60px; 129 | height: 34px; 130 | text-align: center; 131 | border: none; /* Mobile Safari */ 132 | } 133 | 134 | .toggle-all:before { 135 | content: '❯'; 136 | font-size: 22px; 137 | color: #e6e6e6; 138 | padding: 10px 27px 10px 27px; 139 | } 140 | 141 | .toggle-all:checked:before { 142 | color: #737373; 143 | } 144 | 145 | .todo-list { 146 | margin: 0; 147 | padding: 0; 148 | list-style: none; 149 | } 150 | 151 | .todo-list li { 152 | position: relative; 153 | font-size: 24px; 154 | border-bottom: 1px solid #ededed; 155 | } 156 | 157 | .todo-list li:last-child { 158 | border-bottom: none; 159 | } 160 | 161 | .todo-list li.editing { 162 | border-bottom: none; 163 | padding: 0; 164 | } 165 | 166 | .todo-list li.editing .edit { 167 | display: block; 168 | width: 506px; 169 | padding: 13px 17px 12px 17px; 170 | margin: 0 0 0 43px; 171 | } 172 | 173 | .todo-list li.editing .view { 174 | display: none; 175 | } 176 | 177 | .todo-list li .toggle { 178 | text-align: center; 179 | width: 40px; 180 | /* auto, since non-WebKit browsers doesn't support input styling */ 181 | height: auto; 182 | position: absolute; 183 | top: 0; 184 | bottom: 0; 185 | margin: auto 0; 186 | border: none; /* Mobile Safari */ 187 | -webkit-appearance: none; 188 | appearance: none; 189 | } 190 | 191 | .todo-list li .toggle:after { 192 | content: url('data:image/svg+xml;utf8,'); 193 | } 194 | 195 | .todo-list li .toggle:checked:after { 196 | content: url('data:image/svg+xml;utf8,'); 197 | } 198 | 199 | .todo-list li label { 200 | white-space: pre-line; 201 | word-break: break-all; 202 | padding: 15px 60px 15px 15px; 203 | margin-left: 45px; 204 | display: block; 205 | line-height: 1.2; 206 | transition: color 0.4s; 207 | } 208 | 209 | .todo-list li.completed label { 210 | color: #d9d9d9; 211 | text-decoration: line-through; 212 | } 213 | 214 | .todo-list li .destroy { 215 | display: none; 216 | position: absolute; 217 | top: 0; 218 | right: 10px; 219 | bottom: 0; 220 | width: 40px; 221 | height: 40px; 222 | margin: auto 0; 223 | font-size: 30px; 224 | color: #cc9a9a; 225 | margin-bottom: 11px; 226 | transition: color 0.2s ease-out; 227 | } 228 | 229 | .todo-list li .destroy:hover { 230 | color: #af5b5e; 231 | } 232 | 233 | .todo-list li .destroy:after { 234 | content: '×'; 235 | } 236 | 237 | .todo-list li:hover .destroy { 238 | display: block; 239 | } 240 | 241 | .todo-list li .edit { 242 | display: none; 243 | } 244 | 245 | .todo-list li.editing:last-child { 246 | margin-bottom: -1px; 247 | } 248 | 249 | .footer { 250 | color: #777; 251 | padding: 10px 15px; 252 | height: 20px; 253 | text-align: center; 254 | border-top: 1px solid #e6e6e6; 255 | } 256 | 257 | .footer:before { 258 | content: ''; 259 | position: absolute; 260 | right: 0; 261 | bottom: 0; 262 | left: 0; 263 | height: 50px; 264 | overflow: hidden; 265 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 266 | 0 8px 0 -3px #f6f6f6, 267 | 0 9px 1px -3px rgba(0, 0, 0, 0.2), 268 | 0 16px 0 -6px #f6f6f6, 269 | 0 17px 2px -6px rgba(0, 0, 0, 0.2); 270 | } 271 | 272 | .todo-count { 273 | float: left; 274 | text-align: left; 275 | } 276 | 277 | .todo-count strong { 278 | font-weight: 300; 279 | } 280 | 281 | .filters { 282 | margin: 0; 283 | padding: 0; 284 | list-style: none; 285 | position: absolute; 286 | right: 0; 287 | left: 0; 288 | } 289 | 290 | .filters li { 291 | display: inline; 292 | } 293 | 294 | .filters li a { 295 | color: inherit; 296 | margin: 3px; 297 | padding: 3px 7px; 298 | text-decoration: none; 299 | border: 1px solid transparent; 300 | border-radius: 3px; 301 | } 302 | 303 | .filters li a.selected, 304 | .filters li a:hover { 305 | border-color: rgba(175, 47, 47, 0.1); 306 | } 307 | 308 | .filters li a.selected { 309 | border-color: rgba(175, 47, 47, 0.2); 310 | } 311 | 312 | .clear-completed, 313 | html .clear-completed:active { 314 | float: right; 315 | position: relative; 316 | line-height: 20px; 317 | text-decoration: none; 318 | cursor: pointer; 319 | position: relative; 320 | } 321 | 322 | .clear-completed:hover { 323 | text-decoration: underline; 324 | } 325 | 326 | .info { 327 | margin: 65px auto 0; 328 | color: #bfbfbf; 329 | font-size: 10px; 330 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); 331 | text-align: center; 332 | } 333 | 334 | .info p { 335 | line-height: 1; 336 | } 337 | 338 | .info a { 339 | color: inherit; 340 | text-decoration: none; 341 | font-weight: 400; 342 | } 343 | 344 | .info a:hover { 345 | text-decoration: underline; 346 | } 347 | 348 | /* 349 | Hack to remove background from Mobile Safari. 350 | Can't use it globally since it destroys checkboxes in Firefox 351 | */ 352 | @media screen and (-webkit-min-device-pixel-ratio:0) { 353 | .toggle-all, 354 | .todo-list li .toggle { 355 | background: none; 356 | } 357 | 358 | .todo-list li .toggle { 359 | height: 40px; 360 | } 361 | 362 | .toggle-all { 363 | -webkit-transform: rotate(90deg); 364 | transform: rotate(90deg); 365 | -webkit-appearance: none; 366 | appearance: none; 367 | } 368 | } 369 | 370 | @media (max-width: 430px) { 371 | .footer { 372 | height: 50px; 373 | } 374 | 375 | .filters { 376 | bottom: 10px; 377 | } 378 | } -------------------------------------------------------------------------------- /web/dist/gwt-preact-bundle.min.js: -------------------------------------------------------------------------------- 1 | !function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return e[r].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}var o=n(1),i=r(o),a=n(1),u=r(a),l=n(4),c=r(l);window.React=i.default,window.ReactDOM=u.default,window.ReactDOMServer=c.default;var p={};p.cast=function(e){return e},window.GWTReact=p},function(e,t,n){(function(t){!function(t,r){e.exports=r(n(9),n(6))}(this,function(e,n){function r(){return null}function o(e){var t=e.nodeName,n=e.attributes;e.attributes={},t.defaultProps&&x(e.attributes,t.defaultProps),n&&x(e.attributes,n)}function i(e,t){var n,r,o;if(t){for(o in t)if(n=I.test(o))break;if(n){r=e.attributes={};for(o in t)t.hasOwnProperty(o)&&(r[I.test(o)?o.replace(/([A-Z0-9])/,"-$1").toLowerCase():o]=t[o])}}}function a(e,t,r){var o=t&&t._preactCompatRendered&&t._preactCompatRendered.base;o&&o.parentNode!==t&&(o=null),o||(o=t.children[0]);for(var i=t.childNodes.length;i--;)t.childNodes[i]!==o&&t.removeChild(t.childNodes[i]);var a=n.render(e,t,o);return t&&(t._preactCompatRendered=a&&(a._component||{base:a})),"function"==typeof r&&r(),a&&a._component||a}function u(e,t,r,o){var i=n.h(B,{context:e.context},t),u=a(i,r);return o&&o(u),u._component||u.base}function l(e){var t=e._preactCompatRendered&&e._preactCompatRendered.base;return!(!t||t.parentNode!==e)&&(n.render(n.h(r),e,t),!0)}function c(e){return h.bind(null,e)}function p(e,t){for(var n=t||0;n0;)r[o]=arguments[o+2];if(!_(e))return e;var i=e.attributes||e.props,a=n.h(e.nodeName||e.type,i,e.children||i&&i.children),u=[a,t];return r&&r.length?u.push(r):t&&t.children&&u.push(t.children),m(n.cloneElement.apply(void 0,u))}function _(e){return e&&(e instanceof F||e.$$typeof===V)}function y(e,t){return t._refProxies[e]||(t._refProxies[e]=function(n){t&&t.refs&&(t.refs[e]=n,null===n&&(delete t._refProxies[e],t=null))})}function b(e){var t=e.nodeName,n=e.attributes;if(n&&"string"==typeof t){var r={};for(var o in n)r[o.toLowerCase()]=o;if(r.ondoubleclick&&(n.ondblclick=n[r.ondoubleclick],delete n[r.ondoubleclick]),r.onchange&&("textarea"===t||"input"===t.toLowerCase()&&!/^fil|che|rad/i.test(n.type))){var i=r.oninput||"oninput";n[i]||(n[i]=R([n[i],n[r.onchange]]),delete n[r.onchange])}}}function g(e){var t=e.attributes;if(t){var n=t.className||t.class;n&&(t.className=n)}}function x(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}function w(e,t){for(var n in e)if(!(n in t))return!0;for(var r in t)if(e[r]!==t[r])return!0;return!1}function C(e){return e&&e.base||e}function N(){}function k(e){function t(e,t){O(this),E.call(this,e,t,z),A.call(this,e,t)}return e=x({constructor:t},e),e.mixins&&P(e,T(e.mixins)),e.statics&&x(t,e.statics),e.propTypes&&(t.propTypes=e.propTypes),e.defaultProps&&(t.defaultProps=e.defaultProps),e.getDefaultProps&&(t.defaultProps=e.getDefaultProps()),N.prototype=E.prototype,t.prototype=x(new N,e),t.displayName=e.displayName||"Component",t}function T(e){for(var t={},n=0;n",g.indexOf(_)>-1&&(O=O.replace(/>$/," />")),S)C&&m(S)&&(S="\n"+N+h(S,N)),O+=S;else{for(var W=x&&x.length,j=[],D=~O.indexOf("\n"),V=0;V"}return(l.jsx||g.indexOf(_)===-1)&&(C&&~O.indexOf("\n")&&(O+="\n"),O+=""),O}function i(e){var t=e.prototype;t&&t.constructor;return e.displayName||e.name||t&&(t.displayName||t.name)||a(e)}function a(e){var t=Function.prototype.toString.call(e),n=(t.match(/^\s*function\s+([^\( ]+)/)||b)[1];if(!n){for(var r=-1,o=y.length;o--;)if(y[o]===e){r=o;break}r<0&&(r=y.push(e)-1),n="UnnamedComponent"+r}return n}var u={boxFlex:1,boxFlexGroup:1,columnCount:1,fillOpacity:1,flex:1,flexGrow:1,flexPositive:1,flexShrink:1,flexNegative:1,fontWeight:1,lineClamp:1,lineHeight:1,opacity:1,order:1,orphans:1,strokeOpacity:1,widows:1,zIndex:1,zoom:1},l={"<":"<",">":">",'"':""","&":"&"},c=Object.keys||function(e){var t=[];for(var n in e)e.hasOwnProperty(n)&&t.push(n);return t},p=function(e){return String(e).replace(/[<>"&]/g,s)},s=function(e){return l[e]||e},f=function(e){return null==e||e===!1},d=function(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1];return function(n){return t[n]||(t[n]=e(n))}},h=function(e,t){return String(e).replace(/(\n+)/g,"$1"+(t||"\t"))},m=function(e,t,n){return String(e).length>(t||40)||!n&&String(e).indexOf("\n")!==-1||String(e).indexOf("<")!==-1},v=d(function(e){return e.replace(/([A-Z])/g,"-$1").toLowerCase()}),_={shallow:!0},y=[],b={},g=["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"];o.render=o;var x=function(e,t){return o(e,t,_)};return o.shallowRender=x,o})},function(e,t,n){!function(){"use strict";function t(){}function n(e,n){var r,o,i,a,u=M;for(a=arguments.length;a-- >2;)U.push(arguments[a]);for(n&&null!=n.children&&(U.length||U.push(n.children),delete n.children);U.length;)if((o=U.pop())&&void 0!==o.pop)for(a=o.length;a--;)U.push(o[a]);else o!==!0&&o!==!1||(o=null),(i="function"!=typeof e)&&(null==o?o="":"number"==typeof o?o=String(o):"string"!=typeof o&&(i=!1)),i&&r?u[u.length-1]+=o:u===M?u=[o]:u.push(o),r=i;var l=new t;return l.nodeName=e,l.children=u,l.attributes=null==n?void 0:n,l.key=null==n?void 0:n.key,void 0!==A.vnode&&A.vnode(l),l}function r(e,t){for(var n in t)e[n]=t[n];return e}function o(e,t){return n(e.nodeName,r(r({},e.attributes),t),arguments.length>2?[].slice.call(arguments,2):e.children)}function i(e){!e.__d&&(e.__d=!0)&&1==E.push(e)&&(A.debounceRendering||setTimeout)(a)}function a(){var e,t=E;for(E=[];e=t.pop();)e.__d&&T(e)}function u(e,t,n){return"string"==typeof t||"number"==typeof t?void 0!==e.splitText:"string"==typeof t.nodeName?!e._componentConstructor&&l(e,t.nodeName):n||e._componentConstructor===t.nodeName}function l(e,t){return e.__n===t||e.nodeName.toLowerCase()===t.toLowerCase()}function c(e){var t=r({},e.attributes);t.children=e.children;var n=e.nodeName.defaultProps;if(void 0!==n)for(var o in n)void 0===t[o]&&(t[o]=n[o]);return t}function p(e,t){var n=t?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e);return n.__n=e,n}function s(e){e.parentNode&&e.parentNode.removeChild(e)}function f(e,t,n,r,o){if("className"===t&&(t="class"),"key"===t);else if("ref"===t)n&&n(null),r&&r(e);else if("class"!==t||o)if("style"===t){if(r&&"string"!=typeof r&&"string"!=typeof n||(e.style.cssText=r||""),r&&"object"==typeof r){if("string"!=typeof n)for(var i in n)i in r||(e.style[i]="");for(var i in r)e.style[i]="number"==typeof r[i]&&L.test(i)===!1?r[i]+"px":r[i]}}else if("dangerouslySetInnerHTML"===t)r&&(e.innerHTML=r.__html||"");else if("o"==t[0]&&"n"==t[1]){var a=t!==(t=t.replace(/Capture$/,""));t=t.toLowerCase().substring(2),r?n||e.addEventListener(t,h,a):e.removeEventListener(t,h,a),(e.__l||(e.__l={}))[t]=r}else if("list"!==t&&"type"!==t&&!o&&t in e)d(e,t,null==r?"":r),null!=r&&r!==!1||e.removeAttribute(t);else{var u=o&&t!==(t=t.replace(/^xlink\:?/,""));null==r||r===!1?u?e.removeAttributeNS("http://www.w3.org/1999/xlink",t.toLowerCase()):e.removeAttribute(t):"function"!=typeof r&&(u?e.setAttributeNS("http://www.w3.org/1999/xlink",t.toLowerCase(),r):e.setAttribute(t,r))}else e.className=r||""}function d(e,t,n){try{e[t]=n}catch(e){}}function h(e){return this.__l[e.type](A.event&&A.event(e)||e)}function m(){for(var e;e=W.pop();)A.afterMount&&A.afterMount(e),e.componentDidMount&&e.componentDidMount()}function v(e,t,n,r,o,i){j++||(D=null!=o&&void 0!==o.ownerSVGElement,V=null!=e&&!("__preactattr_"in e));var a=_(e,t,n,r,i);return o&&a.parentNode!==o&&o.appendChild(a),--j||(V=!1,i||m()),a}function _(e,t,n,r,o){var i=e,a=D;if(null==t&&(t=""),"string"==typeof t)return e&&void 0!==e.splitText&&e.parentNode&&(!e._component||o)?e.nodeValue!=t&&(e.nodeValue=t):(i=document.createTextNode(t),e&&(e.parentNode&&e.parentNode.replaceChild(i,e),b(e,!0))),i.__preactattr_=!0,i;if("function"==typeof t.nodeName)return P(e,t,n,r);if(D="svg"===t.nodeName||"foreignObject"!==t.nodeName&&D,(!e||!l(e,String(t.nodeName)))&&(i=p(String(t.nodeName),D),e)){for(;e.firstChild;)i.appendChild(e.firstChild);e.parentNode&&e.parentNode.replaceChild(i,e),b(e,!0)}var u=i.firstChild,c=i.__preactattr_||(i.__preactattr_={}),s=t.children;return!V&&s&&1===s.length&&"string"==typeof s[0]&&null!=u&&void 0!==u.splitText&&null==u.nextSibling?u.nodeValue!=s[0]&&(u.nodeValue=s[0]):(s&&s.length||null!=u)&&y(i,s,n,r,V||null!=c.dangerouslySetInnerHTML),x(i,t.attributes,c),D=a,i}function y(e,t,n,r,o){var i,a,l,c,p=e.childNodes,f=[],d={},h=0,m=0,v=p.length,y=0,g=t?t.length:0;if(0!==v)for(var x=0;x=v?e.appendChild(c):c!==p[x]&&(c===p[x+1]?s(p[x]):e.insertBefore(c,p[x]||null)))}if(h)for(var x in d)void 0!==d[x]&&b(d[x],!1);for(;m<=y;)void 0!==(c=f[y--])&&b(c,!1)}function b(e,t){var n=e._component;n?O(n):(null!=e.__preactattr_&&e.__preactattr_.ref&&e.__preactattr_.ref(null),t!==!1&&null!=e.__preactattr_||s(e),g(e))}function g(e){for(e=e.lastChild;e;){var t=e.previousSibling;b(e,!0),e=t}}function x(e,t,n){var r;for(r in n)t&&null!=t[r]||null==n[r]||f(e,r,n[r],n[r]=void 0,D);for(r in t)"children"===r||"innerHTML"===r||r in n&&t[r]===("value"===r||"checked"===r?e[r]:n[r])||f(e,r,n[r],n[r]=t[r],D)}function w(e){var t=e.constructor.name;($[t]||($[t]=[])).push(e)}function C(e,t,n){var r,o=$[e.name];if(e.prototype&&e.prototype.render?(r=new e(t,n),S.call(r,t,n)):(r=new S(t,n),r.constructor=e,r.render=N),o)for(var i=o.length;i--;)if(o[i].constructor===e){r.__b=o[i].__b,o.splice(i,1);break}return r}function N(e,t,n){return this.constructor(e,n)}function k(e,t,n,r,o){e.__x||(e.__x=!0,(e.__r=t.ref)&&delete t.ref,(e.__k=t.key)&&delete t.key,!e.base||o?e.componentWillMount&&e.componentWillMount():e.componentWillReceiveProps&&e.componentWillReceiveProps(t,r),r&&r!==e.context&&(e.__c||(e.__c=e.context),e.context=r),e.__p||(e.__p=e.props),e.props=t,e.__x=!1,0!==n&&(1!==n&&A.syncComponentUpdates===!1&&e.base?i(e):T(e,1,o)),e.__r&&e.__r(e))}function T(e,t,n,o){if(!e.__x){var i,a,u,l=e.props,p=e.state,s=e.context,f=e.__p||l,d=e.__s||p,h=e.__c||s,_=e.base,y=e.__b,g=_||y,x=e._component,w=!1;if(_&&(e.props=f,e.state=d,e.context=h,2!==t&&e.shouldComponentUpdate&&e.shouldComponentUpdate(l,p,s)===!1?w=!0:e.componentWillUpdate&&e.componentWillUpdate(l,p,s),e.props=l,e.state=p,e.context=s),e.__p=e.__s=e.__c=e.__b=null,e.__d=!1,!w){i=e.render(l,p,s),e.getChildContext&&(s=r(r({},s),e.getChildContext()));var N,P,S=i&&i.nodeName;if("function"==typeof S){var R=c(i);a=x,a&&a.constructor===S&&R.key==a.__k?k(a,R,1,s,!1):(N=a,e._component=a=C(S,R,s),a.__b=a.__b||y,a.__u=e,k(a,R,0,s,!1),T(a,1,n,!0)),P=a.base}else u=g,N=x,N&&(u=e._component=null),(g||1===t)&&(u&&(u._component=null),P=v(u,i,s,n||!_,g&&g.parentNode,!0));if(g&&P!==g&&a!==x){var U=g.parentNode;U&&P!==U&&(U.replaceChild(P,g),N||(g._component=null,b(g,!1)))}if(N&&O(N),e.base=P,P&&!o){for(var M=e,L=e;L=L.__u;)(M=L).base=P;P._component=M,P._componentConstructor=M.constructor}}if(!_||n?W.unshift(e):w||(m(),e.componentDidUpdate&&e.componentDidUpdate(f,d,h),A.afterUpdate&&A.afterUpdate(e)),null!=e.__h)for(;e.__h.length;)e.__h.pop().call(e);j||o||m()}}function P(e,t,n,r){for(var o=e&&e._component,i=o,a=e,u=o&&e._componentConstructor===t.nodeName,l=u,p=c(t);o&&!l&&(o=o.__u);)l=o.constructor===t.nodeName;return o&&l&&(!r||o._component)?(k(o,p,3,n,r),e=o.base):(i&&!u&&(O(i),e=a=null),o=C(t.nodeName,p,n),e&&!o.__b&&(o.__b=e,a=null),k(o,p,1,n,r),e=o.base,a&&e!==a&&(a._component=null,b(a,!1))),e}function O(e){A.beforeUnmount&&A.beforeUnmount(e);var t=e.base;e.__x=!0,e.componentWillUnmount&&e.componentWillUnmount(),e.base=null;var n=e._component;n?O(n):t&&(t.__preactattr_&&t.__preactattr_.ref&&t.__preactattr_.ref(null),e.__b=t,s(t),w(e),g(t)),e.__r&&e.__r(null)}function S(e,t){this.__d=!0,this.context=t,this.props=e,this.state=this.state||{}}function R(e,t,n){return v(n,e,{},!1,t,!1)}var A={},U=[],M=[],L=/acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i,E=[],W=[],j=0,D=!1,V=!1,$={};r(S.prototype,{setState:function(e,t){var n=this.state;this.__s||(this.__s=r({},n)),r(n,"function"==typeof e?e(n,this.props):e),t&&(this.__h=this.__h||[]).push(t),i(this)},forceUpdate:function(e){e&&(this.__h=this.__h||[]).push(e),T(this,2)},render:function(){}});var H={h:n,createElement:n,cloneElement:o,Component:S,render:R,rerender:a,options:A};e.exports=H}()},function(e,t){function n(){throw new Error("setTimeout has not been defined")}function r(){throw new Error("clearTimeout has not been defined")}function o(e){if(p===setTimeout)return setTimeout(e,0);if((p===n||!p)&&setTimeout)return p=setTimeout,setTimeout(e,0);try{return p(e,0)}catch(t){try{return p.call(null,e,0)}catch(t){return p.call(this,e,0)}}}function i(e){if(s===clearTimeout)return clearTimeout(e);if((s===r||!s)&&clearTimeout)return s=clearTimeout,clearTimeout(e);try{return s(e)}catch(t){try{return s.call(null,e)}catch(t){return s.call(this,e)}}}function a(){m&&d&&(m=!1,d.length?h=d.concat(h):v=-1,h.length&&u())}function u(){if(!m){var e=o(a);m=!0;for(var t=h.length;t;){for(d=h,h=[];++v1)for(var n=1;n 0 ) children[ len ] = arguments[ len + 2 ]; 400 | 401 | if (!isValidElement(element)) { return element; } 402 | var elementProps = element.attributes || element.props; 403 | var node = preact.h( 404 | element.nodeName || element.type, 405 | elementProps, 406 | element.children || elementProps && elementProps.children 407 | ); 408 | // Only provide the 3rd argument if needed. 409 | // Arguments 3+ overwrite element.children in preactCloneElement 410 | var cloneArgs = [node, props]; 411 | if (children && children.length) { 412 | cloneArgs.push(children); 413 | } 414 | else if (props && props.children) { 415 | cloneArgs.push(props.children); 416 | } 417 | return normalizeVNode(preact.cloneElement.apply(void 0, cloneArgs)); 418 | } 419 | 420 | 421 | function isValidElement(element) { 422 | return element && ((element instanceof VNode) || element.$$typeof===REACT_ELEMENT_TYPE); 423 | } 424 | 425 | 426 | function createStringRefProxy(name, component) { 427 | return component._refProxies[name] || (component._refProxies[name] = function (resolved) { 428 | if (component && component.refs) { 429 | component.refs[name] = resolved; 430 | if (resolved===null) { 431 | delete component._refProxies[name]; 432 | component = null; 433 | } 434 | } 435 | }); 436 | } 437 | 438 | 439 | function applyEventNormalization(ref) { 440 | var nodeName = ref.nodeName; 441 | var attributes = ref.attributes; 442 | 443 | if (!attributes || typeof nodeName!=='string') { return; } 444 | var props = {}; 445 | for (var i in attributes) { 446 | props[i.toLowerCase()] = i; 447 | } 448 | if (props.ondoubleclick) { 449 | attributes.ondblclick = attributes[props.ondoubleclick]; 450 | delete attributes[props.ondoubleclick]; 451 | } 452 | // for *textual inputs* (incl textarea), normalize `onChange` -> `onInput`: 453 | if (props.onchange && (nodeName==='textarea' || (nodeName.toLowerCase()==='input' && !/^fil|che|rad/i.test(attributes.type)))) { 454 | var normalized = props.oninput || 'oninput'; 455 | if (!attributes[normalized]) { 456 | attributes[normalized] = multihook([attributes[normalized], attributes[props.onchange]]); 457 | delete attributes[props.onchange]; 458 | } 459 | } 460 | } 461 | 462 | 463 | function applyClassName(ref) { 464 | var attributes = ref.attributes; 465 | 466 | if (!attributes) { return; } 467 | var cl = attributes.className || attributes.class; 468 | if (cl) { attributes.className = cl; } 469 | } 470 | 471 | 472 | function extend(base, props) { 473 | for (var key in props) { 474 | if (props.hasOwnProperty(key)) { 475 | base[key] = props[key]; 476 | } 477 | } 478 | return base; 479 | } 480 | 481 | 482 | function shallowDiffers(a, b) { 483 | for (var i in a) { if (!(i in b)) { return true; } } 484 | for (var i$1 in b) { if (a[i$1]!==b[i$1]) { return true; } } 485 | return false; 486 | } 487 | 488 | 489 | function findDOMNode(component) { 490 | return component && component.base || component; 491 | } 492 | 493 | 494 | function F(){} 495 | 496 | function createClass(obj) { 497 | function cl(props, context) { 498 | bindAll(this); 499 | Component$1.call(this, props, context, BYPASS_HOOK); 500 | newComponentHook.call(this, props, context); 501 | } 502 | 503 | obj = extend({ constructor: cl }, obj); 504 | 505 | // We need to apply mixins here so that getDefaultProps is correctly mixed 506 | if (obj.mixins) { 507 | applyMixins(obj, collateMixins(obj.mixins)); 508 | } 509 | if (obj.statics) { 510 | extend(cl, obj.statics); 511 | } 512 | if (obj.propTypes) { 513 | cl.propTypes = obj.propTypes; 514 | } 515 | if (obj.defaultProps) { 516 | cl.defaultProps = obj.defaultProps; 517 | } 518 | if (obj.getDefaultProps) { 519 | cl.defaultProps = obj.getDefaultProps(); 520 | } 521 | 522 | F.prototype = Component$1.prototype; 523 | cl.prototype = extend(new F(), obj); 524 | 525 | cl.displayName = obj.displayName || 'Component'; 526 | 527 | return cl; 528 | } 529 | 530 | 531 | // Flatten an Array of mixins to a map of method name to mixin implementations 532 | function collateMixins(mixins) { 533 | var keyed = {}; 534 | for (var i=0; i 1) { 857 | for (var i = 1; i < arguments.length; i++) { 858 | args[i - 1] = arguments[i]; 859 | } 860 | } 861 | queue.push(new Item(fun, args)); 862 | if (queue.length === 1 && !draining) { 863 | runTimeout(drainQueue); 864 | } 865 | }; 866 | 867 | // v8 likes predictible objects 868 | function Item(fun, array) { 869 | this.fun = fun; 870 | this.array = array; 871 | } 872 | Item.prototype.run = function () { 873 | this.fun.apply(null, this.array); 874 | }; 875 | process.title = 'browser'; 876 | process.browser = true; 877 | process.env = {}; 878 | process.argv = []; 879 | process.version = ''; // empty string to avoid regexp issues 880 | process.versions = {}; 881 | 882 | function noop() {} 883 | 884 | process.on = noop; 885 | process.addListener = noop; 886 | process.once = noop; 887 | process.off = noop; 888 | process.removeListener = noop; 889 | process.removeAllListeners = noop; 890 | process.emit = noop; 891 | process.prependListener = noop; 892 | process.prependOnceListener = noop; 893 | 894 | process.listeners = function (name) { return [] } 895 | 896 | process.binding = function (name) { 897 | throw new Error('process.binding is not supported'); 898 | }; 899 | 900 | process.cwd = function () { return '/' }; 901 | process.chdir = function (dir) { 902 | throw new Error('process.chdir is not supported'); 903 | }; 904 | process.umask = function() { return 0; }; 905 | 906 | 907 | /***/ }), 908 | /* 3 */ 909 | /***/ (function(module, exports, __webpack_require__) { 910 | 911 | /* WEBPACK VAR INJECTION */(function(process) {/** 912 | * Copyright 2013-present, Facebook, Inc. 913 | * All rights reserved. 914 | * 915 | * This source code is licensed under the BSD-style license found in the 916 | * LICENSE file in the root directory of this source tree. An additional grant 917 | * of patent rights can be found in the PATENTS file in the same directory. 918 | */ 919 | 920 | if (process.env.NODE_ENV !== 'production') { 921 | var REACT_ELEMENT_TYPE = (typeof Symbol === 'function' && 922 | Symbol.for && 923 | Symbol.for('react.element')) || 924 | 0xeac7; 925 | 926 | var isValidElement = function(object) { 927 | return typeof object === 'object' && 928 | object !== null && 929 | object.$$typeof === REACT_ELEMENT_TYPE; 930 | }; 931 | 932 | // By explicitly using `prop-types` you are opting into new development behavior. 933 | // http://fb.me/prop-types-in-prod 934 | var throwOnDirectAccess = true; 935 | module.exports = __webpack_require__(4)(isValidElement, throwOnDirectAccess); 936 | } else { 937 | // By explicitly using `prop-types` you are opting into new production behavior. 938 | // http://fb.me/prop-types-in-prod 939 | module.exports = __webpack_require__(10)(); 940 | } 941 | 942 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2))) 943 | 944 | /***/ }), 945 | /* 4 */ 946 | /***/ (function(module, exports, __webpack_require__) { 947 | 948 | /* WEBPACK VAR INJECTION */(function(process) {/** 949 | * Copyright 2013-present, Facebook, Inc. 950 | * All rights reserved. 951 | * 952 | * This source code is licensed under the BSD-style license found in the 953 | * LICENSE file in the root directory of this source tree. An additional grant 954 | * of patent rights can be found in the PATENTS file in the same directory. 955 | */ 956 | 957 | 'use strict'; 958 | 959 | var emptyFunction = __webpack_require__(5); 960 | var invariant = __webpack_require__(6); 961 | var warning = __webpack_require__(7); 962 | 963 | var ReactPropTypesSecret = __webpack_require__(8); 964 | var checkPropTypes = __webpack_require__(9); 965 | 966 | module.exports = function(isValidElement, throwOnDirectAccess) { 967 | /* global Symbol */ 968 | var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; 969 | var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec. 970 | 971 | /** 972 | * Returns the iterator method function contained on the iterable object. 973 | * 974 | * Be sure to invoke the function with the iterable as context: 975 | * 976 | * var iteratorFn = getIteratorFn(myIterable); 977 | * if (iteratorFn) { 978 | * var iterator = iteratorFn.call(myIterable); 979 | * ... 980 | * } 981 | * 982 | * @param {?object} maybeIterable 983 | * @return {?function} 984 | */ 985 | function getIteratorFn(maybeIterable) { 986 | var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]); 987 | if (typeof iteratorFn === 'function') { 988 | return iteratorFn; 989 | } 990 | } 991 | 992 | /** 993 | * Collection of methods that allow declaration and validation of props that are 994 | * supplied to React components. Example usage: 995 | * 996 | * var Props = require('ReactPropTypes'); 997 | * var MyArticle = React.createClass({ 998 | * propTypes: { 999 | * // An optional string prop named "description". 1000 | * description: Props.string, 1001 | * 1002 | * // A required enum prop named "category". 1003 | * category: Props.oneOf(['News','Photos']).isRequired, 1004 | * 1005 | * // A prop named "dialog" that requires an instance of Dialog. 1006 | * dialog: Props.instanceOf(Dialog).isRequired 1007 | * }, 1008 | * render: function() { ... } 1009 | * }); 1010 | * 1011 | * A more formal specification of how these methods are used: 1012 | * 1013 | * type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...) 1014 | * decl := ReactPropTypes.{type}(.isRequired)? 1015 | * 1016 | * Each and every declaration produces a function with the same signature. This 1017 | * allows the creation of custom validation functions. For example: 1018 | * 1019 | * var MyLink = React.createClass({ 1020 | * propTypes: { 1021 | * // An optional string or URI prop named "href". 1022 | * href: function(props, propName, componentName) { 1023 | * var propValue = props[propName]; 1024 | * if (propValue != null && typeof propValue !== 'string' && 1025 | * !(propValue instanceof URI)) { 1026 | * return new Error( 1027 | * 'Expected a string or an URI for ' + propName + ' in ' + 1028 | * componentName 1029 | * ); 1030 | * } 1031 | * } 1032 | * }, 1033 | * render: function() {...} 1034 | * }); 1035 | * 1036 | * @internal 1037 | */ 1038 | 1039 | var ANONYMOUS = '<>'; 1040 | 1041 | // Important! 1042 | // Keep this list in sync with production version in `./factoryWithThrowingShims.js`. 1043 | var ReactPropTypes = { 1044 | array: createPrimitiveTypeChecker('array'), 1045 | bool: createPrimitiveTypeChecker('boolean'), 1046 | func: createPrimitiveTypeChecker('function'), 1047 | number: createPrimitiveTypeChecker('number'), 1048 | object: createPrimitiveTypeChecker('object'), 1049 | string: createPrimitiveTypeChecker('string'), 1050 | symbol: createPrimitiveTypeChecker('symbol'), 1051 | 1052 | any: createAnyTypeChecker(), 1053 | arrayOf: createArrayOfTypeChecker, 1054 | element: createElementTypeChecker(), 1055 | instanceOf: createInstanceTypeChecker, 1056 | node: createNodeChecker(), 1057 | objectOf: createObjectOfTypeChecker, 1058 | oneOf: createEnumTypeChecker, 1059 | oneOfType: createUnionTypeChecker, 1060 | shape: createShapeTypeChecker 1061 | }; 1062 | 1063 | /** 1064 | * inlined Object.is polyfill to avoid requiring consumers ship their own 1065 | * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is 1066 | */ 1067 | /*eslint-disable no-self-compare*/ 1068 | function is(x, y) { 1069 | // SameValue algorithm 1070 | if (x === y) { 1071 | // Steps 1-5, 7-10 1072 | // Steps 6.b-6.e: +0 != -0 1073 | return x !== 0 || 1 / x === 1 / y; 1074 | } else { 1075 | // Step 6.a: NaN == NaN 1076 | return x !== x && y !== y; 1077 | } 1078 | } 1079 | /*eslint-enable no-self-compare*/ 1080 | 1081 | /** 1082 | * We use an Error-like object for backward compatibility as people may call 1083 | * PropTypes directly and inspect their output. However, we don't use real 1084 | * Errors anymore. We don't inspect their stack anyway, and creating them 1085 | * is prohibitively expensive if they are created too often, such as what 1086 | * happens in oneOfType() for any type before the one that matched. 1087 | */ 1088 | function PropTypeError(message) { 1089 | this.message = message; 1090 | this.stack = ''; 1091 | } 1092 | // Make `instanceof Error` still work for returned errors. 1093 | PropTypeError.prototype = Error.prototype; 1094 | 1095 | function createChainableTypeChecker(validate) { 1096 | if (process.env.NODE_ENV !== 'production') { 1097 | var manualPropTypeCallCache = {}; 1098 | var manualPropTypeWarningCount = 0; 1099 | } 1100 | function checkType(isRequired, props, propName, componentName, location, propFullName, secret) { 1101 | componentName = componentName || ANONYMOUS; 1102 | propFullName = propFullName || propName; 1103 | 1104 | if (secret !== ReactPropTypesSecret) { 1105 | if (throwOnDirectAccess) { 1106 | // New behavior only for users of `prop-types` package 1107 | invariant( 1108 | false, 1109 | 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + 1110 | 'Use `PropTypes.checkPropTypes()` to call them. ' + 1111 | 'Read more at http://fb.me/use-check-prop-types' 1112 | ); 1113 | } else if (process.env.NODE_ENV !== 'production' && typeof console !== 'undefined') { 1114 | // Old behavior for people using React.PropTypes 1115 | var cacheKey = componentName + ':' + propName; 1116 | if ( 1117 | !manualPropTypeCallCache[cacheKey] && 1118 | // Avoid spamming the console because they are often not actionable except for lib authors 1119 | manualPropTypeWarningCount < 3 1120 | ) { 1121 | warning( 1122 | false, 1123 | 'You are manually calling a React.PropTypes validation ' + 1124 | 'function for the `%s` prop on `%s`. This is deprecated ' + 1125 | 'and will throw in the standalone `prop-types` package. ' + 1126 | 'You may be seeing this warning due to a third-party PropTypes ' + 1127 | 'library. See https://fb.me/react-warning-dont-call-proptypes ' + 'for details.', 1128 | propFullName, 1129 | componentName 1130 | ); 1131 | manualPropTypeCallCache[cacheKey] = true; 1132 | manualPropTypeWarningCount++; 1133 | } 1134 | } 1135 | } 1136 | if (props[propName] == null) { 1137 | if (isRequired) { 1138 | if (props[propName] === null) { 1139 | return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.')); 1140 | } 1141 | return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.')); 1142 | } 1143 | return null; 1144 | } else { 1145 | return validate(props, propName, componentName, location, propFullName); 1146 | } 1147 | } 1148 | 1149 | var chainedCheckType = checkType.bind(null, false); 1150 | chainedCheckType.isRequired = checkType.bind(null, true); 1151 | 1152 | return chainedCheckType; 1153 | } 1154 | 1155 | function createPrimitiveTypeChecker(expectedType) { 1156 | function validate(props, propName, componentName, location, propFullName, secret) { 1157 | var propValue = props[propName]; 1158 | var propType = getPropType(propValue); 1159 | if (propType !== expectedType) { 1160 | // `propValue` being instance of, say, date/regexp, pass the 'object' 1161 | // check, but we can offer a more precise error message here rather than 1162 | // 'of type `object`'. 1163 | var preciseType = getPreciseType(propValue); 1164 | 1165 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.')); 1166 | } 1167 | return null; 1168 | } 1169 | return createChainableTypeChecker(validate); 1170 | } 1171 | 1172 | function createAnyTypeChecker() { 1173 | return createChainableTypeChecker(emptyFunction.thatReturnsNull); 1174 | } 1175 | 1176 | function createArrayOfTypeChecker(typeChecker) { 1177 | function validate(props, propName, componentName, location, propFullName) { 1178 | if (typeof typeChecker !== 'function') { 1179 | return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.'); 1180 | } 1181 | var propValue = props[propName]; 1182 | if (!Array.isArray(propValue)) { 1183 | var propType = getPropType(propValue); 1184 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.')); 1185 | } 1186 | for (var i = 0; i < propValue.length; i++) { 1187 | var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']', ReactPropTypesSecret); 1188 | if (error instanceof Error) { 1189 | return error; 1190 | } 1191 | } 1192 | return null; 1193 | } 1194 | return createChainableTypeChecker(validate); 1195 | } 1196 | 1197 | function createElementTypeChecker() { 1198 | function validate(props, propName, componentName, location, propFullName) { 1199 | var propValue = props[propName]; 1200 | if (!isValidElement(propValue)) { 1201 | var propType = getPropType(propValue); 1202 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement.')); 1203 | } 1204 | return null; 1205 | } 1206 | return createChainableTypeChecker(validate); 1207 | } 1208 | 1209 | function createInstanceTypeChecker(expectedClass) { 1210 | function validate(props, propName, componentName, location, propFullName) { 1211 | if (!(props[propName] instanceof expectedClass)) { 1212 | var expectedClassName = expectedClass.name || ANONYMOUS; 1213 | var actualClassName = getClassName(props[propName]); 1214 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.')); 1215 | } 1216 | return null; 1217 | } 1218 | return createChainableTypeChecker(validate); 1219 | } 1220 | 1221 | function createEnumTypeChecker(expectedValues) { 1222 | if (!Array.isArray(expectedValues)) { 1223 | process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid argument supplied to oneOf, expected an instance of array.') : void 0; 1224 | return emptyFunction.thatReturnsNull; 1225 | } 1226 | 1227 | function validate(props, propName, componentName, location, propFullName) { 1228 | var propValue = props[propName]; 1229 | for (var i = 0; i < expectedValues.length; i++) { 1230 | if (is(propValue, expectedValues[i])) { 1231 | return null; 1232 | } 1233 | } 1234 | 1235 | var valuesString = JSON.stringify(expectedValues); 1236 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of value `' + propValue + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.')); 1237 | } 1238 | return createChainableTypeChecker(validate); 1239 | } 1240 | 1241 | function createObjectOfTypeChecker(typeChecker) { 1242 | function validate(props, propName, componentName, location, propFullName) { 1243 | if (typeof typeChecker !== 'function') { 1244 | return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.'); 1245 | } 1246 | var propValue = props[propName]; 1247 | var propType = getPropType(propValue); 1248 | if (propType !== 'object') { 1249 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.')); 1250 | } 1251 | for (var key in propValue) { 1252 | if (propValue.hasOwnProperty(key)) { 1253 | var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret); 1254 | if (error instanceof Error) { 1255 | return error; 1256 | } 1257 | } 1258 | } 1259 | return null; 1260 | } 1261 | return createChainableTypeChecker(validate); 1262 | } 1263 | 1264 | function createUnionTypeChecker(arrayOfTypeCheckers) { 1265 | if (!Array.isArray(arrayOfTypeCheckers)) { 1266 | process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid argument supplied to oneOfType, expected an instance of array.') : void 0; 1267 | return emptyFunction.thatReturnsNull; 1268 | } 1269 | 1270 | function validate(props, propName, componentName, location, propFullName) { 1271 | for (var i = 0; i < arrayOfTypeCheckers.length; i++) { 1272 | var checker = arrayOfTypeCheckers[i]; 1273 | if (checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret) == null) { 1274 | return null; 1275 | } 1276 | } 1277 | 1278 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`.')); 1279 | } 1280 | return createChainableTypeChecker(validate); 1281 | } 1282 | 1283 | function createNodeChecker() { 1284 | function validate(props, propName, componentName, location, propFullName) { 1285 | if (!isNode(props[propName])) { 1286 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.')); 1287 | } 1288 | return null; 1289 | } 1290 | return createChainableTypeChecker(validate); 1291 | } 1292 | 1293 | function createShapeTypeChecker(shapeTypes) { 1294 | function validate(props, propName, componentName, location, propFullName) { 1295 | var propValue = props[propName]; 1296 | var propType = getPropType(propValue); 1297 | if (propType !== 'object') { 1298 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.')); 1299 | } 1300 | for (var key in shapeTypes) { 1301 | var checker = shapeTypes[key]; 1302 | if (!checker) { 1303 | continue; 1304 | } 1305 | var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret); 1306 | if (error) { 1307 | return error; 1308 | } 1309 | } 1310 | return null; 1311 | } 1312 | return createChainableTypeChecker(validate); 1313 | } 1314 | 1315 | function isNode(propValue) { 1316 | switch (typeof propValue) { 1317 | case 'number': 1318 | case 'string': 1319 | case 'undefined': 1320 | return true; 1321 | case 'boolean': 1322 | return !propValue; 1323 | case 'object': 1324 | if (Array.isArray(propValue)) { 1325 | return propValue.every(isNode); 1326 | } 1327 | if (propValue === null || isValidElement(propValue)) { 1328 | return true; 1329 | } 1330 | 1331 | var iteratorFn = getIteratorFn(propValue); 1332 | if (iteratorFn) { 1333 | var iterator = iteratorFn.call(propValue); 1334 | var step; 1335 | if (iteratorFn !== propValue.entries) { 1336 | while (!(step = iterator.next()).done) { 1337 | if (!isNode(step.value)) { 1338 | return false; 1339 | } 1340 | } 1341 | } else { 1342 | // Iterator will provide entry [k,v] tuples rather than values. 1343 | while (!(step = iterator.next()).done) { 1344 | var entry = step.value; 1345 | if (entry) { 1346 | if (!isNode(entry[1])) { 1347 | return false; 1348 | } 1349 | } 1350 | } 1351 | } 1352 | } else { 1353 | return false; 1354 | } 1355 | 1356 | return true; 1357 | default: 1358 | return false; 1359 | } 1360 | } 1361 | 1362 | function isSymbol(propType, propValue) { 1363 | // Native Symbol. 1364 | if (propType === 'symbol') { 1365 | return true; 1366 | } 1367 | 1368 | // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol' 1369 | if (propValue['@@toStringTag'] === 'Symbol') { 1370 | return true; 1371 | } 1372 | 1373 | // Fallback for non-spec compliant Symbols which are polyfilled. 1374 | if (typeof Symbol === 'function' && propValue instanceof Symbol) { 1375 | return true; 1376 | } 1377 | 1378 | return false; 1379 | } 1380 | 1381 | // Equivalent of `typeof` but with special handling for array and regexp. 1382 | function getPropType(propValue) { 1383 | var propType = typeof propValue; 1384 | if (Array.isArray(propValue)) { 1385 | return 'array'; 1386 | } 1387 | if (propValue instanceof RegExp) { 1388 | // Old webkits (at least until Android 4.0) return 'function' rather than 1389 | // 'object' for typeof a RegExp. We'll normalize this here so that /bla/ 1390 | // passes PropTypes.object. 1391 | return 'object'; 1392 | } 1393 | if (isSymbol(propType, propValue)) { 1394 | return 'symbol'; 1395 | } 1396 | return propType; 1397 | } 1398 | 1399 | // This handles more types than `getPropType`. Only used for error messages. 1400 | // See `createPrimitiveTypeChecker`. 1401 | function getPreciseType(propValue) { 1402 | var propType = getPropType(propValue); 1403 | if (propType === 'object') { 1404 | if (propValue instanceof Date) { 1405 | return 'date'; 1406 | } else if (propValue instanceof RegExp) { 1407 | return 'regexp'; 1408 | } 1409 | } 1410 | return propType; 1411 | } 1412 | 1413 | // Returns class name of the object, if any. 1414 | function getClassName(propValue) { 1415 | if (!propValue.constructor || !propValue.constructor.name) { 1416 | return ANONYMOUS; 1417 | } 1418 | return propValue.constructor.name; 1419 | } 1420 | 1421 | ReactPropTypes.checkPropTypes = checkPropTypes; 1422 | ReactPropTypes.PropTypes = ReactPropTypes; 1423 | 1424 | return ReactPropTypes; 1425 | }; 1426 | 1427 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2))) 1428 | 1429 | /***/ }), 1430 | /* 5 */ 1431 | /***/ (function(module, exports) { 1432 | 1433 | "use strict"; 1434 | 1435 | /** 1436 | * Copyright (c) 2013-present, Facebook, Inc. 1437 | * All rights reserved. 1438 | * 1439 | * This source code is licensed under the BSD-style license found in the 1440 | * LICENSE file in the root directory of this source tree. An additional grant 1441 | * of patent rights can be found in the PATENTS file in the same directory. 1442 | * 1443 | * 1444 | */ 1445 | 1446 | function makeEmptyFunction(arg) { 1447 | return function () { 1448 | return arg; 1449 | }; 1450 | } 1451 | 1452 | /** 1453 | * This function accepts and discards inputs; it has no side effects. This is 1454 | * primarily useful idiomatically for overridable function endpoints which 1455 | * always need to be callable, since JS lacks a null-call idiom ala Cocoa. 1456 | */ 1457 | var emptyFunction = function emptyFunction() {}; 1458 | 1459 | emptyFunction.thatReturns = makeEmptyFunction; 1460 | emptyFunction.thatReturnsFalse = makeEmptyFunction(false); 1461 | emptyFunction.thatReturnsTrue = makeEmptyFunction(true); 1462 | emptyFunction.thatReturnsNull = makeEmptyFunction(null); 1463 | emptyFunction.thatReturnsThis = function () { 1464 | return this; 1465 | }; 1466 | emptyFunction.thatReturnsArgument = function (arg) { 1467 | return arg; 1468 | }; 1469 | 1470 | module.exports = emptyFunction; 1471 | 1472 | /***/ }), 1473 | /* 6 */ 1474 | /***/ (function(module, exports, __webpack_require__) { 1475 | 1476 | /* WEBPACK VAR INJECTION */(function(process) {/** 1477 | * Copyright (c) 2013-present, Facebook, Inc. 1478 | * All rights reserved. 1479 | * 1480 | * This source code is licensed under the BSD-style license found in the 1481 | * LICENSE file in the root directory of this source tree. An additional grant 1482 | * of patent rights can be found in the PATENTS file in the same directory. 1483 | * 1484 | */ 1485 | 1486 | 'use strict'; 1487 | 1488 | /** 1489 | * Use invariant() to assert state which your program assumes to be true. 1490 | * 1491 | * Provide sprintf-style format (only %s is supported) and arguments 1492 | * to provide information about what broke and what you were 1493 | * expecting. 1494 | * 1495 | * The invariant message will be stripped in production, but the invariant 1496 | * will remain to ensure logic does not differ in production. 1497 | */ 1498 | 1499 | var validateFormat = function validateFormat(format) {}; 1500 | 1501 | if (process.env.NODE_ENV !== 'production') { 1502 | validateFormat = function validateFormat(format) { 1503 | if (format === undefined) { 1504 | throw new Error('invariant requires an error message argument'); 1505 | } 1506 | }; 1507 | } 1508 | 1509 | function invariant(condition, format, a, b, c, d, e, f) { 1510 | validateFormat(format); 1511 | 1512 | if (!condition) { 1513 | var error; 1514 | if (format === undefined) { 1515 | error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.'); 1516 | } else { 1517 | var args = [a, b, c, d, e, f]; 1518 | var argIndex = 0; 1519 | error = new Error(format.replace(/%s/g, function () { 1520 | return args[argIndex++]; 1521 | })); 1522 | error.name = 'Invariant Violation'; 1523 | } 1524 | 1525 | error.framesToPop = 1; // we don't care about invariant's own frame 1526 | throw error; 1527 | } 1528 | } 1529 | 1530 | module.exports = invariant; 1531 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2))) 1532 | 1533 | /***/ }), 1534 | /* 7 */ 1535 | /***/ (function(module, exports, __webpack_require__) { 1536 | 1537 | /* WEBPACK VAR INJECTION */(function(process) {/** 1538 | * Copyright 2014-2015, Facebook, Inc. 1539 | * All rights reserved. 1540 | * 1541 | * This source code is licensed under the BSD-style license found in the 1542 | * LICENSE file in the root directory of this source tree. An additional grant 1543 | * of patent rights can be found in the PATENTS file in the same directory. 1544 | * 1545 | */ 1546 | 1547 | 'use strict'; 1548 | 1549 | var emptyFunction = __webpack_require__(5); 1550 | 1551 | /** 1552 | * Similar to invariant but only logs a warning if the condition is not met. 1553 | * This can be used to log issues in development environments in critical 1554 | * paths. Removing the logging code for production environments will keep the 1555 | * same logic and follow the same code paths. 1556 | */ 1557 | 1558 | var warning = emptyFunction; 1559 | 1560 | if (process.env.NODE_ENV !== 'production') { 1561 | (function () { 1562 | var printWarning = function printWarning(format) { 1563 | for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 1564 | args[_key - 1] = arguments[_key]; 1565 | } 1566 | 1567 | var argIndex = 0; 1568 | var message = 'Warning: ' + format.replace(/%s/g, function () { 1569 | return args[argIndex++]; 1570 | }); 1571 | if (typeof console !== 'undefined') { 1572 | console.error(message); 1573 | } 1574 | try { 1575 | // --- Welcome to debugging React --- 1576 | // This error was thrown as a convenience so that you can use this stack 1577 | // to find the callsite that caused this warning to fire. 1578 | throw new Error(message); 1579 | } catch (x) {} 1580 | }; 1581 | 1582 | warning = function warning(condition, format) { 1583 | if (format === undefined) { 1584 | throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument'); 1585 | } 1586 | 1587 | if (format.indexOf('Failed Composite propType: ') === 0) { 1588 | return; // Ignore CompositeComponent proptype check. 1589 | } 1590 | 1591 | if (!condition) { 1592 | for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { 1593 | args[_key2 - 2] = arguments[_key2]; 1594 | } 1595 | 1596 | printWarning.apply(undefined, [format].concat(args)); 1597 | } 1598 | }; 1599 | })(); 1600 | } 1601 | 1602 | module.exports = warning; 1603 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2))) 1604 | 1605 | /***/ }), 1606 | /* 8 */ 1607 | /***/ (function(module, exports) { 1608 | 1609 | /** 1610 | * Copyright 2013-present, Facebook, Inc. 1611 | * All rights reserved. 1612 | * 1613 | * This source code is licensed under the BSD-style license found in the 1614 | * LICENSE file in the root directory of this source tree. An additional grant 1615 | * of patent rights can be found in the PATENTS file in the same directory. 1616 | */ 1617 | 1618 | 'use strict'; 1619 | 1620 | var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'; 1621 | 1622 | module.exports = ReactPropTypesSecret; 1623 | 1624 | 1625 | /***/ }), 1626 | /* 9 */ 1627 | /***/ (function(module, exports, __webpack_require__) { 1628 | 1629 | /* WEBPACK VAR INJECTION */(function(process) {/** 1630 | * Copyright 2013-present, Facebook, Inc. 1631 | * All rights reserved. 1632 | * 1633 | * This source code is licensed under the BSD-style license found in the 1634 | * LICENSE file in the root directory of this source tree. An additional grant 1635 | * of patent rights can be found in the PATENTS file in the same directory. 1636 | */ 1637 | 1638 | 'use strict'; 1639 | 1640 | if (process.env.NODE_ENV !== 'production') { 1641 | var invariant = __webpack_require__(6); 1642 | var warning = __webpack_require__(7); 1643 | var ReactPropTypesSecret = __webpack_require__(8); 1644 | var loggedTypeFailures = {}; 1645 | } 1646 | 1647 | /** 1648 | * Assert that the values match with the type specs. 1649 | * Error messages are memorized and will only be shown once. 1650 | * 1651 | * @param {object} typeSpecs Map of name to a ReactPropType 1652 | * @param {object} values Runtime values that need to be type-checked 1653 | * @param {string} location e.g. "prop", "context", "child context" 1654 | * @param {string} componentName Name of the component for error messages. 1655 | * @param {?Function} getStack Returns the component stack. 1656 | * @private 1657 | */ 1658 | function checkPropTypes(typeSpecs, values, location, componentName, getStack) { 1659 | if (process.env.NODE_ENV !== 'production') { 1660 | for (var typeSpecName in typeSpecs) { 1661 | if (typeSpecs.hasOwnProperty(typeSpecName)) { 1662 | var error; 1663 | // Prop type validation may throw. In case they do, we don't want to 1664 | // fail the render phase where it didn't fail before. So we log it. 1665 | // After these have been cleaned up, we'll let them throw. 1666 | try { 1667 | // This is intentionally an invariant that gets caught. It's the same 1668 | // behavior as without this statement except with a better message. 1669 | invariant(typeof typeSpecs[typeSpecName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'React.PropTypes.', componentName || 'React class', location, typeSpecName); 1670 | error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret); 1671 | } catch (ex) { 1672 | error = ex; 1673 | } 1674 | warning(!error || error instanceof Error, '%s: type specification of %s `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error); 1675 | if (error instanceof Error && !(error.message in loggedTypeFailures)) { 1676 | // Only monitor this failure once because there tends to be a lot of the 1677 | // same error. 1678 | loggedTypeFailures[error.message] = true; 1679 | 1680 | var stack = getStack ? getStack() : ''; 1681 | 1682 | warning(false, 'Failed %s type: %s%s', location, error.message, stack != null ? stack : ''); 1683 | } 1684 | } 1685 | } 1686 | } 1687 | } 1688 | 1689 | module.exports = checkPropTypes; 1690 | 1691 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2))) 1692 | 1693 | /***/ }), 1694 | /* 10 */ 1695 | /***/ (function(module, exports, __webpack_require__) { 1696 | 1697 | /** 1698 | * Copyright 2013-present, Facebook, Inc. 1699 | * All rights reserved. 1700 | * 1701 | * This source code is licensed under the BSD-style license found in the 1702 | * LICENSE file in the root directory of this source tree. An additional grant 1703 | * of patent rights can be found in the PATENTS file in the same directory. 1704 | */ 1705 | 1706 | 'use strict'; 1707 | 1708 | var emptyFunction = __webpack_require__(5); 1709 | var invariant = __webpack_require__(6); 1710 | 1711 | module.exports = function() { 1712 | // Important! 1713 | // Keep this list in sync with production version in `./factoryWithTypeCheckers.js`. 1714 | function shim() { 1715 | invariant( 1716 | false, 1717 | 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + 1718 | 'Use PropTypes.checkPropTypes() to call them. ' + 1719 | 'Read more at http://fb.me/use-check-prop-types' 1720 | ); 1721 | }; 1722 | shim.isRequired = shim; 1723 | function getShim() { 1724 | return shim; 1725 | }; 1726 | var ReactPropTypes = { 1727 | array: shim, 1728 | bool: shim, 1729 | func: shim, 1730 | number: shim, 1731 | object: shim, 1732 | string: shim, 1733 | symbol: shim, 1734 | 1735 | any: shim, 1736 | arrayOf: getShim, 1737 | element: shim, 1738 | instanceOf: getShim, 1739 | node: shim, 1740 | objectOf: getShim, 1741 | oneOf: getShim, 1742 | oneOfType: getShim, 1743 | shape: getShim 1744 | }; 1745 | 1746 | ReactPropTypes.checkPropTypes = emptyFunction; 1747 | ReactPropTypes.PropTypes = ReactPropTypes; 1748 | 1749 | return ReactPropTypes; 1750 | }; 1751 | 1752 | 1753 | /***/ }), 1754 | /* 11 */ 1755 | /***/ (function(module, exports, __webpack_require__) { 1756 | 1757 | !function() { 1758 | 'use strict'; 1759 | function VNode() {} 1760 | function h(nodeName, attributes) { 1761 | var lastSimple, child, simple, i, children = EMPTY_CHILDREN; 1762 | for (i = arguments.length; i-- > 2; ) stack.push(arguments[i]); 1763 | if (attributes && null != attributes.children) { 1764 | if (!stack.length) stack.push(attributes.children); 1765 | delete attributes.children; 1766 | } 1767 | while (stack.length) if ((child = stack.pop()) && void 0 !== child.pop) for (i = child.length; i--; ) stack.push(child[i]); else { 1768 | if (child === !0 || child === !1) child = null; 1769 | if (simple = 'function' != typeof nodeName) if (null == child) child = ''; else if ('number' == typeof child) child = String(child); else if ('string' != typeof child) simple = !1; 1770 | if (simple && lastSimple) children[children.length - 1] += child; else if (children === EMPTY_CHILDREN) children = [ child ]; else children.push(child); 1771 | lastSimple = simple; 1772 | } 1773 | var p = new VNode(); 1774 | p.nodeName = nodeName; 1775 | p.children = children; 1776 | p.attributes = null == attributes ? void 0 : attributes; 1777 | p.key = null == attributes ? void 0 : attributes.key; 1778 | if (void 0 !== options.vnode) options.vnode(p); 1779 | return p; 1780 | } 1781 | function extend(obj, props) { 1782 | for (var i in props) obj[i] = props[i]; 1783 | return obj; 1784 | } 1785 | function cloneElement(vnode, props) { 1786 | return h(vnode.nodeName, extend(extend({}, vnode.attributes), props), arguments.length > 2 ? [].slice.call(arguments, 2) : vnode.children); 1787 | } 1788 | function enqueueRender(component) { 1789 | if (!component.__d && (component.__d = !0) && 1 == items.push(component)) (options.debounceRendering || setTimeout)(rerender); 1790 | } 1791 | function rerender() { 1792 | var p, list = items; 1793 | items = []; 1794 | while (p = list.pop()) if (p.__d) renderComponent(p); 1795 | } 1796 | function isSameNodeType(node, vnode, hydrating) { 1797 | if ('string' == typeof vnode || 'number' == typeof vnode) return void 0 !== node.splitText; 1798 | if ('string' == typeof vnode.nodeName) return !node._componentConstructor && isNamedNode(node, vnode.nodeName); else return hydrating || node._componentConstructor === vnode.nodeName; 1799 | } 1800 | function isNamedNode(node, nodeName) { 1801 | return node.__n === nodeName || node.nodeName.toLowerCase() === nodeName.toLowerCase(); 1802 | } 1803 | function getNodeProps(vnode) { 1804 | var props = extend({}, vnode.attributes); 1805 | props.children = vnode.children; 1806 | var defaultProps = vnode.nodeName.defaultProps; 1807 | if (void 0 !== defaultProps) for (var i in defaultProps) if (void 0 === props[i]) props[i] = defaultProps[i]; 1808 | return props; 1809 | } 1810 | function createNode(nodeName, isSvg) { 1811 | var node = isSvg ? document.createElementNS('http://www.w3.org/2000/svg', nodeName) : document.createElement(nodeName); 1812 | node.__n = nodeName; 1813 | return node; 1814 | } 1815 | function removeNode(node) { 1816 | if (node.parentNode) node.parentNode.removeChild(node); 1817 | } 1818 | function setAccessor(node, name, old, value, isSvg) { 1819 | if ('className' === name) name = 'class'; 1820 | if ('key' === name) ; else if ('ref' === name) { 1821 | if (old) old(null); 1822 | if (value) value(node); 1823 | } else if ('class' === name && !isSvg) node.className = value || ''; else if ('style' === name) { 1824 | if (!value || 'string' == typeof value || 'string' == typeof old) node.style.cssText = value || ''; 1825 | if (value && 'object' == typeof value) { 1826 | if ('string' != typeof old) for (var i in old) if (!(i in value)) node.style[i] = ''; 1827 | for (var i in value) node.style[i] = 'number' == typeof value[i] && IS_NON_DIMENSIONAL.test(i) === !1 ? value[i] + 'px' : value[i]; 1828 | } 1829 | } else if ('dangerouslySetInnerHTML' === name) { 1830 | if (value) node.innerHTML = value.__html || ''; 1831 | } else if ('o' == name[0] && 'n' == name[1]) { 1832 | var useCapture = name !== (name = name.replace(/Capture$/, '')); 1833 | name = name.toLowerCase().substring(2); 1834 | if (value) { 1835 | if (!old) node.addEventListener(name, eventProxy, useCapture); 1836 | } else node.removeEventListener(name, eventProxy, useCapture); 1837 | (node.__l || (node.__l = {}))[name] = value; 1838 | } else if ('list' !== name && 'type' !== name && !isSvg && name in node) { 1839 | setProperty(node, name, null == value ? '' : value); 1840 | if (null == value || value === !1) node.removeAttribute(name); 1841 | } else { 1842 | var ns = isSvg && name !== (name = name.replace(/^xlink\:?/, '')); 1843 | if (null == value || value === !1) if (ns) node.removeAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase()); else node.removeAttribute(name); else if ('function' != typeof value) if (ns) node.setAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase(), value); else node.setAttribute(name, value); 1844 | } 1845 | } 1846 | function setProperty(node, name, value) { 1847 | try { 1848 | node[name] = value; 1849 | } catch (e) {} 1850 | } 1851 | function eventProxy(e) { 1852 | return this.__l[e.type](options.event && options.event(e) || e); 1853 | } 1854 | function flushMounts() { 1855 | var c; 1856 | while (c = mounts.pop()) { 1857 | if (options.afterMount) options.afterMount(c); 1858 | if (c.componentDidMount) c.componentDidMount(); 1859 | } 1860 | } 1861 | function diff(dom, vnode, context, mountAll, parent, componentRoot) { 1862 | if (!diffLevel++) { 1863 | isSvgMode = null != parent && void 0 !== parent.ownerSVGElement; 1864 | hydrating = null != dom && !('__preactattr_' in dom); 1865 | } 1866 | var ret = idiff(dom, vnode, context, mountAll, componentRoot); 1867 | if (parent && ret.parentNode !== parent) parent.appendChild(ret); 1868 | if (!--diffLevel) { 1869 | hydrating = !1; 1870 | if (!componentRoot) flushMounts(); 1871 | } 1872 | return ret; 1873 | } 1874 | function idiff(dom, vnode, context, mountAll, componentRoot) { 1875 | var out = dom, prevSvgMode = isSvgMode; 1876 | if (null == vnode) vnode = ''; 1877 | if ('string' == typeof vnode) { 1878 | if (dom && void 0 !== dom.splitText && dom.parentNode && (!dom._component || componentRoot)) { 1879 | if (dom.nodeValue != vnode) dom.nodeValue = vnode; 1880 | } else { 1881 | out = document.createTextNode(vnode); 1882 | if (dom) { 1883 | if (dom.parentNode) dom.parentNode.replaceChild(out, dom); 1884 | recollectNodeTree(dom, !0); 1885 | } 1886 | } 1887 | out.__preactattr_ = !0; 1888 | return out; 1889 | } 1890 | if ('function' == typeof vnode.nodeName) return buildComponentFromVNode(dom, vnode, context, mountAll); 1891 | isSvgMode = 'svg' === vnode.nodeName ? !0 : 'foreignObject' === vnode.nodeName ? !1 : isSvgMode; 1892 | if (!dom || !isNamedNode(dom, String(vnode.nodeName))) { 1893 | out = createNode(String(vnode.nodeName), isSvgMode); 1894 | if (dom) { 1895 | while (dom.firstChild) out.appendChild(dom.firstChild); 1896 | if (dom.parentNode) dom.parentNode.replaceChild(out, dom); 1897 | recollectNodeTree(dom, !0); 1898 | } 1899 | } 1900 | var fc = out.firstChild, props = out.__preactattr_ || (out.__preactattr_ = {}), vchildren = vnode.children; 1901 | if (!hydrating && vchildren && 1 === vchildren.length && 'string' == typeof vchildren[0] && null != fc && void 0 !== fc.splitText && null == fc.nextSibling) { 1902 | if (fc.nodeValue != vchildren[0]) fc.nodeValue = vchildren[0]; 1903 | } else if (vchildren && vchildren.length || null != fc) innerDiffNode(out, vchildren, context, mountAll, hydrating || null != props.dangerouslySetInnerHTML); 1904 | diffAttributes(out, vnode.attributes, props); 1905 | isSvgMode = prevSvgMode; 1906 | return out; 1907 | } 1908 | function innerDiffNode(dom, vchildren, context, mountAll, isHydrating) { 1909 | var j, c, vchild, child, originalChildren = dom.childNodes, children = [], keyed = {}, keyedLen = 0, min = 0, len = originalChildren.length, childrenLen = 0, vlen = vchildren ? vchildren.length : 0; 1910 | if (0 !== len) for (var i = 0; i < len; i++) { 1911 | var _child = originalChildren[i], props = _child.__preactattr_, key = vlen && props ? _child._component ? _child._component.__k : props.key : null; 1912 | if (null != key) { 1913 | keyedLen++; 1914 | keyed[key] = _child; 1915 | } else if (props || (void 0 !== _child.splitText ? isHydrating ? _child.nodeValue.trim() : !0 : isHydrating)) children[childrenLen++] = _child; 1916 | } 1917 | if (0 !== vlen) for (var i = 0; i < vlen; i++) { 1918 | vchild = vchildren[i]; 1919 | child = null; 1920 | var key = vchild.key; 1921 | if (null != key) { 1922 | if (keyedLen && void 0 !== keyed[key]) { 1923 | child = keyed[key]; 1924 | keyed[key] = void 0; 1925 | keyedLen--; 1926 | } 1927 | } else if (!child && min < childrenLen) for (j = min; j < childrenLen; j++) if (void 0 !== children[j] && isSameNodeType(c = children[j], vchild, isHydrating)) { 1928 | child = c; 1929 | children[j] = void 0; 1930 | if (j === childrenLen - 1) childrenLen--; 1931 | if (j === min) min++; 1932 | break; 1933 | } 1934 | child = idiff(child, vchild, context, mountAll); 1935 | if (child && child !== dom) if (i >= len) dom.appendChild(child); else if (child !== originalChildren[i]) if (child === originalChildren[i + 1]) removeNode(originalChildren[i]); else dom.insertBefore(child, originalChildren[i] || null); 1936 | } 1937 | if (keyedLen) for (var i in keyed) if (void 0 !== keyed[i]) recollectNodeTree(keyed[i], !1); 1938 | while (min <= childrenLen) if (void 0 !== (child = children[childrenLen--])) recollectNodeTree(child, !1); 1939 | } 1940 | function recollectNodeTree(node, unmountOnly) { 1941 | var component = node._component; 1942 | if (component) unmountComponent(component); else { 1943 | if (null != node.__preactattr_ && node.__preactattr_.ref) node.__preactattr_.ref(null); 1944 | if (unmountOnly === !1 || null == node.__preactattr_) removeNode(node); 1945 | removeChildren(node); 1946 | } 1947 | } 1948 | function removeChildren(node) { 1949 | node = node.lastChild; 1950 | while (node) { 1951 | var next = node.previousSibling; 1952 | recollectNodeTree(node, !0); 1953 | node = next; 1954 | } 1955 | } 1956 | function diffAttributes(dom, attrs, old) { 1957 | var name; 1958 | for (name in old) if ((!attrs || null == attrs[name]) && null != old[name]) setAccessor(dom, name, old[name], old[name] = void 0, isSvgMode); 1959 | for (name in attrs) if (!('children' === name || 'innerHTML' === name || name in old && attrs[name] === ('value' === name || 'checked' === name ? dom[name] : old[name]))) setAccessor(dom, name, old[name], old[name] = attrs[name], isSvgMode); 1960 | } 1961 | function collectComponent(component) { 1962 | var name = component.constructor.name; 1963 | (components[name] || (components[name] = [])).push(component); 1964 | } 1965 | function createComponent(Ctor, props, context) { 1966 | var inst, list = components[Ctor.name]; 1967 | if (Ctor.prototype && Ctor.prototype.render) { 1968 | inst = new Ctor(props, context); 1969 | Component.call(inst, props, context); 1970 | } else { 1971 | inst = new Component(props, context); 1972 | inst.constructor = Ctor; 1973 | inst.render = doRender; 1974 | } 1975 | if (list) for (var i = list.length; i--; ) if (list[i].constructor === Ctor) { 1976 | inst.__b = list[i].__b; 1977 | list.splice(i, 1); 1978 | break; 1979 | } 1980 | return inst; 1981 | } 1982 | function doRender(props, state, context) { 1983 | return this.constructor(props, context); 1984 | } 1985 | function setComponentProps(component, props, opts, context, mountAll) { 1986 | if (!component.__x) { 1987 | component.__x = !0; 1988 | if (component.__r = props.ref) delete props.ref; 1989 | if (component.__k = props.key) delete props.key; 1990 | if (!component.base || mountAll) { 1991 | if (component.componentWillMount) component.componentWillMount(); 1992 | } else if (component.componentWillReceiveProps) component.componentWillReceiveProps(props, context); 1993 | if (context && context !== component.context) { 1994 | if (!component.__c) component.__c = component.context; 1995 | component.context = context; 1996 | } 1997 | if (!component.__p) component.__p = component.props; 1998 | component.props = props; 1999 | component.__x = !1; 2000 | if (0 !== opts) if (1 === opts || options.syncComponentUpdates !== !1 || !component.base) renderComponent(component, 1, mountAll); else enqueueRender(component); 2001 | if (component.__r) component.__r(component); 2002 | } 2003 | } 2004 | function renderComponent(component, opts, mountAll, isChild) { 2005 | if (!component.__x) { 2006 | var rendered, inst, cbase, props = component.props, state = component.state, context = component.context, previousProps = component.__p || props, previousState = component.__s || state, previousContext = component.__c || context, isUpdate = component.base, nextBase = component.__b, initialBase = isUpdate || nextBase, initialChildComponent = component._component, skip = !1; 2007 | if (isUpdate) { 2008 | component.props = previousProps; 2009 | component.state = previousState; 2010 | component.context = previousContext; 2011 | if (2 !== opts && component.shouldComponentUpdate && component.shouldComponentUpdate(props, state, context) === !1) skip = !0; else if (component.componentWillUpdate) component.componentWillUpdate(props, state, context); 2012 | component.props = props; 2013 | component.state = state; 2014 | component.context = context; 2015 | } 2016 | component.__p = component.__s = component.__c = component.__b = null; 2017 | component.__d = !1; 2018 | if (!skip) { 2019 | rendered = component.render(props, state, context); 2020 | if (component.getChildContext) context = extend(extend({}, context), component.getChildContext()); 2021 | var toUnmount, base, childComponent = rendered && rendered.nodeName; 2022 | if ('function' == typeof childComponent) { 2023 | var childProps = getNodeProps(rendered); 2024 | inst = initialChildComponent; 2025 | if (inst && inst.constructor === childComponent && childProps.key == inst.__k) setComponentProps(inst, childProps, 1, context, !1); else { 2026 | toUnmount = inst; 2027 | component._component = inst = createComponent(childComponent, childProps, context); 2028 | inst.__b = inst.__b || nextBase; 2029 | inst.__u = component; 2030 | setComponentProps(inst, childProps, 0, context, !1); 2031 | renderComponent(inst, 1, mountAll, !0); 2032 | } 2033 | base = inst.base; 2034 | } else { 2035 | cbase = initialBase; 2036 | toUnmount = initialChildComponent; 2037 | if (toUnmount) cbase = component._component = null; 2038 | if (initialBase || 1 === opts) { 2039 | if (cbase) cbase._component = null; 2040 | base = diff(cbase, rendered, context, mountAll || !isUpdate, initialBase && initialBase.parentNode, !0); 2041 | } 2042 | } 2043 | if (initialBase && base !== initialBase && inst !== initialChildComponent) { 2044 | var baseParent = initialBase.parentNode; 2045 | if (baseParent && base !== baseParent) { 2046 | baseParent.replaceChild(base, initialBase); 2047 | if (!toUnmount) { 2048 | initialBase._component = null; 2049 | recollectNodeTree(initialBase, !1); 2050 | } 2051 | } 2052 | } 2053 | if (toUnmount) unmountComponent(toUnmount); 2054 | component.base = base; 2055 | if (base && !isChild) { 2056 | var componentRef = component, t = component; 2057 | while (t = t.__u) (componentRef = t).base = base; 2058 | base._component = componentRef; 2059 | base._componentConstructor = componentRef.constructor; 2060 | } 2061 | } 2062 | if (!isUpdate || mountAll) mounts.unshift(component); else if (!skip) { 2063 | flushMounts(); 2064 | if (component.componentDidUpdate) component.componentDidUpdate(previousProps, previousState, previousContext); 2065 | if (options.afterUpdate) options.afterUpdate(component); 2066 | } 2067 | if (null != component.__h) while (component.__h.length) component.__h.pop().call(component); 2068 | if (!diffLevel && !isChild) flushMounts(); 2069 | } 2070 | } 2071 | function buildComponentFromVNode(dom, vnode, context, mountAll) { 2072 | var c = dom && dom._component, originalComponent = c, oldDom = dom, isDirectOwner = c && dom._componentConstructor === vnode.nodeName, isOwner = isDirectOwner, props = getNodeProps(vnode); 2073 | while (c && !isOwner && (c = c.__u)) isOwner = c.constructor === vnode.nodeName; 2074 | if (c && isOwner && (!mountAll || c._component)) { 2075 | setComponentProps(c, props, 3, context, mountAll); 2076 | dom = c.base; 2077 | } else { 2078 | if (originalComponent && !isDirectOwner) { 2079 | unmountComponent(originalComponent); 2080 | dom = oldDom = null; 2081 | } 2082 | c = createComponent(vnode.nodeName, props, context); 2083 | if (dom && !c.__b) { 2084 | c.__b = dom; 2085 | oldDom = null; 2086 | } 2087 | setComponentProps(c, props, 1, context, mountAll); 2088 | dom = c.base; 2089 | if (oldDom && dom !== oldDom) { 2090 | oldDom._component = null; 2091 | recollectNodeTree(oldDom, !1); 2092 | } 2093 | } 2094 | return dom; 2095 | } 2096 | function unmountComponent(component) { 2097 | if (options.beforeUnmount) options.beforeUnmount(component); 2098 | var base = component.base; 2099 | component.__x = !0; 2100 | if (component.componentWillUnmount) component.componentWillUnmount(); 2101 | component.base = null; 2102 | var inner = component._component; 2103 | if (inner) unmountComponent(inner); else if (base) { 2104 | if (base.__preactattr_ && base.__preactattr_.ref) base.__preactattr_.ref(null); 2105 | component.__b = base; 2106 | removeNode(base); 2107 | collectComponent(component); 2108 | removeChildren(base); 2109 | } 2110 | if (component.__r) component.__r(null); 2111 | } 2112 | function Component(props, context) { 2113 | this.__d = !0; 2114 | this.context = context; 2115 | this.props = props; 2116 | this.state = this.state || {}; 2117 | } 2118 | function render(vnode, parent, merge) { 2119 | return diff(merge, vnode, {}, !1, parent, !1); 2120 | } 2121 | var options = {}; 2122 | var stack = []; 2123 | var EMPTY_CHILDREN = []; 2124 | var IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i; 2125 | var items = []; 2126 | var mounts = []; 2127 | var diffLevel = 0; 2128 | var isSvgMode = !1; 2129 | var hydrating = !1; 2130 | var components = {}; 2131 | extend(Component.prototype, { 2132 | setState: function(state, callback) { 2133 | var s = this.state; 2134 | if (!this.__s) this.__s = extend({}, s); 2135 | extend(s, 'function' == typeof state ? state(s, this.props) : state); 2136 | if (callback) (this.__h = this.__h || []).push(callback); 2137 | enqueueRender(this); 2138 | }, 2139 | forceUpdate: function(callback) { 2140 | if (callback) (this.__h = this.__h || []).push(callback); 2141 | renderComponent(this, 2); 2142 | }, 2143 | render: function() {} 2144 | }); 2145 | var preact = { 2146 | h: h, 2147 | createElement: h, 2148 | cloneElement: cloneElement, 2149 | Component: Component, 2150 | render: render, 2151 | rerender: rerender, 2152 | options: options 2153 | }; 2154 | if (true) module.exports = preact; else self.preact = preact; 2155 | }(); 2156 | //# sourceMappingURL=preact.js.map 2157 | 2158 | /***/ }), 2159 | /* 12 */ 2160 | /***/ (function(module, exports, __webpack_require__) { 2161 | 2162 | /* eslint-disable */ 2163 | var renderToString = dep(__webpack_require__(13)); 2164 | 2165 | function dep(obj) { return obj['default'] || obj; } 2166 | 2167 | module.exports = { 2168 | renderToString: renderToString, 2169 | renderToStaticMarkup: renderToString 2170 | }; 2171 | 2172 | 2173 | /***/ }), 2174 | /* 13 */ 2175 | /***/ (function(module, exports, __webpack_require__) { 2176 | 2177 | (function (global, factory) { 2178 | true ? module.exports = factory() : 2179 | typeof define === 'function' && define.amd ? define(factory) : 2180 | (global.preactRenderToString = factory()); 2181 | }(this, (function () { 2182 | 2183 | var NON_DIMENSION_PROPS = { 2184 | boxFlex: 1, boxFlexGroup: 1, columnCount: 1, fillOpacity: 1, flex: 1, flexGrow: 1, 2185 | flexPositive: 1, flexShrink: 1, flexNegative: 1, fontWeight: 1, lineClamp: 1, lineHeight: 1, 2186 | opacity: 1, order: 1, orphans: 1, strokeOpacity: 1, widows: 1, zIndex: 1, zoom: 1 2187 | }; 2188 | 2189 | var ESC = { 2190 | '<': '<', 2191 | '>': '>', 2192 | '"': '"', 2193 | '&': '&' 2194 | }; 2195 | 2196 | var objectKeys = Object.keys || function (obj) { 2197 | var keys = []; 2198 | for (var i in obj) { 2199 | if (obj.hasOwnProperty(i)) keys.push(i); 2200 | }return keys; 2201 | }; 2202 | 2203 | var encodeEntities = function (s) { 2204 | return String(s).replace(/[<>"&]/g, escapeChar); 2205 | }; 2206 | 2207 | var escapeChar = function (a) { 2208 | return ESC[a] || a; 2209 | }; 2210 | 2211 | var falsey = function (v) { 2212 | return v == null || v === false; 2213 | }; 2214 | 2215 | var memoize = function (fn) { 2216 | var mem = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 2217 | return function (v) { 2218 | return mem[v] || (mem[v] = fn(v)); 2219 | }; 2220 | }; 2221 | 2222 | var indent = function (s, char) { 2223 | return String(s).replace(/(\n+)/g, '$1' + (char || '\t')); 2224 | }; 2225 | 2226 | var isLargeString = function (s, length, ignoreLines) { 2227 | return String(s).length > (length || 40) || !ignoreLines && String(s).indexOf('\n') !== -1 || String(s).indexOf('<') !== -1; 2228 | }; 2229 | 2230 | function styleObjToCss(s) { 2231 | var str = ''; 2232 | for (var prop in s) { 2233 | var val = s[prop]; 2234 | if (val != null) { 2235 | if (str) str += ' '; 2236 | str += jsToCss(prop); 2237 | str += ': '; 2238 | str += val; 2239 | if (typeof val === 'number' && !NON_DIMENSION_PROPS[prop]) { 2240 | str += 'px'; 2241 | } 2242 | str += ';'; 2243 | } 2244 | } 2245 | return str || undefined; 2246 | } 2247 | 2248 | function hashToClassName(c) { 2249 | var str = ''; 2250 | for (var prop in c) { 2251 | if (c[prop]) { 2252 | if (str) str += ' '; 2253 | str += prop; 2254 | } 2255 | } 2256 | return str; 2257 | } 2258 | 2259 | var jsToCss = memoize(function (s) { 2260 | return s.replace(/([A-Z])/g, '-$1').toLowerCase(); 2261 | }); 2262 | 2263 | function assign(obj, props) { 2264 | for (var i in props) { 2265 | obj[i] = props[i]; 2266 | }return obj; 2267 | } 2268 | 2269 | function getNodeProps(vnode) { 2270 | var defaultProps = vnode.nodeName.defaultProps, 2271 | props = assign({}, defaultProps || vnode.attributes); 2272 | if (defaultProps) assign(props, vnode.attributes); 2273 | if (vnode.children) props.children = vnode.children; 2274 | return props; 2275 | } 2276 | 2277 | var SHALLOW = { shallow: true }; 2278 | 2279 | var UNNAMED = []; 2280 | 2281 | var EMPTY = {}; 2282 | 2283 | var VOID_ELEMENTS = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr']; 2284 | 2285 | renderToString.render = renderToString; 2286 | 2287 | var shallowRender = function (vnode, context) { 2288 | return renderToString(vnode, context, SHALLOW); 2289 | }; 2290 | 2291 | function renderToString(vnode, context, opts, inner, isSvgMode) { 2292 | var _ref = vnode || EMPTY; 2293 | 2294 | var nodeName = _ref.nodeName; 2295 | var attributes = _ref.attributes; 2296 | var children = _ref.children; 2297 | var isComponent = false; 2298 | context = context || {}; 2299 | opts = opts || {}; 2300 | 2301 | var pretty = opts.pretty, 2302 | indentChar = typeof pretty === 'string' ? pretty : '\t'; 2303 | 2304 | if (vnode == null || vnode === false) { 2305 | return ''; 2306 | } 2307 | 2308 | if (!nodeName) { 2309 | return encodeEntities(vnode); 2310 | } 2311 | 2312 | if (typeof nodeName === 'function') { 2313 | isComponent = true; 2314 | if (opts.shallow && (inner || opts.renderRootComponent === false)) { 2315 | nodeName = getComponentName(nodeName); 2316 | } else { 2317 | var props = getNodeProps(vnode), 2318 | rendered = void 0; 2319 | 2320 | if (!nodeName.prototype || typeof nodeName.prototype.render !== 'function') { 2321 | rendered = nodeName(props, context); 2322 | } else { 2323 | var c = new nodeName(props, context); 2324 | 2325 | c._disable = c.__x = true; 2326 | c.props = props; 2327 | c.context = context; 2328 | if (c.componentWillMount) c.componentWillMount(); 2329 | rendered = c.render(c.props, c.state, c.context); 2330 | 2331 | if (c.getChildContext) { 2332 | context = assign(assign({}, context), c.getChildContext()); 2333 | } 2334 | } 2335 | 2336 | return renderToString(rendered, context, opts, opts.shallowHighOrder !== false); 2337 | } 2338 | } 2339 | 2340 | var s = '', 2341 | html = void 0; 2342 | 2343 | if (attributes) { 2344 | var attrs = objectKeys(attributes); 2345 | 2346 | if (opts && opts.sortAttributes === true) attrs.sort(); 2347 | 2348 | for (var i = 0; i < attrs.length; i++) { 2349 | var name = attrs[i], 2350 | v = attributes[name]; 2351 | if (name === 'children') continue; 2352 | if (!(opts && opts.allAttributes) && (name === 'key' || name === 'ref')) continue; 2353 | 2354 | if (name === 'className') { 2355 | if (attributes['class']) continue; 2356 | name = 'class'; 2357 | } else if (isSvgMode && name.match(/^xlink\:?(.+)/)) { 2358 | name = name.toLowerCase().replace(/^xlink\:?(.+)/, 'xlink:$1'); 2359 | } 2360 | 2361 | if (name === 'class' && v && typeof v === 'object') { 2362 | v = hashToClassName(v); 2363 | } else if (name === 'style' && v && typeof v === 'object') { 2364 | v = styleObjToCss(v); 2365 | } 2366 | 2367 | var hooked = opts.attributeHook && opts.attributeHook(name, v, context, opts, isComponent); 2368 | if (hooked || hooked === '') { 2369 | s += hooked; 2370 | continue; 2371 | } 2372 | 2373 | if (name === 'dangerouslySetInnerHTML') { 2374 | html = v && v.__html; 2375 | } else if ((v || v === 0 || v === '') && typeof v !== 'function') { 2376 | if (v === true || v === '') { 2377 | v = name; 2378 | 2379 | if (!opts || !opts.xml) { 2380 | s += ' ' + name; 2381 | continue; 2382 | } 2383 | } 2384 | s += ' ' + name + '="' + encodeEntities(v) + '"'; 2385 | } 2386 | } 2387 | } 2388 | 2389 | var sub = s.replace(/^\n\s*/, ' '); 2390 | if (sub !== s && !~sub.indexOf('\n')) s = sub;else if (~s.indexOf('\n')) s += '\n'; 2391 | 2392 | s = '<' + nodeName + s + '>'; 2393 | 2394 | if (VOID_ELEMENTS.indexOf(nodeName) > -1) { 2395 | s = s.replace(/>$/, ' />'); 2396 | } 2397 | 2398 | if (html) { 2399 | if (pretty && isLargeString(html)) { 2400 | html = '\n' + indentChar + indent(html, indentChar); 2401 | } 2402 | s += html; 2403 | } else { 2404 | var len = children && children.length, 2405 | pieces = [], 2406 | hasLarge = ~s.indexOf('\n'); 2407 | for (var _i = 0; _i < len; _i++) { 2408 | var child = children[_i]; 2409 | if (!falsey(child)) { 2410 | var childSvgMode = nodeName === 'svg' ? true : nodeName === 'foreignObject' ? false : isSvgMode, 2411 | ret = renderToString(child, context, opts, true, childSvgMode); 2412 | if (!hasLarge && pretty && isLargeString(ret)) hasLarge = true; 2413 | pieces.push(ret); 2414 | } 2415 | } 2416 | if (hasLarge) { 2417 | for (var _i2 = pieces.length; _i2--;) { 2418 | pieces[_i2] = '\n' + indentChar + indent(pieces[_i2], indentChar); 2419 | } 2420 | } 2421 | if (pieces.length) { 2422 | s += pieces.join(''); 2423 | } else if (opts && opts.xml) { 2424 | return s.substring(0, s.length - 1) + ' />'; 2425 | } 2426 | } 2427 | 2428 | if (opts.jsx || VOID_ELEMENTS.indexOf(nodeName) === -1) { 2429 | if (pretty && ~s.indexOf('\n')) s += '\n'; 2430 | s += ''; 2431 | } 2432 | 2433 | return s; 2434 | } 2435 | 2436 | function getComponentName(component) { 2437 | var proto = component.prototype, 2438 | ctor = proto && proto.constructor; 2439 | return component.displayName || component.name || proto && (proto.displayName || proto.name) || getFallbackComponentName(component); 2440 | } 2441 | 2442 | function getFallbackComponentName(component) { 2443 | var str = Function.prototype.toString.call(component), 2444 | name = (str.match(/^\s*function\s+([^\( ]+)/) || EMPTY)[1]; 2445 | if (!name) { 2446 | var index = -1; 2447 | for (var i = UNNAMED.length; i--;) { 2448 | if (UNNAMED[i] === component) { 2449 | index = i; 2450 | break; 2451 | } 2452 | } 2453 | 2454 | if (index < 0) { 2455 | index = UNNAMED.push(component) - 1; 2456 | } 2457 | name = 'UnnamedComponent' + index; 2458 | } 2459 | return name; 2460 | } 2461 | renderToString.shallowRender = shallowRender; 2462 | 2463 | return renderToString; 2464 | 2465 | }))); 2466 | //# sourceMappingURL=index.js.map 2467 | 2468 | 2469 | /***/ }) 2470 | /******/ ]); --------------------------------------------------------------------------------