├── .gitignore ├── README.md ├── generator ├── generator.js ├── lib │ └── ReactComponent.java ├── reactReflectiveProptypes.js └── templates │ ├── BaseClassTemplate.java │ ├── Connector.js │ └── DefaultImplementationClassTemplate.java ├── package.json └── samples ├── container ├── .babelrc ├── .react-vaadin.config ├── README.md ├── package.json ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── nunopinheiro │ │ └── vaadin_react │ │ └── MyUI.java │ ├── node │ ├── TestComponent.js │ └── TestComponent.jsx │ ├── resources │ └── com │ │ └── nunopinheiro │ │ └── vaadin_react │ │ └── MyAppWidgetset.gwt.xml │ └── webapp │ └── VAADIN │ └── themes │ └── mytheme │ ├── addons.scss │ ├── favicon.ico │ ├── mytheme.scss │ ├── styles.css │ └── styles.scss ├── simple ├── .babelrc ├── .react-vaadin.config ├── README.md ├── package.json ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── nunopinheiro │ │ └── vaadin_react │ │ └── MyUI.java │ ├── node │ ├── TestComponent.js │ └── TestComponent.jsx │ ├── resources │ └── com │ │ └── nunopinheiro │ │ └── vaadin_react │ │ └── MyAppWidgetset.gwt.xml │ └── webapp │ └── VAADIN │ └── themes │ └── mytheme │ ├── addons.scss │ ├── favicon.ico │ ├── mytheme.scss │ ├── styles.css │ └── styles.scss └── third-party-component ├── .babelrc ├── .react-vaadin.config ├── README.md ├── package.json ├── pom.xml └── src └── main ├── java └── com │ └── nunopinheiro │ └── vaadin_react │ └── MyUI.java ├── resources └── com │ └── nunopinheiro │ └── vaadin_react │ └── MyAppWidgetset.gwt.xml └── webapp └── VAADIN └── themes └── mytheme ├── addons.scss ├── favicon.ico ├── mytheme.scss ├── styles.css └── styles.scss /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .project 3 | .settings/ 4 | node_modules/ 5 | generated/ 6 | .classpath 7 | */src/main/node/*.js 8 | bin/ 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | vaadin-react 2 | ============== 3 | 4 | Vaadin-React is a tool to create serverside Vaadin components which enable the usage of React components. 5 | 6 | The project is still recent and any suggestion will be considered. 7 | 8 | ## Usage 9 | 10 | 1 - Install the tool using `npm install -g vaadin-react` 11 | 12 | 2 - Configure your project with a `.react-vaadin.config` config file. This is a json file with two fields: 13 | - components : an array of file or dir paths to process your components 14 | - package : The package to use when generating the java files 15 | 16 | 3 - Run vaadin-react in your project to generate the resources. This tool expects a project which is a mix of maven and npm. Please check the samples. 17 | 18 | ## Contributing 19 | Please open any issue that you find. You can also make suggestions to improve the current behaviour. 20 | 21 | ## Known Limitations 22 | 23 | - This project uses react-docgen to parse the components. It can only be used in components compatible with that project. 24 | - Server-side functions cannot return values to the components since that would imply blocking the browser until the answer was received. 25 | -------------------------------------------------------------------------------- /generator/generator.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var fs = require('fs'); 4 | var configuration = JSON.parse(fs.readFileSync('.react-vaadin.config', 'utf8')); 5 | var reactDocs = require('react-docgen'); 6 | var baseClassTemplate = fs.readFileSync(__dirname + "/templates/BaseClassTemplate.java", "utf8") 7 | var defaultImplClassTemplate = fs.readFileSync(__dirname + "/templates/DefaultImplementationClassTemplate.java", "utf8") 8 | var connectorTemplate = fs.readFileSync(__dirname + "/templates/Connector.js", "utf8") 9 | var Mustache = require("mustache"); 10 | require("./reactReflectiveProptypes") 11 | function listFiles(path){ 12 | var stat = fs.statSync(path) 13 | if(stat.isDirectory()){ 14 | var files = [] 15 | var contents = fs.readdirSync(path) 16 | for(var i in contents){ 17 | var fullPath = path + "/" + contents[i] 18 | files = files.concat(listFiles(fullPath)) 19 | } 20 | return files 21 | }else{ 22 | if(path.endsWith(".js")){ 23 | return [path] 24 | }else{ 25 | return [] 26 | } 27 | } 28 | } 29 | 30 | var files = [] 31 | for(var i in configuration.components){ 32 | files = files.concat(listFiles(configuration.components[i])) 33 | } 34 | 35 | for(var file in files){ 36 | var filePath = "./" + files[file] 37 | processFile(filePath) 38 | } 39 | 40 | function readComponentName(file){ 41 | var splitted = file.split("/"); 42 | var componentWithExtension = splitted[splitted.length - 1] 43 | return componentWithExtension.split(".")[0] 44 | } 45 | function processFile(file){ 46 | 47 | var src = fs.readFileSync(file) 48 | var componentModule = require(process.cwd() + "/" + file) 49 | var componentName = readComponentName(file) 50 | //Read component from its module. The component will be the module itself if exported as default 51 | var component = componentModule[componentName] || componentModule 52 | 53 | var processedProps = [] 54 | var requiredProps = [] 55 | var requiredArgList = "" 56 | var requiredArgListCall = "" 57 | 58 | for(var propName in component.propTypes){ 59 | var prop = component.propTypes[propName] 60 | var upperName = propName[0].toUpperCase() + propName.substring(1) 61 | var processedProp = { name : propName, upperName : upperName} 62 | addJavaType(processedProp, prop.type) 63 | processedProps.push(processedProp) 64 | 65 | if(prop.required){ 66 | //Create arguments string for the constructor, we are doing it here because it would be uglier in mustache 67 | if(requiredArgList != ""){ 68 | requiredArgList += ", "; 69 | requiredArgListCall += ", "; 70 | } 71 | requiredArgList += `${processedProp.type} ${prop.name}` 72 | requiredArgListCall += `${prop.name}` 73 | requiredProps.push(processedProp) 74 | } 75 | } 76 | 77 | var view = { 78 | name : componentName, 79 | requiredProps : requiredProps, 80 | props : processedProps, 81 | requiredArgList : requiredArgList, 82 | requiredArgListCall : requiredArgListCall, 83 | package : configuration.package, 84 | file : process.cwd() + "/" + file 85 | }; 86 | var renderedBase = Mustache.render(baseClassTemplate, view); 87 | var renderedImpl = Mustache.render(defaultImplClassTemplate, view); 88 | var renderedConnector = Mustache.render(connectorTemplate, view); 89 | 90 | //We are assuming maven (at least for now), we will be writting to target/generated-sources/vaadin-react 91 | var javaDir = "target/generated-sources/vaadin-react/" + getPackageAsPath(configuration.package) + "/"; 92 | var resourcesDir = "target/classes/" + getPackageAsPath(configuration.package) + "/"; 93 | mkdirs(javaDir); 94 | mkdirs(resourcesDir); 95 | fs.writeFileSync(javaDir + componentName + "_Base.java", renderedBase, 'utf8'); 96 | fs.writeFileSync(javaDir + componentName + "Impl.java", renderedImpl, 'utf8'); 97 | 98 | var connectorPath = resourcesDir + componentName + "SimpleConnector.js"; 99 | fs.writeFileSync(connectorPath, renderedConnector, 'utf8'); 100 | 101 | //export browserified connector 102 | var browserify = require('browserify'); 103 | var b = browserify(); 104 | b.add(connectorPath); 105 | b.bundle().pipe(fs.createWriteStream(resourcesDir + componentName + "Connector.js")); 106 | 107 | //We save the original simple connector and the browserified connector so the user can decide which to use in case he wants to optimize his "widgetset" 108 | 109 | 110 | //Copy the lib to the target folder - we are avoiding a maven distribution for now 111 | var libPackageFolder = "target/generated-sources/vaadin-react/com/nunopinheiro/vaadin_react"; 112 | mkdirs(libPackageFolder); 113 | fs.createReadStream(__dirname + "/lib/ReactComponent.java", "utf8").pipe(fs.createWriteStream(libPackageFolder + "/ReactComponent.java")); 114 | } 115 | 116 | function getPackageAsPath(package){ 117 | //I wanted to spend more time writting a comment about this "replace all" than making a decent function 118 | while(package.indexOf(".") > 0){ 119 | package = package.replace(".", "/"); 120 | } 121 | return package; 122 | } 123 | 124 | function addJavaType(properties, type){ 125 | // The existing React types can be seen in the official documentation: 126 | // https://facebook.github.io/react/docs/reusable-components.html 127 | switch(type) { 128 | case "string": 129 | properties.type = "String"; 130 | break; 131 | case "number": 132 | properties.type = "double"; 133 | break; 134 | case "bool": 135 | properties.type = "boolean"; 136 | break; 137 | case "func": 138 | //JavascriptFunction is a special vaadin type which enable handling client-side events on the server 139 | properties.type = "JavaScriptFunction"; 140 | properties.isFunction = true; 141 | break; 142 | case "object": 143 | properties.type = "elemental.json.JsonObject"; 144 | break; 145 | case "array": 146 | properties.type = "elemental.json.JsonArray"; 147 | break; 148 | case "symbol": 149 | //The type used on the server-side will be String, but it will be transformed into a Symbol on the client-side 150 | properties.type = "String"; 151 | properties.isSymbol = true; 152 | break; 153 | case "element": 154 | properties.type = "com.nunopinheiro.vaadin_react.ReactComponent"; 155 | properties.isElement = true; 156 | break; 157 | //These validation types are still unsupported 158 | case "node": 159 | case "instanceOf": 160 | case "enum": 161 | case "union": 162 | case "arrayOf": 163 | case "custom": 164 | case "shape": 165 | default: 166 | throw "Unsupported type: " + type 167 | } 168 | } 169 | 170 | function mkdirs(path){ 171 | //Had to do my own mkdirs... WOW 172 | // I am assuming the path is not absolute (does not start with '/') 173 | var splitted = path.split("/"); 174 | var path = ""; 175 | for(var part in splitted){ 176 | path += splitted[part] + "/" 177 | if(!fs.existsSync(path)){ 178 | fs.mkdirSync(path); 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /generator/lib/ReactComponent.java: -------------------------------------------------------------------------------- 1 | package com.nunopinheiro.vaadin_react; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.InvocationTargetException; 5 | import java.lang.reflect.Method; 6 | import java.lang.reflect.Type; 7 | import java.util.Map; 8 | import com.vaadin.server.JsonCodec; 9 | import com.vaadin.server.communication.JSONSerializer; 10 | import com.vaadin.ui.ConnectorTracker; 11 | import elemental.json.JsonValue; 12 | import elemental.json.Json; 13 | import elemental.json.JsonObject; 14 | import com.vaadin.server.EncodeResult; 15 | import com.vaadin.ui.AbstractJavaScriptComponent; 16 | 17 | /** 18 | This class is copied to the target folder to avoid distributing the project in maven. 19 | **/ 20 | public abstract class ReactComponent extends AbstractJavaScriptComponent{ 21 | 22 | //Turn the method into public 23 | public ReactComponentState getState(){ 24 | return (ReactComponentState) super.getState(); 25 | } 26 | 27 | /** 28 | Returns the type of the current component. 29 | Is required in the connector to enable renderization of embedded ReactComponents 30 | **/ 31 | public abstract String getComponentType(); 32 | 33 | //During react components composition we need to track the parent to allow updating the client-side state 34 | private ReactComponent reactParent; 35 | 36 | public ReactComponent getReactParent(){ 37 | return reactParent; 38 | } 39 | 40 | protected void setReactParent(ReactComponent reactParent){ 41 | this.reactParent = reactParent; 42 | } 43 | 44 | @Override 45 | public void markAsDirty() { 46 | if(getReactParent() != null){ 47 | getReactParent().markAsDirty(); 48 | } 49 | else{ 50 | super.markAsDirty(); 51 | } 52 | } 53 | 54 | /** 55 | Magic going on here to enable inner components. 56 | Hack 1: 57 | Vaadin serializes the javascript component state based on the type of the getter. 58 | If we add a ReactComponent inside another ReactComponent vaadin won't be able to calculate the right type, 59 | and serialize only the fields which exist on the supertype (ReactComponentState). 60 | To enable this we are hacking into vaadin internals to inject a custom serializer (CustomSerializer). 61 | This serializer delegates the serialization to Vaadin, but uses the concrete type of the state instead of the type on the signature. 62 | 63 | Hack 2: 64 | Using hack 1 to serialize the states vaadin won't be able to calculate a diff and the state of the object will be null (check JsonCodec.encode()@ vaadin-server) 65 | To enable our hack 1 we can only customly serialize inner components, not the top level one being rendered. 66 | To enable this, we created a ReactComponentStateWrapper. 67 | 68 | These hacks use lots of private methods, and can be broken in the future. 69 | **/ 70 | static{ 71 | initCustomSerializer(); 72 | } 73 | 74 | public static class ReactComponentState extends com.vaadin.shared.ui.JavaScriptComponentState{} 75 | 76 | public static class ReactComponentStateWrapper implements java.io.Serializable{ 77 | private ReactComponentState state; 78 | 79 | public ReactComponentStateWrapper(ReactComponentState state){ 80 | setState(state); 81 | } 82 | public ReactComponentState getState(){ 83 | 84 | return state; 85 | } 86 | 87 | public void setState(ReactComponentState state){ 88 | this.state = state; 89 | } 90 | } 91 | 92 | 93 | private static class CustomSerializer implements JSONSerializer { 94 | static final Method defaultSerializerMethod = setupSerializationMethod(); 95 | @Override 96 | 97 | public ReactComponentStateWrapper deserialize(Type type, JsonValue jsonValue, ConnectorTracker connectorTracker) { 98 | throw new RuntimeException("Unable to deserialize components"); 99 | } 100 | 101 | @Override 102 | public JsonValue serialize(ReactComponentStateWrapper value, ConnectorTracker connectorTracker) { 103 | try { 104 | EncodeResult result = (EncodeResult) defaultSerializerMethod.invoke(null, value.getState(), value.getState().getClass(), null, connectorTracker); 105 | return result.getEncodedValue(); 106 | } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 107 | throw new RuntimeException("Unable to serialize value", e); 108 | } 109 | } 110 | } 111 | 112 | private static Method setupSerializationMethod() { 113 | Method defaultSerializerMethod; 114 | try { 115 | defaultSerializerMethod = JsonCodec.class.getDeclaredMethod("encodeObject", Object.class, Class.class, JsonObject.class, 116 | ConnectorTracker.class); 117 | defaultSerializerMethod.setAccessible(true); 118 | } catch (NoSuchMethodException | SecurityException e) { 119 | throw new RuntimeException("Unable to setup serialization methods", e); 120 | } 121 | return defaultSerializerMethod; 122 | } 123 | 124 | 125 | public static void initCustomSerializer() { 126 | try { 127 | final Field serializersField = Class.forName("com.vaadin.server.JsonCodec").getDeclaredField("customSerializers"); 128 | serializersField.setAccessible(true); 129 | 130 | Map, JSONSerializer> serializers = (Map, JSONSerializer>) serializersField 131 | .get(null); 132 | 133 | if (!serializers.keySet().contains(ReactComponentStateWrapper.class)) { 134 | serializers.put(ReactComponentStateWrapper.class, new CustomSerializer()); 135 | } 136 | } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException | ClassNotFoundException e) { 137 | throw new RuntimeException("Unable to initialize custom serializer for JavascriptComponentState.", e); 138 | } 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /generator/reactReflectiveProptypes.js: -------------------------------------------------------------------------------- 1 | //Import this script to inject the reflective propTypes in react 2 | //We need to ensure that we are using the same react module as the component we are using 3 | //For this to happen our script can't depend on react, and we must import react from the target node_modules folder 4 | var React = require(process.cwd() + "/node_modules/react"); 5 | 6 | var originalPropTypes = React.PropTypes; 7 | var newPropTypes = {} 8 | 9 | for(var propType in originalPropTypes){ 10 | // Create a new reflective property each time the getter is called 11 | Object.defineProperty(newPropTypes, propType, 12 | { 13 | get: reflectiveGetter(propType) 14 | } 15 | ); 16 | } 17 | 18 | React.PropTypes = newPropTypes 19 | 20 | //Enforce different scope for each property 21 | function reflectiveGetter(propType){ 22 | return function(){ 23 | return createReflectivePropType(propType); 24 | } 25 | } 26 | 27 | function createReflectivePropType(type){ 28 | var fakePropType = null; 29 | //Used for propTypes with arguments 30 | fakePropType = function fakePropType(propTypes){ 31 | createInnerPropertyTypes(fakePropType, propTypes) 32 | return fakePropType; 33 | } 34 | 35 | fakePropType.type = type; 36 | fakePropType.isRequired = function(){} 37 | fakePropType.isRequired.type = type; 38 | fakePropType.isRequired.required = true; 39 | 40 | return fakePropType; 41 | } 42 | 43 | function createInnerPropertyTypes(outer, propTypes){ 44 | outer.inner = propTypes; 45 | outer.isRequired.inner = propTypes 46 | } 47 | -------------------------------------------------------------------------------- /generator/templates/BaseClassTemplate.java: -------------------------------------------------------------------------------- 1 | package {{package}}; 2 | 3 | import com.vaadin.ui.AbstractJavaScriptComponent; 4 | import com.vaadin.shared.ui.JavaScriptComponentState; 5 | import com.vaadin.ui.JavaScriptFunction; 6 | import elemental.json.JsonArray; 7 | import com.nunopinheiro.vaadin_react.ReactComponent; 8 | 9 | abstract public class {{ name }}_Base extends ReactComponent{ 10 | 11 | @Override 12 | public String getComponentType(){ 13 | return "{{name}}"; 14 | } 15 | 16 | public {{ name }}_Base({{requiredArgList}}){ 17 | //initialize required properties from constructor 18 | {{#requiredProps}} 19 | set{{upperName}}({{name}}); 20 | {{/requiredProps}} 21 | 22 | } 23 | 24 | @Override 25 | public {{name}}State getState(){ 26 | return ({{name}}State) super.getState(); 27 | } 28 | 29 | {{#props}} 30 | {{^isFunction}} 31 | {{^isElement}} 32 | public {{ type }} get{{upperName}}(){ 33 | return getState().get{{upperName}}(); 34 | } 35 | 36 | public void set{{upperName}}({{ type }} {{name}}){ 37 | if(getReactParent() != null){ 38 | getReactParent().markAsDirty(); 39 | } 40 | getState().set{{upperName}}({{name}}); 41 | } 42 | {{/isElement}} 43 | {{#isElement}} 44 | public ReactComponent {{ name }}; 45 | public ReactComponent get{{upperName}}(){ 46 | return {{name}}; 47 | } 48 | 49 | public void set{{upperName}}(ReactComponent {{name}}){ 50 | if(getReactParent() != null){ 51 | getReactParent().markAsDirty(); 52 | } 53 | if(this.{{name}} != null){ 54 | //Clean up react parent from former child 55 | this.{{name}}.setReactParent(null); 56 | } 57 | this.{{name}} = {{name}}; 58 | //Add this component as react parent of the other component, enabling client refreshes on child changes 59 | this.{{name}}.setReactParent(this); 60 | getState().set{{upperName}}(new ReactComponent.ReactComponentStateWrapper({{name}}.getState())); 61 | getState().set{{upperName}}ComponentType({{name}}.getComponentType()); 62 | } 63 | {{/isElement}} 64 | {{/isFunction}} 65 | {{/props}} 66 | 67 | //Register function handler and getters and setters 68 | {{#props}} 69 | {{#isFunction}} 70 | 71 | public {{ type }} {{ name }}; 72 | 73 | private void handle{{upperName}}(JsonArray args){ 74 | get{{upperName}}().call(args); 75 | } 76 | 77 | public {{ type }} get{{upperName}}(){ 78 | return {{name}}; 79 | } 80 | 81 | public void set{{upperName}}({{ type }} {{name}}){ 82 | this.{{name}} = {{name}}; 83 | if({{name}} != null){ 84 | addFunction("{{name}}Handler", this::handle{{upperName}}); 85 | } 86 | } 87 | {{/isFunction}} 88 | {{/props}} 89 | 90 | //Vaadin enforces the state to have an empty constructor 91 | public static class {{name}}State extends ReactComponent.ReactComponentState{ 92 | //Only fields which are not functions can be present on the state. Functions will be represented by the handlers 93 | {{#props}} 94 | {{^isFunction}} 95 | {{^isElement}} 96 | private {{ type }} {{ name }}; 97 | 98 | public {{ type }} get{{upperName}}(){ 99 | return {{name}}; 100 | } 101 | 102 | public void set{{upperName}}({{ type }} {{name}}){ 103 | this.{{name}} = {{name}}; 104 | } 105 | {{/isElement}} 106 | {{#isElement}} 107 | private ReactComponent.ReactComponentStateWrapper {{ name }}; 108 | private String {{ name }}ComponentType; 109 | 110 | public ReactComponent.ReactComponentStateWrapper get{{upperName}}(){ 111 | return {{name}}; 112 | } 113 | 114 | public void set{{upperName}}(ReactComponentStateWrapper {{name}}){ 115 | this.{{name}} = {{name}}; 116 | } 117 | 118 | public String get{{upperName}}ComponentType(){ 119 | return {{name}}ComponentType; 120 | } 121 | 122 | public void set{{upperName}}ComponentType(String {{name}}ComponentType){ 123 | this.{{name}}ComponentType = {{name}}ComponentType; 124 | } 125 | {{/isElement}} 126 | {{/isFunction}} 127 | {{/props}} 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /generator/templates/Connector.js: -------------------------------------------------------------------------------- 1 | //We need to calculate the vaadin client side name of the package wich we do by replacing '.' by '_' 2 | var ReactDOM = require("react-dom"); 3 | var React = require("react"); 4 | var module = require("{{& file}}"); 5 | 6 | // The module can be exported either by its name or as the default export 7 | var {{name}} = module.{{name}} || module; 8 | 9 | var package = "{{package}}"; 10 | while(package.indexOf(".") > 0){ 11 | package = package.replace(".", "_"); 12 | } 13 | 14 | var connectorName = package + "_" + "{{name}}Impl"; 15 | var renderFunction = "$vaadinReact{{name}}Render"; 16 | 17 | window[connectorName] = function() { 18 | this.onStateChange = function() { 19 | var component = window[renderFunction](this.getState()); 20 | ReactDOM.render(component, this.getElement()); 21 | } 22 | }; 23 | 24 | //The component can be rendered either from a top level (as a vaadin component), or within another vaadin component 25 | window[renderFunction] = function(state) { 26 | var Component = React.createFactory({{name}}); 27 | var props = {}; 28 | //add the rpc call to the component properties 29 | {{#props}} 30 | {{#isFunction}} 31 | props.{{name}} = this.{{name}}Handler; 32 | {{/isFunction}} 33 | {{/props}} 34 | //add the non function elements 35 | {{#props}} 36 | {{^isFunction}} 37 | {{^isSymbol}} 38 | {{^isElement}} 39 | props.{{name}} = state.{{name}}; 40 | {{/isElement}} 41 | {{/isSymbol}} 42 | {{#isSymbol}} 43 | props.{{name}} = Symbol(state.{{name}}); 44 | {{/isSymbol}} 45 | {{#isElement}} 46 | if(state.{{name}}ComponentType){ 47 | //Render an inner component 48 | var componentRenderer = window["$vaadinReact" + state.{{name}}ComponentType + "Render"]; 49 | props.{{name}} = componentRenderer(state.{{name}}); 50 | } 51 | {{/isElement}} 52 | {{/isFunction}} 53 | {{/props}} 54 | return Component(props); 55 | } 56 | -------------------------------------------------------------------------------- /generator/templates/DefaultImplementationClassTemplate.java: -------------------------------------------------------------------------------- 1 | package {{package}}; 2 | 3 | import com.vaadin.annotations.JavaScript; 4 | import com.vaadin.ui.JavaScriptFunction; 5 | 6 | /** 7 | This is the default generated class, you can directly use this class to instantiate your component 8 | Notice that the resources referred in the @Javascript tag will only be loaded after vaadin needs to present the component 9 | If you always use this component (and use it on your entry view) you have several options you can add the resources to you UI using the @JavaScript annotation 10 | 11 | If you are using vaadin embedded in a page, you may also opt to add the resources to the external page, so when vaadin needs to load the components they are already present. 12 | In that case, instead of this component, you should create a new class which inherits from {{ name }}_Base and use it instead 13 | **/ 14 | @JavaScript({"{{name}}Connector.js"}) 15 | public class {{ name }}Impl extends {{name}}_Base{ 16 | public {{ name }}Impl({{requiredArgList}}){ 17 | super({{requiredArgListCall}}); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vaadin-react", 3 | "dependencies": { 4 | "browserify": "", 5 | "mustache": "^2.2.1" 6 | }, 7 | "scripts": { 8 | "compile": "babel src/main/node --out-dir src/main/node;" 9 | }, 10 | "version": "0.0.2", 11 | "bin": "generator/generator.js", 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/NunoPinheiro/vaadin-react" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/container/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets" : ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /samples/container/.react-vaadin.config: -------------------------------------------------------------------------------- 1 | { 2 | "components" : ["src/main/node"], 3 | "package" : "com.nunopinheiro.vaadin_react" 4 | } 5 | -------------------------------------------------------------------------------- /samples/container/README.md: -------------------------------------------------------------------------------- 1 | vaadin-react simple sample 2 | ============== 3 | 4 | ## Instructions 5 | 1 - Install vaadin-react in your machine 6 | npm install -g vaadin-react 7 | 8 | 2 - Download this project npm dependencies 9 | npm install . 10 | 11 | 3 - Compile the react component that exists in this project 12 | npm run-script compile 13 | 14 | 4 - Run vaadin react to generate the vaadin component 15 | vaadin-react 16 | 17 | 5 - Compile the java code and start a local server 18 | mvn jetty:run 19 | 20 | The application should now be available at: 21 | 22 | http://localhost:8080/ 23 | -------------------------------------------------------------------------------- /samples/container/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-vaadin-simple-sample", 3 | "dependencies": { 4 | "react": "", 5 | "react-dom": "" 6 | }, 7 | "devDependencies": { 8 | "babel-preset-react": "", 9 | "babel-preset-es2015": "", 10 | "babel-cli": "", 11 | "browserify": "" 12 | }, 13 | "scripts": { 14 | "compile": "babel src/main/node --out-dir src/main/node;" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/container/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.nunopinheiro 7 | vaadin-react-composite-sample 8 | war 9 | 1.0-SNAPSHOT 10 | vaadin-react 11 | 12 | 13 | 7.6.7 14 | ${vaadin.version} 15 | 9.2.3.v20140905 16 | UTF-8 17 | 1.8 18 | 1.8 19 | 20 | 21 | 22 | 23 | vaadin-addons 24 | http://maven.vaadin.com/vaadin-addons 25 | 26 | 27 | vaadin-snapshots 28 | https://oss.sonatype.org/content/repositories/vaadin-snapshots/ 29 | 30 | false 31 | 32 | 33 | true 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | com.vaadin 42 | vaadin-bom 43 | ${vaadin.version} 44 | pom 45 | import 46 | 47 | 48 | 49 | 50 | 51 | 52 | javax.servlet 53 | javax.servlet-api 54 | 3.0.1 55 | provided 56 | 57 | 58 | com.vaadin 59 | vaadin-server 60 | 61 | 62 | com.vaadin 63 | vaadin-push 64 | 65 | 66 | com.vaadin 67 | vaadin-client 68 | provided 69 | 70 | 74 | 76 | 77 | com.vaadin 78 | vaadin-themes 79 | 80 | 81 | 82 | 83 | 84 | 85 | org.apache.maven.plugins 86 | maven-compiler-plugin 87 | 3.3 88 | 89 | 90 | org.apache.maven.plugins 91 | maven-resources-plugin 92 | 2.6 93 | 94 | 95 | org.apache.maven.plugins 96 | maven-war-plugin 97 | 2.3 98 | 99 | false 100 | 101 | WEB-INF/classes/VAADIN/gwt-unitCache/**, 102 | WEB-INF/classes/VAADIN/widgetsets/WEB-INF/** 103 | 104 | 105 | 106 | com.vaadin 107 | vaadin-maven-plugin 108 | ${vaadin.plugin.version} 109 | 110 | -Xmx512M -Xss1024k 111 | ${basedir}/target/classes/VAADIN/widgetsets 112 | false 113 | false 114 | 115 | true 116 | 117 | 118 | 119 | 120 | update-theme 121 | update-widgetset 122 | compile 123 | 124 | compile-theme 125 | 126 | 127 | 128 | 129 | 130 | org.apache.maven.plugins 131 | maven-source-plugin 132 | 2.4 133 | 134 | 135 | org.apache.maven.plugins 136 | maven-clean-plugin 137 | 2.6.1 138 | 139 | 140 | 141 | 142 | src/main/webapp/VAADIN/themes 143 | 144 | **/styles.css 145 | **/styles.scss.cache 146 | 147 | 148 | 149 | 150 | 151 | 152 | 154 | 155 | org.eclipse.jetty 156 | jetty-maven-plugin 157 | ${jetty.plugin.version} 158 | 159 | 2 160 | 161 | 162 | 163 | org.codehaus.mojo 164 | build-helper-maven-plugin 165 | 1.7 166 | 167 | 168 | add-source 169 | generate-sources 170 | 171 | add-source 172 | 173 | 174 | 175 | target/generated-sources/vaadin-react/ 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | vaadin-prerelease 188 | 189 | false 190 | 191 | 192 | 193 | 194 | vaadin-prereleases 195 | http://maven.vaadin.com/vaadin-prereleases 196 | 197 | 198 | 199 | 200 | vaadin-prereleases 201 | http://maven.vaadin.com/vaadin-prereleases 202 | 203 | 204 | 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /samples/container/src/main/java/com/nunopinheiro/vaadin_react/MyUI.java: -------------------------------------------------------------------------------- 1 | package com.nunopinheiro.vaadin_react; 2 | 3 | import javax.servlet.annotation.WebServlet; 4 | 5 | 6 | import com.vaadin.annotations.Theme; 7 | import com.vaadin.annotations.VaadinServletConfiguration; 8 | import com.vaadin.annotations.Widgetset; 9 | import com.vaadin.server.VaadinRequest; 10 | import com.vaadin.server.VaadinServlet; 11 | import com.vaadin.ui.Button; 12 | import com.vaadin.ui.Button.ClickEvent; 13 | import com.vaadin.ui.Label; 14 | import com.vaadin.ui.UI; 15 | import com.vaadin.ui.VerticalLayout; 16 | 17 | import elemental.json.Json; 18 | import elemental.json.JsonArray; 19 | 20 | 21 | /** 22 | * This UI is the application entry point. A UI may either represent a browser 23 | * window (or tab) or some part of a html page where a Vaadin application is 24 | * embedded. 25 | *

26 | * The UI is initialized using {@link #init(VaadinRequest)}. This method is 27 | * intended to be overridden to add component to the user interface and 28 | * initialize non-component functionality. 29 | */ 30 | @Theme("mytheme") 31 | @Widgetset("com.nunopinheiro.vaadin_react.MyAppWidgetset") 32 | public class MyUI extends UI { 33 | @Override 34 | protected void init(VaadinRequest vaadinRequest) { 35 | final VerticalLayout layout = new VerticalLayout(); 36 | TestComponentImpl outerContainer = new TestComponentImpl("Outer"); 37 | TestComponentImpl innerContainer = new TestComponentImpl("Inner"); 38 | 39 | outerContainer.setElement(innerContainer); 40 | Button incOuter = new Button("Increment outer"); 41 | Button incinner = new Button("Increment inner"); 42 | incOuter.addClickListener(new IncClickListener(outerContainer, "outer")); 43 | incinner.addClickListener(new IncClickListener(innerContainer, "inner")); 44 | 45 | layout.addComponent(outerContainer); 46 | layout.addComponent(incOuter); 47 | layout.addComponent(incinner); 48 | layout.setMargin(true); 49 | layout.setSpacing(true); 50 | 51 | setContent(layout); 52 | } 53 | 54 | class IncClickListener implements Button.ClickListener{ 55 | TestComponentImpl component; 56 | String text; 57 | int val = 0; 58 | public IncClickListener(TestComponentImpl component, String text){ 59 | this.text = text; 60 | this.component = component; 61 | component.setMessage(text + " " + val); 62 | } 63 | 64 | @Override 65 | public void buttonClick(ClickEvent event) { 66 | component.setMessage(text + " " + ++val); 67 | } 68 | 69 | } 70 | 71 | @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true) 72 | @VaadinServletConfiguration(ui = MyUI.class, productionMode = false) 73 | public static class MyUIServlet extends VaadinServlet { 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /samples/container/src/main/node/TestComponent.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | var React = require("react"); 7 | 8 | var TestComponent = exports.TestComponent = React.createClass({ 9 | displayName: "TestComponent", 10 | 11 | propTypes: { 12 | element: React.PropTypes.element, 13 | message: React.PropTypes.string.isRequired 14 | }, 15 | getInitialState: function getInitialState() { 16 | return {}; 17 | }, 18 | render: function render() { 19 | return React.createElement( 20 | "div", 21 | null, 22 | this.props.message, 23 | this.props.element 24 | ); 25 | } 26 | }); 27 | 28 | //HACK to enable view in browser 29 | if (typeof window != "undefined") { 30 | window.TestComponent = TestComponent; 31 | } -------------------------------------------------------------------------------- /samples/container/src/main/node/TestComponent.jsx: -------------------------------------------------------------------------------- 1 | var React = require("react"); 2 | 3 | export var TestComponent = React.createClass({ 4 | propTypes: { 5 | element : React.PropTypes.element, 6 | message : React.PropTypes.string.isRequired 7 | }, 8 | getInitialState : function(){ 9 | return {} 10 | }, 11 | render : function(){ 12 | return

13 | {this.props.message} 14 | {this.props.element} 15 |
; 16 | } 17 | }); 18 | 19 | 20 | 21 | //HACK to enable view in browser 22 | if(typeof window != "undefined"){ 23 | window.TestComponent = TestComponent; 24 | } 25 | -------------------------------------------------------------------------------- /samples/container/src/main/resources/com/nunopinheiro/vaadin_react/MyAppWidgetset.gwt.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/container/src/main/webapp/VAADIN/themes/mytheme/addons.scss: -------------------------------------------------------------------------------- 1 | /* This file is automatically managed and will be overwritten from time to time. */ 2 | /* Do not manually edit this file. */ 3 | 4 | /* Import and include this mixin into your project theme to include the addon themes */ 5 | @mixin addons { 6 | } 7 | 8 | -------------------------------------------------------------------------------- /samples/container/src/main/webapp/VAADIN/themes/mytheme/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NunoPinheiro/vaadin-react/7d2a2a97bc51e27cc88946538758e40122f64598/samples/container/src/main/webapp/VAADIN/themes/mytheme/favicon.ico -------------------------------------------------------------------------------- /samples/container/src/main/webapp/VAADIN/themes/mytheme/mytheme.scss: -------------------------------------------------------------------------------- 1 | // If you edit this file you need to compile the theme. See README.md for details. 2 | 3 | // Global variable overrides. Must be declared before importing Valo. 4 | 5 | // Defines the plaintext font size, weight and family. Font size affects general component sizing. 6 | //$v-font-size: 16px; 7 | //$v-font-weight: 300; 8 | //$v-font-family: "Open Sans", sans-serif; 9 | 10 | // Defines the border used by all components. 11 | //$v-border: 1px solid (v-shade 0.7); 12 | //$v-border-radius: 4px; 13 | 14 | // Affects the color of some component elements, e.g Button, Panel title, etc 15 | //$v-background-color: hsl(210, 0%, 98%); 16 | // Affects the color of content areas, e.g Panel and Window content, TextField input etc 17 | //$v-app-background-color: $v-background-color; 18 | 19 | // Affects the visual appearance of all components 20 | //$v-gradient: v-linear 8%; 21 | //$v-bevel-depth: 30%; 22 | //$v-shadow-opacity: 5%; 23 | 24 | // Defines colors for indicating status (focus, success, failure) 25 | //$v-focus-color: valo-focus-color(); // Calculates a suitable color automatically 26 | //$v-friendly-color: #2c9720; 27 | //$v-error-indicator-color: #ed473b; 28 | 29 | // For more information, see: https://vaadin.com/book/-/page/themes.valo.html 30 | // Example variants can be copy/pasted from https://vaadin.com/wiki/-/wiki/Main/Valo+Examples 31 | 32 | @import "../valo/valo.scss"; 33 | 34 | @mixin mytheme { 35 | @include valo; 36 | 37 | // Insert your own theme rules here 38 | } 39 | -------------------------------------------------------------------------------- /samples/container/src/main/webapp/VAADIN/themes/mytheme/styles.scss: -------------------------------------------------------------------------------- 1 | @import "mytheme.scss"; 2 | @import "addons.scss"; 3 | 4 | // This file prefixes all rules with the theme name to avoid causing conflicts with other themes. 5 | // The actual styles should be defined in mytheme.scss 6 | 7 | .mytheme { 8 | @include addons; 9 | @include mytheme; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /samples/simple/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets" : ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /samples/simple/.react-vaadin.config: -------------------------------------------------------------------------------- 1 | { 2 | "components" : ["src/main/node"], 3 | "package" : "com.nunopinheiro.vaadin_react" 4 | } 5 | -------------------------------------------------------------------------------- /samples/simple/README.md: -------------------------------------------------------------------------------- 1 | vaadin-react simple sample 2 | ============== 3 | 4 | ## Instructions 5 | 1 - Install vaadin-react in your machine 6 | npm install -g vaadin-react 7 | 8 | 2 - Download this project npm dependencies 9 | npm install . 10 | 11 | 3 - Compile the react component that exists in this project 12 | npm run-script compile 13 | 14 | 4 - Run vaadin react to generate the vaadin component 15 | vaadin-react 16 | 17 | 5 - Compile the java code and start a local server 18 | mvn jetty:run 19 | 20 | The application should now be available at: 21 | 22 | http://localhost:8080/ 23 | -------------------------------------------------------------------------------- /samples/simple/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-vaadin-simple-sample", 3 | "dependencies": { 4 | "react": "", 5 | "react-dom": "" 6 | }, 7 | "devDependencies": { 8 | "babel-preset-react": "", 9 | "babel-preset-es2015": "", 10 | "babel-cli": "", 11 | "browserify": "" 12 | }, 13 | "scripts": { 14 | "compile": "babel src/main/node --out-dir src/main/node;" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/simple/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.nunopinheiro 7 | vaadin-react-simple-sample 8 | war 9 | 1.0-SNAPSHOT 10 | vaadin-react 11 | 12 | 13 | 7.6.7 14 | ${vaadin.version} 15 | 9.2.3.v20140905 16 | UTF-8 17 | 1.8 18 | 1.8 19 | 20 | 21 | 22 | 23 | vaadin-addons 24 | http://maven.vaadin.com/vaadin-addons 25 | 26 | 27 | vaadin-snapshots 28 | https://oss.sonatype.org/content/repositories/vaadin-snapshots/ 29 | 30 | false 31 | 32 | 33 | true 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | com.vaadin 42 | vaadin-bom 43 | ${vaadin.version} 44 | pom 45 | import 46 | 47 | 48 | 49 | 50 | 51 | 52 | javax.servlet 53 | javax.servlet-api 54 | 3.0.1 55 | provided 56 | 57 | 58 | com.vaadin 59 | vaadin-server 60 | 61 | 62 | com.vaadin 63 | vaadin-push 64 | 65 | 66 | com.vaadin 67 | vaadin-client 68 | provided 69 | 70 | 74 | 76 | 77 | com.vaadin 78 | vaadin-themes 79 | 80 | 81 | 82 | 83 | 84 | 85 | org.apache.maven.plugins 86 | maven-compiler-plugin 87 | 3.3 88 | 89 | 90 | org.apache.maven.plugins 91 | maven-resources-plugin 92 | 2.6 93 | 94 | 95 | org.apache.maven.plugins 96 | maven-war-plugin 97 | 2.3 98 | 99 | false 100 | 101 | WEB-INF/classes/VAADIN/gwt-unitCache/**, 102 | WEB-INF/classes/VAADIN/widgetsets/WEB-INF/** 103 | 104 | 105 | 106 | com.vaadin 107 | vaadin-maven-plugin 108 | ${vaadin.plugin.version} 109 | 110 | -Xmx512M -Xss1024k 111 | ${basedir}/target/classes/VAADIN/widgetsets 112 | false 113 | false 114 | 115 | true 116 | 117 | 118 | 119 | 120 | update-theme 121 | update-widgetset 122 | compile 123 | 124 | compile-theme 125 | 126 | 127 | 128 | 129 | 130 | org.apache.maven.plugins 131 | maven-source-plugin 132 | 2.4 133 | 134 | 135 | org.apache.maven.plugins 136 | maven-clean-plugin 137 | 2.6.1 138 | 139 | 140 | 141 | 142 | src/main/webapp/VAADIN/themes 143 | 144 | **/styles.css 145 | **/styles.scss.cache 146 | 147 | 148 | 149 | 150 | 151 | 152 | 154 | 155 | org.eclipse.jetty 156 | jetty-maven-plugin 157 | ${jetty.plugin.version} 158 | 159 | 2 160 | 161 | 162 | 163 | org.codehaus.mojo 164 | build-helper-maven-plugin 165 | 1.7 166 | 167 | 168 | add-source 169 | generate-sources 170 | 171 | add-source 172 | 173 | 174 | 175 | target/generated-sources/vaadin-react/ 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | vaadin-prerelease 188 | 189 | false 190 | 191 | 192 | 193 | 194 | vaadin-prereleases 195 | http://maven.vaadin.com/vaadin-prereleases 196 | 197 | 198 | 199 | 200 | vaadin-prereleases 201 | http://maven.vaadin.com/vaadin-prereleases 202 | 203 | 204 | 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /samples/simple/src/main/java/com/nunopinheiro/vaadin_react/MyUI.java: -------------------------------------------------------------------------------- 1 | package com.nunopinheiro.vaadin_react; 2 | 3 | import javax.servlet.annotation.WebServlet; 4 | 5 | import com.vaadin.annotations.Theme; 6 | import com.vaadin.annotations.VaadinServletConfiguration; 7 | import com.vaadin.annotations.Widgetset; 8 | import com.vaadin.server.VaadinRequest; 9 | import com.vaadin.server.VaadinServlet; 10 | import com.vaadin.ui.Button; 11 | import com.vaadin.ui.Label; 12 | import com.vaadin.ui.TextField; 13 | import com.vaadin.ui.UI; 14 | import com.vaadin.ui.VerticalLayout; 15 | 16 | import elemental.js.json.JsJsonArray; 17 | import elemental.json.JsonArray; 18 | 19 | /** 20 | * This UI is the application entry point. A UI may either represent a browser 21 | * window (or tab) or some part of a html page where a Vaadin application is 22 | * embedded. 23 | *

24 | * The UI is initialized using {@link #init(VaadinRequest)}. This method is 25 | * intended to be overridden to add component to the user interface and 26 | * initialize non-component functionality. 27 | */ 28 | @Theme("mytheme") 29 | @Widgetset("com.nunopinheiro.vaadin_react.MyAppWidgetset") 30 | public class MyUI extends UI { 31 | 32 | @Override 33 | protected void init(VaadinRequest vaadinRequest) { 34 | final VerticalLayout layout = new VerticalLayout(); 35 | 36 | layout.addComponent(new TestComponentImpl("Nuno", this::handle)); 37 | layout.setMargin(true); 38 | layout.setSpacing(true); 39 | 40 | setContent(layout); 41 | } 42 | 43 | private void handle(JsonArray args){ 44 | System.out.println("name changed to " + args.getString(0)); 45 | } 46 | 47 | @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true) 48 | @VaadinServletConfiguration(ui = MyUI.class, productionMode = false) 49 | public static class MyUIServlet extends VaadinServlet { 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /samples/simple/src/main/node/TestComponent.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | var React = require("react"); 7 | 8 | var TestComponent = exports.TestComponent = React.createClass({ 9 | displayName: "TestComponent", 10 | 11 | propTypes: { 12 | name: React.PropTypes.string.isRequired, 13 | onNameChange: React.PropTypes.func.isRequired 14 | }, 15 | getInitialState: function getInitialState() { 16 | return { "name": this.props.name }; 17 | }, 18 | render: function render() { 19 | return React.createElement( 20 | "div", 21 | null, 22 | React.createElement( 23 | "h1", 24 | null, 25 | "Hello, ", 26 | this.state.name 27 | ), 28 | "Change Name :", 29 | React.createElement("input", { type: "text", onChange: this.nameChanged }), 30 | React.createElement( 31 | "button", 32 | { onClick: this.triggerNameChangeEvent }, 33 | "Click to change name on server" 34 | ) 35 | ); 36 | }, 37 | nameChanged: function nameChanged(e) { 38 | if (this.state.name != e.target.value) { 39 | this.setState({ "name": e.target.value }); 40 | } 41 | }, 42 | triggerNameChangeEvent: function triggerNameChangeEvent(e) { 43 | this.props.onNameChange(this.state.name); 44 | } 45 | }); 46 | 47 | //HACK to enable view in browser 48 | if (typeof window != "undefined") { 49 | window.TestComponent = TestComponent; 50 | } -------------------------------------------------------------------------------- /samples/simple/src/main/node/TestComponent.jsx: -------------------------------------------------------------------------------- 1 | var React = require("react"); 2 | 3 | export var TestComponent = React.createClass({ 4 | propTypes: { 5 | name : React.PropTypes.string.isRequired, 6 | onNameChange : React.PropTypes.func.isRequired 7 | }, 8 | getInitialState : function(){ 9 | return {"name" : this.props.name} 10 | }, 11 | render : function(){ 12 | return

13 |

Hello, {this.state.name}

14 | Change Name : 15 | 16 | 17 |
; 18 | }, 19 | nameChanged : function(e){ 20 | if(this.state.name != e.target.value){ 21 | this.setState({"name" : e.target.value}) 22 | } 23 | }, 24 | triggerNameChangeEvent : function(e){ 25 | this.props.onNameChange(this.state.name) 26 | } 27 | }); 28 | 29 | 30 | 31 | //HACK to enable view in browser 32 | if(typeof window != "undefined"){ 33 | window.TestComponent = TestComponent; 34 | } 35 | -------------------------------------------------------------------------------- /samples/simple/src/main/resources/com/nunopinheiro/vaadin_react/MyAppWidgetset.gwt.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/simple/src/main/webapp/VAADIN/themes/mytheme/addons.scss: -------------------------------------------------------------------------------- 1 | /* This file is automatically managed and will be overwritten from time to time. */ 2 | /* Do not manually edit this file. */ 3 | 4 | /* Import and include this mixin into your project theme to include the addon themes */ 5 | @mixin addons { 6 | } 7 | 8 | -------------------------------------------------------------------------------- /samples/simple/src/main/webapp/VAADIN/themes/mytheme/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NunoPinheiro/vaadin-react/7d2a2a97bc51e27cc88946538758e40122f64598/samples/simple/src/main/webapp/VAADIN/themes/mytheme/favicon.ico -------------------------------------------------------------------------------- /samples/simple/src/main/webapp/VAADIN/themes/mytheme/mytheme.scss: -------------------------------------------------------------------------------- 1 | // If you edit this file you need to compile the theme. See README.md for details. 2 | 3 | // Global variable overrides. Must be declared before importing Valo. 4 | 5 | // Defines the plaintext font size, weight and family. Font size affects general component sizing. 6 | //$v-font-size: 16px; 7 | //$v-font-weight: 300; 8 | //$v-font-family: "Open Sans", sans-serif; 9 | 10 | // Defines the border used by all components. 11 | //$v-border: 1px solid (v-shade 0.7); 12 | //$v-border-radius: 4px; 13 | 14 | // Affects the color of some component elements, e.g Button, Panel title, etc 15 | //$v-background-color: hsl(210, 0%, 98%); 16 | // Affects the color of content areas, e.g Panel and Window content, TextField input etc 17 | //$v-app-background-color: $v-background-color; 18 | 19 | // Affects the visual appearance of all components 20 | //$v-gradient: v-linear 8%; 21 | //$v-bevel-depth: 30%; 22 | //$v-shadow-opacity: 5%; 23 | 24 | // Defines colors for indicating status (focus, success, failure) 25 | //$v-focus-color: valo-focus-color(); // Calculates a suitable color automatically 26 | //$v-friendly-color: #2c9720; 27 | //$v-error-indicator-color: #ed473b; 28 | 29 | // For more information, see: https://vaadin.com/book/-/page/themes.valo.html 30 | // Example variants can be copy/pasted from https://vaadin.com/wiki/-/wiki/Main/Valo+Examples 31 | 32 | @import "../valo/valo.scss"; 33 | 34 | @mixin mytheme { 35 | @include valo; 36 | 37 | // Insert your own theme rules here 38 | } 39 | -------------------------------------------------------------------------------- /samples/simple/src/main/webapp/VAADIN/themes/mytheme/styles.scss: -------------------------------------------------------------------------------- 1 | @import "mytheme.scss"; 2 | @import "addons.scss"; 3 | 4 | // This file prefixes all rules with the theme name to avoid causing conflicts with other themes. 5 | // The actual styles should be defined in mytheme.scss 6 | 7 | .mytheme { 8 | @include addons; 9 | @include mytheme; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /samples/third-party-component/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets" : ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /samples/third-party-component/.react-vaadin.config: -------------------------------------------------------------------------------- 1 | { 2 | "components" : ["node_modules/react-markdown/src/react-markdown.js"], 3 | "package" : "com.nunopinheiro.vaadin_react" 4 | } 5 | -------------------------------------------------------------------------------- /samples/third-party-component/README.md: -------------------------------------------------------------------------------- 1 | vaadin-react third-party sample 2 | ============== 3 | 4 | This project is a sample of a third party component being transformed (markdown). 5 | 6 | ## Instructions 7 | 1 - Install vaadin-react in your machine 8 | npm install -g vaadin-react 9 | 10 | 2 - Download this project npm dependencies 11 | npm install . 12 | 13 | 3 - Compile the react component that exists in this project 14 | npm run-script compile 15 | 16 | 4 - Run vaadin react to generate the vaadin component 17 | vaadin-react 18 | 19 | 5 - Compile the java code and start a local server 20 | mvn jetty:run 21 | 22 | The application should now be available at: 23 | 24 | http://localhost:8080/ 25 | -------------------------------------------------------------------------------- /samples/third-party-component/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-vaadin-third-party-sample", 3 | "dependencies": { 4 | "react": "", 5 | "react-dom": "", 6 | "react-markdown": "^2.4.2" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /samples/third-party-component/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.nunopinheiro 7 | vaadin-react-third-party-sample 8 | war 9 | 1.0-SNAPSHOT 10 | vaadin-react 11 | 12 | 13 | 7.6.7 14 | ${vaadin.version} 15 | 9.2.3.v20140905 16 | UTF-8 17 | 1.8 18 | 1.8 19 | 20 | 21 | 22 | 23 | vaadin-addons 24 | http://maven.vaadin.com/vaadin-addons 25 | 26 | 27 | vaadin-snapshots 28 | https://oss.sonatype.org/content/repositories/vaadin-snapshots/ 29 | 30 | false 31 | 32 | 33 | true 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | com.vaadin 42 | vaadin-bom 43 | ${vaadin.version} 44 | pom 45 | import 46 | 47 | 48 | 49 | 50 | 51 | 52 | javax.servlet 53 | javax.servlet-api 54 | 3.0.1 55 | provided 56 | 57 | 58 | com.vaadin 59 | vaadin-server 60 | 61 | 62 | com.vaadin 63 | vaadin-push 64 | 65 | 66 | com.vaadin 67 | vaadin-client 68 | provided 69 | 70 | 74 | 76 | 77 | com.vaadin 78 | vaadin-themes 79 | 80 | 81 | 82 | 83 | 84 | 85 | org.apache.maven.plugins 86 | maven-compiler-plugin 87 | 3.3 88 | 89 | 90 | org.apache.maven.plugins 91 | maven-resources-plugin 92 | 2.6 93 | 94 | 95 | org.apache.maven.plugins 96 | maven-war-plugin 97 | 2.3 98 | 99 | false 100 | 101 | WEB-INF/classes/VAADIN/gwt-unitCache/**, 102 | WEB-INF/classes/VAADIN/widgetsets/WEB-INF/** 103 | 104 | 105 | 106 | com.vaadin 107 | vaadin-maven-plugin 108 | ${vaadin.plugin.version} 109 | 110 | -Xmx512M -Xss1024k 111 | ${basedir}/target/classes/VAADIN/widgetsets 112 | false 113 | false 114 | 115 | true 116 | 117 | 118 | 119 | 120 | update-theme 121 | update-widgetset 122 | compile 123 | 124 | compile-theme 125 | 126 | 127 | 128 | 129 | 130 | org.apache.maven.plugins 131 | maven-source-plugin 132 | 2.4 133 | 134 | 135 | org.apache.maven.plugins 136 | maven-clean-plugin 137 | 2.6.1 138 | 139 | 140 | 141 | 142 | src/main/webapp/VAADIN/themes 143 | 144 | **/styles.css 145 | **/styles.scss.cache 146 | 147 | 148 | 149 | 150 | 151 | 152 | 154 | 155 | org.eclipse.jetty 156 | jetty-maven-plugin 157 | ${jetty.plugin.version} 158 | 159 | 2 160 | 161 | 162 | 163 | org.codehaus.mojo 164 | build-helper-maven-plugin 165 | 1.7 166 | 167 | 168 | add-source 169 | generate-sources 170 | 171 | add-source 172 | 173 | 174 | 175 | target/generated-sources/vaadin-react/ 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | vaadin-prerelease 188 | 189 | false 190 | 191 | 192 | 193 | 194 | vaadin-prereleases 195 | http://maven.vaadin.com/vaadin-prereleases 196 | 197 | 198 | 199 | 200 | vaadin-prereleases 201 | http://maven.vaadin.com/vaadin-prereleases 202 | 203 | 204 | 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /samples/third-party-component/src/main/java/com/nunopinheiro/vaadin_react/MyUI.java: -------------------------------------------------------------------------------- 1 | package com.nunopinheiro.vaadin_react; 2 | 3 | import javax.servlet.annotation.WebServlet; 4 | 5 | import com.vaadin.annotations.Theme; 6 | import com.vaadin.annotations.VaadinServletConfiguration; 7 | import com.vaadin.annotations.Widgetset; 8 | import com.vaadin.server.VaadinRequest; 9 | import com.vaadin.server.VaadinServlet; 10 | import com.vaadin.ui.Button; 11 | import com.vaadin.ui.Label; 12 | import com.vaadin.ui.TextArea; 13 | import com.vaadin.ui.UI; 14 | import com.vaadin.ui.VerticalLayout; 15 | 16 | import elemental.json.JsonArray; 17 | 18 | /** 19 | * This UI is the application entry point. A UI may either represent a browser 20 | * window (or tab) or some part of a html page where a Vaadin application is 21 | * embedded. 22 | *

23 | * The UI is initialized using {@link #init(VaadinRequest)}. This method is 24 | * intended to be overridden to add component to the user interface and 25 | * initialize non-component functionality. 26 | */ 27 | @Theme("mytheme") 28 | @Widgetset("com.nunopinheiro.vaadin_react.MyAppWidgetset") 29 | public class MyUI extends UI { 30 | 31 | @Override 32 | protected void init(VaadinRequest vaadinRequest) { 33 | final VerticalLayout layout = new VerticalLayout(); 34 | 35 | Label label = new Label("Write your markup in this Vaadin component, click on the button to submit it and it will be rendered on the React markdown component"); 36 | TextArea textArea = new TextArea(); 37 | 38 | ReactMarkdownImpl reactMarkdown = new ReactMarkdownImpl(""); 39 | Button button = new Button("Click to Preview"); 40 | //Update the React Markdown component with the markdown written in the Vaadin textarea 41 | button.addClickListener((x) ->reactMarkdown.setSource(textArea.getValue())); 42 | 43 | 44 | layout.addComponent(label); 45 | layout.addComponent(textArea); 46 | layout.addComponent(button); 47 | layout.addComponent(reactMarkdown); 48 | 49 | layout.setMargin(true); 50 | layout.setSpacing(true); 51 | 52 | setContent(layout); 53 | } 54 | 55 | private void handle(JsonArray args){ 56 | System.out.println("this will break client side because the component expects a return"); 57 | } 58 | 59 | @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true) 60 | @VaadinServletConfiguration(ui = MyUI.class, productionMode = false) 61 | public static class MyUIServlet extends VaadinServlet { 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /samples/third-party-component/src/main/resources/com/nunopinheiro/vaadin_react/MyAppWidgetset.gwt.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/third-party-component/src/main/webapp/VAADIN/themes/mytheme/addons.scss: -------------------------------------------------------------------------------- 1 | /* This file is automatically managed and will be overwritten from time to time. */ 2 | /* Do not manually edit this file. */ 3 | 4 | /* Import and include this mixin into your project theme to include the addon themes */ 5 | @mixin addons { 6 | } 7 | 8 | -------------------------------------------------------------------------------- /samples/third-party-component/src/main/webapp/VAADIN/themes/mytheme/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NunoPinheiro/vaadin-react/7d2a2a97bc51e27cc88946538758e40122f64598/samples/third-party-component/src/main/webapp/VAADIN/themes/mytheme/favicon.ico -------------------------------------------------------------------------------- /samples/third-party-component/src/main/webapp/VAADIN/themes/mytheme/mytheme.scss: -------------------------------------------------------------------------------- 1 | // If you edit this file you need to compile the theme. See README.md for details. 2 | 3 | // Global variable overrides. Must be declared before importing Valo. 4 | 5 | // Defines the plaintext font size, weight and family. Font size affects general component sizing. 6 | //$v-font-size: 16px; 7 | //$v-font-weight: 300; 8 | //$v-font-family: "Open Sans", sans-serif; 9 | 10 | // Defines the border used by all components. 11 | //$v-border: 1px solid (v-shade 0.7); 12 | //$v-border-radius: 4px; 13 | 14 | // Affects the color of some component elements, e.g Button, Panel title, etc 15 | //$v-background-color: hsl(210, 0%, 98%); 16 | // Affects the color of content areas, e.g Panel and Window content, TextField input etc 17 | //$v-app-background-color: $v-background-color; 18 | 19 | // Affects the visual appearance of all components 20 | //$v-gradient: v-linear 8%; 21 | //$v-bevel-depth: 30%; 22 | //$v-shadow-opacity: 5%; 23 | 24 | // Defines colors for indicating status (focus, success, failure) 25 | //$v-focus-color: valo-focus-color(); // Calculates a suitable color automatically 26 | //$v-friendly-color: #2c9720; 27 | //$v-error-indicator-color: #ed473b; 28 | 29 | // For more information, see: https://vaadin.com/book/-/page/themes.valo.html 30 | // Example variants can be copy/pasted from https://vaadin.com/wiki/-/wiki/Main/Valo+Examples 31 | 32 | @import "../valo/valo.scss"; 33 | 34 | @mixin mytheme { 35 | @include valo; 36 | 37 | // Insert your own theme rules here 38 | } 39 | -------------------------------------------------------------------------------- /samples/third-party-component/src/main/webapp/VAADIN/themes/mytheme/styles.scss: -------------------------------------------------------------------------------- 1 | @import "mytheme.scss"; 2 | @import "addons.scss"; 3 | 4 | // This file prefixes all rules with the theme name to avoid causing conflicts with other themes. 5 | // The actual styles should be defined in mytheme.scss 6 | 7 | .mytheme { 8 | @include addons; 9 | @include mytheme; 10 | 11 | } 12 | --------------------------------------------------------------------------------