├── .editorconfig ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── .prettierignore ├── .prettierrc ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── angular.json ├── apps ├── .gitkeep ├── angular-app │ ├── browserslist │ ├── jest.config.js │ ├── src │ │ ├── app │ │ │ ├── app.component.html │ │ │ ├── app.component.scss │ │ │ ├── app.component.spec.ts │ │ │ ├── app.component.ts │ │ │ └── app.module.ts │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── main.ts │ │ ├── polyfills.ts │ │ ├── styles.scss │ │ └── test-setup.ts │ ├── tsconfig.app.json │ ├── tsconfig.json │ ├── tsconfig.spec.json │ └── tslint.json ├── angular-ivy-app │ ├── browserslist │ ├── jest.config.js │ ├── src │ │ ├── app │ │ │ ├── app.component.html │ │ │ ├── app.component.scss │ │ │ ├── app.component.spec.ts │ │ │ ├── app.component.ts │ │ │ └── app.module.ts │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── main.ts │ │ ├── polyfills.ts │ │ ├── styles.scss │ │ └── test-setup.ts │ ├── tsconfig.app.json │ ├── tsconfig.json │ ├── tsconfig.spec.json │ └── tslint.json └── react-app │ ├── browserslist │ ├── jest.config.js │ ├── src │ ├── app │ │ └── app.tsx │ ├── assets │ │ └── .gitkeep │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── index.html │ ├── main.tsx │ ├── polyfills.ts │ └── styles.scss │ ├── tsconfig.app.json │ ├── tsconfig.json │ ├── tsconfig.spec.json │ └── tslint.json ├── jest.config.js ├── libs ├── .gitkeep ├── angular-component-library │ ├── README.md │ ├── ng-package.json │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── lib │ │ │ ├── angular-component-library.module.ts │ │ │ ├── hello-world │ │ │ └── hello-world.component.ts │ │ │ └── timer │ │ │ └── timer.component.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tslint.json ├── angular-wrappers │ ├── README.md │ ├── jest.config.js │ ├── ng-package.json │ ├── package.json │ ├── src │ │ ├── lib │ │ │ ├── .gitkeep │ │ │ ├── angular-wrapper.module.ts │ │ │ └── hello-jsx.component.tsx │ │ └── public_api.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.spec.json │ └── tslint.json ├── react-component-library │ ├── README.md │ ├── jest.config.js │ ├── ng-package.json │ ├── package.json │ ├── src │ │ ├── lib │ │ │ ├── .gitkeep │ │ │ └── react.component.tsx │ │ └── public_api.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.spec.json │ └── tslint.json ├── react-ng-wrapper │ ├── README.md │ ├── ng-package.json │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── lib │ │ │ └── react-ng-wrapper.tsx │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tslint.json └── react-wrappers │ ├── README.md │ ├── jest.config.js │ ├── ng-package.json │ ├── package.json │ ├── src │ ├── index.ts │ └── lib │ │ ├── hello.tsx │ │ └── timer.tsx │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.spec.json │ └── tslint.json ├── nx.json ├── package.json ├── renovate.json ├── tools ├── schematics │ └── .gitkeep └── tsconfig.tools.json ├── tsconfig.json ├── tslint.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | /node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | 37 | # System Files 38 | .DS_Store 39 | Thumbs.db 40 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at rjgunning+github@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Richard Sahrakorpi 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 | # Angular React hybrid aplications 2 | 3 | Proof of Concept Angular-React Hybrid project based on ng-packagr example application https://github.com/ng-packagr/ng-packagr/tree/master/integration 4 | 5 | This project has 2 component libraries, 1 written in react and one in Angular. Using the `react-wrappers` library, we then convert the angular components into react compatible components. Likewise using the `angular-wrappers` library we convert the react components for use in angular applications. 6 | 7 | Three demo applications are included in this repository 8 | 9 | - `react-app` - is a react application which imports both the `react-component-library` and the `angular-component-library` (via the `react-wrappers` and `react-ng-wrapper` libraries). 10 | - `angular-app` - imports the `react-component-library` (via the `angular-wrappers` library) 11 | - `angular-ivy-app` - imports the `angular-component-library` to show they can still be used within angular. 12 | 13 | This project was generated using [Nx](https://nx.dev). 14 | 15 | ## Build 16 | 17 | Run `yarn build:all` to build all the libraries. 18 | 19 | ## Development server 20 | 21 | Run `yarn start [app]` (where app is one of `react-app`, `angular-app` or `angular-ivy-app`). 22 | 23 | Navigate to `http://localhost:4200/`. 24 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "", 5 | "projects": { 6 | "react-app": { 7 | "root": "apps/react-app/", 8 | "sourceRoot": "apps/react-app/src", 9 | "projectType": "application", 10 | "prefix": "hybrid", 11 | "schematics": { 12 | "@nrwl/schematics:component": { 13 | "style": "scss" 14 | } 15 | }, 16 | "architect": { 17 | "build": { 18 | "builder": "@nrwl/web:build", 19 | "options": { 20 | "outputPath": "dist/apps/react-app", 21 | "index": "apps/react-app/src/index.html", 22 | "main": "apps/react-app/src/main.tsx", 23 | "polyfills": "apps/react-app/src/polyfills.ts", 24 | "tsConfig": "apps/react-app/tsconfig.app.json", 25 | "assets": [ 26 | "apps/react-app/src/favicon.ico", 27 | "apps/react-app/src/assets" 28 | ], 29 | "styles": [ 30 | "apps/react-app/src/styles.scss" 31 | ], 32 | "scripts": [], 33 | "webpackConfig": "@nrwl/react/plugins/babel" 34 | }, 35 | "configurations": { 36 | "production": { 37 | "fileReplacements": [ 38 | { 39 | "replace": "apps/react-app/src/environments/environment.ts", 40 | "with": "apps/react-app/src/environments/environment.prod.ts" 41 | } 42 | ], 43 | "optimization": true, 44 | "outputHashing": "all", 45 | "sourceMap": false, 46 | "extractCss": true, 47 | "namedChunks": false, 48 | "extractLicenses": true, 49 | "vendorChunk": false, 50 | "budgets": [ 51 | { 52 | "type": "initial", 53 | "maximumWarning": "2mb", 54 | "maximumError": "5mb" 55 | } 56 | ] 57 | } 58 | } 59 | }, 60 | "serve": { 61 | "builder": "@nrwl/web:dev-server", 62 | "options": { 63 | "buildTarget": "react-app:build" 64 | }, 65 | "configurations": { 66 | "production": { 67 | "buildTarget": "react-app:build:production" 68 | } 69 | } 70 | } 71 | } 72 | }, 73 | "angular-app": { 74 | "root": "apps/angular-app/", 75 | "sourceRoot": "apps/angular-app/src", 76 | "projectType": "application", 77 | "prefix": "hybrid", 78 | "schematics": { 79 | "@nrwl/schematics:component": { 80 | "style": "scss" 81 | } 82 | }, 83 | "architect": { 84 | "build": { 85 | "builder": "@angular-devkit/build-angular:browser", 86 | "options": { 87 | "outputPath": "dist/apps/angular-app", 88 | "index": "apps/angular-app/src/index.html", 89 | "main": "apps/angular-app/src/main.ts", 90 | "polyfills": "apps/angular-app/src/polyfills.ts", 91 | "tsConfig": "apps/angular-app/tsconfig.app.json", 92 | "assets": [ 93 | "apps/angular-app/src/favicon.ico", 94 | "apps/angular-app/src/assets" 95 | ], 96 | "styles": [ 97 | "apps/angular-app/src/styles.scss" 98 | ], 99 | "scripts": [], 100 | "es5BrowserSupport": true 101 | }, 102 | "configurations": { 103 | "production": { 104 | "fileReplacements": [ 105 | { 106 | "replace": "apps/angular-app/src/environments/environment.ts", 107 | "with": "apps/angular-app/src/environments/environment.prod.ts" 108 | } 109 | ], 110 | "optimization": true, 111 | "outputHashing": "all", 112 | "sourceMap": false, 113 | "extractCss": true, 114 | "namedChunks": false, 115 | "aot": true, 116 | "extractLicenses": true, 117 | "vendorChunk": false, 118 | "buildOptimizer": true, 119 | "budgets": [ 120 | { 121 | "type": "initial", 122 | "maximumWarning": "2mb", 123 | "maximumError": "5mb" 124 | } 125 | ] 126 | } 127 | } 128 | }, 129 | "serve": { 130 | "builder": "@angular-devkit/build-angular:dev-server", 131 | "options": { 132 | "browserTarget": "angular-app:build" 133 | }, 134 | "configurations": { 135 | "production": { 136 | "browserTarget": "angular-app:build:production" 137 | } 138 | } 139 | } 140 | } 141 | }, 142 | "angular-ivy-app": { 143 | "root": "apps/angular-ivy-app/", 144 | "sourceRoot": "apps/angular-ivy-app/src", 145 | "projectType": "application", 146 | "prefix": "hybrid", 147 | "schematics": { 148 | "@nrwl/schematics:component": { 149 | "style": "scss" 150 | } 151 | }, 152 | "architect": { 153 | "build": { 154 | "builder": "@angular-devkit/build-angular:browser", 155 | "options": { 156 | "outputPath": "dist/apps/angular-ivy-app", 157 | "index": "apps/angular-ivy-app/src/index.html", 158 | "main": "apps/angular-ivy-app/src/main.ts", 159 | "polyfills": "apps/angular-ivy-app/src/polyfills.ts", 160 | "tsConfig": "apps/angular-ivy-app/tsconfig.app.json", 161 | "assets": [ 162 | "apps/angular-ivy-app/src/favicon.ico", 163 | "apps/angular-ivy-app/src/assets" 164 | ], 165 | "styles": [ 166 | "apps/angular-ivy-app/src/styles.scss" 167 | ], 168 | "scripts": [], 169 | "es5BrowserSupport": true 170 | }, 171 | "configurations": { 172 | "production": { 173 | "fileReplacements": [ 174 | { 175 | "replace": "apps/angular-ivy-app/src/environments/environment.ts", 176 | "with": "apps/angular-ivy-app/src/environments/environment.prod.ts" 177 | } 178 | ], 179 | "optimization": true, 180 | "outputHashing": "all", 181 | "sourceMap": false, 182 | "extractCss": true, 183 | "namedChunks": false, 184 | "aot": true, 185 | "extractLicenses": true, 186 | "vendorChunk": false, 187 | "buildOptimizer": true, 188 | "budgets": [ 189 | { 190 | "type": "initial", 191 | "maximumWarning": "2mb", 192 | "maximumError": "5mb" 193 | } 194 | ] 195 | } 196 | } 197 | }, 198 | "serve": { 199 | "builder": "@angular-devkit/build-angular:dev-server", 200 | "options": { 201 | "browserTarget": "angular-ivy-app:build" 202 | }, 203 | "configurations": { 204 | "production": { 205 | "browserTarget": "angular-ivy-app:build:production" 206 | } 207 | } 208 | } 209 | } 210 | }, 211 | "angular-wrappers": { 212 | "root": "libs/angular-wrappers", 213 | "sourceRoot": "libs/angular-wrappers/src", 214 | "projectType": "library", 215 | "prefix": "hybrid", 216 | "architect": { 217 | "build": { 218 | "builder": "@angular-devkit/build-ng-packagr:build", 219 | "options": { 220 | "tsConfig": "libs/angular-wrappers/tsconfig.lib.json", 221 | "project": "libs/angular-wrappers/ng-package.json" 222 | } 223 | } 224 | }, 225 | "schematics": { 226 | "@nrwl/schematics:component": { 227 | "styleext": "scss" 228 | } 229 | } 230 | }, 231 | "react-component-library": { 232 | "root": "libs/react-component-library", 233 | "sourceRoot": "libs/react-component-library/src", 234 | "projectType": "library", 235 | "prefix": "hybrid", 236 | "architect": { 237 | "build": { 238 | "builder": "@angular-devkit/build-ng-packagr:build", 239 | "options": { 240 | "tsConfig": "libs/react-component-library/tsconfig.lib.json", 241 | "project": "libs/react-component-library/ng-package.json" 242 | } 243 | } 244 | } 245 | }, 246 | "react-ng-wrapper": { 247 | "root": "libs/react-ng-wrapper", 248 | "sourceRoot": "libs/react-ng-wrapper/src", 249 | "projectType": "library", 250 | "schematics": {}, 251 | "architect": { 252 | "build": { 253 | "builder": "@angular-devkit/build-ng-packagr:build", 254 | "options": { 255 | "tsConfig": "libs/react-ng-wrapper/tsconfig.lib.json", 256 | "project": "libs/react-ng-wrapper/ng-package.json" 257 | } 258 | } 259 | } 260 | }, 261 | "react-wrappers": { 262 | "root": "libs/react-wrappers", 263 | "sourceRoot": "libs/react-wrappers/src", 264 | "projectType": "library", 265 | "schematics": {}, 266 | "architect": { 267 | "build": { 268 | "builder": "@angular-devkit/build-ng-packagr:build", 269 | "options": { 270 | "tsConfig": "libs/react-wrappers/tsconfig.lib.json", 271 | "project": "libs/react-wrappers/ng-package.json" 272 | } 273 | } 274 | } 275 | }, 276 | "angular-component-library": { 277 | "projectType": "library", 278 | "root": "libs/angular-component-library", 279 | "sourceRoot": "libs/angular-component-library/src", 280 | "prefix": "hybrid", 281 | "architect": { 282 | "build": { 283 | "builder": "@angular-devkit/build-ng-packagr:build", 284 | "options": { 285 | "tsConfig": "libs/angular-component-library/tsconfig.lib.json", 286 | "project": "libs/angular-component-library/ng-package.json" 287 | } 288 | } 289 | }, 290 | "schematics": {} 291 | } 292 | }, 293 | "cli": { 294 | "warnings": { 295 | "typescriptMismatch": false, 296 | "versionMismatch": false 297 | }, 298 | "defaultCollection": "@nrwl/angular", 299 | "packageManager": "yarn" 300 | }, 301 | "schematics": { 302 | "@nrwl/schematics:application": { 303 | "style": "scss", 304 | "framework": "react" 305 | }, 306 | "@nrwl/react": { 307 | "application": { 308 | "style": "css", 309 | "linter": "eslint", 310 | "babel": true 311 | }, 312 | "component": { 313 | "style": "css" 314 | }, 315 | "library": { 316 | "style": "css", 317 | "linter": "eslint" 318 | } 319 | }, 320 | "@nrwl/next": { 321 | "application": { 322 | "linter": "eslint" 323 | } 324 | }, 325 | "@nrwl/web": { 326 | "application": { 327 | "linter": "eslint" 328 | } 329 | }, 330 | "@nrwl/schematics:library": { 331 | "style": "scss" 332 | } 333 | }, 334 | "defaultProject": "react-app" 335 | } 336 | -------------------------------------------------------------------------------- /apps/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /apps/angular-app/browserslist: -------------------------------------------------------------------------------- 1 | # This file is currently used by autoprefixer to adjust CSS to support the below specified browsers 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | # 5 | # For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed 6 | 7 | > 0.5% 8 | last 2 versions 9 | Firefox ESR 10 | not dead 11 | not IE 9-11 -------------------------------------------------------------------------------- /apps/angular-app/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'angular-app', 3 | preset: '../../jest.config.js', 4 | coverageDirectory: '../../coverage/apps/angular-app/', 5 | snapshotSerializers: [ 6 | 'jest-preset-angular/AngularSnapshotSerializer.js', 7 | 'jest-preset-angular/HTMLCommentSerializer.js' 8 | ] 9 | }; 10 | -------------------------------------------------------------------------------- /apps/angular-app/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |

Angular Root!

2 | 3 | 4 | -------------------------------------------------------------------------------- /apps/angular-app/src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | :host{ 2 | text-align: center; 3 | font-size: xx-large; 4 | } 5 | 6 | hybrid-hello-jsx { 7 | margin-bottom: 2rem; 8 | } 9 | 10 | hybrid-hello-jsx, hybrid-hello-world, hybrid-timer { 11 | display:block; 12 | } 13 | -------------------------------------------------------------------------------- /apps/angular-app/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, async } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | 4 | describe('AppComponent', () => { 5 | beforeEach(async(() => { 6 | TestBed.configureTestingModule({ 7 | declarations: [AppComponent] 8 | }).compileComponents(); 9 | })); 10 | 11 | it('should create the app', () => { 12 | const fixture = TestBed.createComponent(AppComponent); 13 | const app = fixture.debugElement.componentInstance; 14 | expect(app).toBeTruthy(); 15 | }); 16 | 17 | it(`should have as title 'angular-app'`, () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.debugElement.componentInstance; 20 | expect(app.title).toEqual('angular-app'); 21 | }); 22 | 23 | it('should render title in a h1 tag', () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | fixture.detectChanges(); 26 | const compiled = fixture.debugElement.nativeElement; 27 | expect(compiled.querySelector('h1').textContent).toContain( 28 | 'Welcome to angular-app!' 29 | ); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /apps/angular-app/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'hybrid-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.scss'] 7 | }) 8 | export class AppComponent { 9 | title = 'angular-app'; 10 | } 11 | -------------------------------------------------------------------------------- /apps/angular-app/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { NgModule } from '@angular/core'; 3 | 4 | import { AppComponent } from './app.component'; 5 | import { AngularWrapperModule } from '@hybrid/angular-wrappers'; 6 | 7 | @NgModule({ 8 | declarations: [AppComponent], 9 | imports: [ 10 | BrowserModule, 11 | AngularWrapperModule 12 | ], 13 | providers: [], 14 | bootstrap: [AppComponent] 15 | }) 16 | export class AppModule { } 17 | -------------------------------------------------------------------------------- /apps/angular-app/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RGunning/Angular-React-hybrid/51034938cc44bbd2dbe0e9356d8833611cea3aef/apps/angular-app/src/assets/.gitkeep -------------------------------------------------------------------------------- /apps/angular-app/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /apps/angular-app/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /apps/angular-app/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RGunning/Angular-React-hybrid/51034938cc44bbd2dbe0e9356d8833611cea3aef/apps/angular-app/src/favicon.ico -------------------------------------------------------------------------------- /apps/angular-app/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AngularApp 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /apps/angular-app/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic() 12 | .bootstrapModule(AppModule) 13 | .catch(err => console.error(err)); 14 | -------------------------------------------------------------------------------- /apps/angular-app/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 22 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 23 | 24 | /** 25 | * Web Animations `@angular/platform-browser/animations` 26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 28 | */ 29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 30 | 31 | /** 32 | * By default, zone.js will patch all possible macroTask and DomEvents 33 | * user can disable parts of macroTask/DomEvents patch by setting following flags 34 | * because those flags need to be set before `zone.js` being loaded, and webpack 35 | * will put import in the top of bundle, so user need to create a separate file 36 | * in this directory (for example: zone-flags.ts), and put the following flags 37 | * into that file, and then add the following code before importing zone.js. 38 | * import './zone-flags.ts'; 39 | * 40 | * The flags allowed in zone-flags.ts are listed here. 41 | * 42 | * The following flags will work for all browsers. 43 | * 44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 46 | * (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 47 | * 48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 50 | * 51 | * (window as any).__Zone_enable_cross_context_check = true; 52 | * 53 | */ 54 | 55 | /*************************************************************************************************** 56 | * Zone JS is required by default for Angular itself. 57 | */ 58 | import 'zone.js/dist/zone'; // Included with Angular CLI. 59 | 60 | /*************************************************************************************************** 61 | * APPLICATION IMPORTS 62 | */ 63 | -------------------------------------------------------------------------------- /apps/angular-app/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /apps/angular-app/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular'; 2 | -------------------------------------------------------------------------------- /apps/angular-app/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "exclude": ["src/test-setup.ts", "**/*.spec.ts"], 8 | "include": ["**/*.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /apps/angular-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "types": ["node", "jest"] 5 | }, 6 | "angularCompilerOptions": { 7 | "enableIvy": false 8 | }, 9 | "include": ["**/*.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/angular-app/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/angular-app/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tslint.json", 3 | "rules": { 4 | "directive-selector": [true, "attribute", "hybrid", "camelCase"], 5 | "component-selector": [true, "element", "hybrid", "kebab-case"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/angular-ivy-app/browserslist: -------------------------------------------------------------------------------- 1 | # This file is currently used by autoprefixer to adjust CSS to support the below specified browsers 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | # 5 | # For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed 6 | 7 | > 0.5% 8 | last 2 versions 9 | Firefox ESR 10 | not dead 11 | not IE 9-11 -------------------------------------------------------------------------------- /apps/angular-ivy-app/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'angular-app', 3 | preset: '../../jest.config.js', 4 | coverageDirectory: '../../coverage/apps/angular-app/', 5 | snapshotSerializers: [ 6 | 'jest-preset-angular/AngularSnapshotSerializer.js', 7 | 'jest-preset-angular/HTMLCommentSerializer.js' 8 | ] 9 | }; 10 | -------------------------------------------------------------------------------- /apps/angular-ivy-app/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |

Angular Root!

2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /apps/angular-ivy-app/src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | :host{ 2 | text-align: center; 3 | font-size: xx-large; 4 | } 5 | 6 | hybrid-hello-jsx { 7 | margin-bottom: 2rem; 8 | } 9 | 10 | hybrid-hello-jsx, hybrid-hello-world, hybrid-timer { 11 | display:block; 12 | } 13 | -------------------------------------------------------------------------------- /apps/angular-ivy-app/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, async } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | 4 | describe('AppComponent', () => { 5 | beforeEach(async(() => { 6 | TestBed.configureTestingModule({ 7 | declarations: [AppComponent] 8 | }).compileComponents(); 9 | })); 10 | 11 | it('should create the app', () => { 12 | const fixture = TestBed.createComponent(AppComponent); 13 | const app = fixture.debugElement.componentInstance; 14 | expect(app).toBeTruthy(); 15 | }); 16 | 17 | it(`should have as title 'angular-app'`, () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.debugElement.componentInstance; 20 | expect(app.title).toEqual('angular-app'); 21 | }); 22 | 23 | it('should render title in a h1 tag', () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | fixture.detectChanges(); 26 | const compiled = fixture.debugElement.nativeElement; 27 | expect(compiled.querySelector('h1').textContent).toContain( 28 | 'Welcome to angular-app!' 29 | ); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /apps/angular-ivy-app/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'hybrid-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.scss'] 7 | }) 8 | export class AppComponent { 9 | title = 'angular-app'; 10 | } 11 | -------------------------------------------------------------------------------- /apps/angular-ivy-app/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { NgModule } from '@angular/core'; 3 | 4 | import { AppComponent } from './app.component'; 5 | import { AngularComponentLibraryModule } from '@hybrid/angular-component-library' 6 | //import { AngularWrapperModule } from '@hybrid/angular-wrappers' 7 | @NgModule({ 8 | declarations: [AppComponent], 9 | imports: [ 10 | BrowserModule, 11 | AngularComponentLibraryModule, 12 | //AngularWrapperModule 13 | ], 14 | providers: [], 15 | bootstrap: [AppComponent] 16 | }) 17 | export class AppModule { } 18 | -------------------------------------------------------------------------------- /apps/angular-ivy-app/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RGunning/Angular-React-hybrid/51034938cc44bbd2dbe0e9356d8833611cea3aef/apps/angular-ivy-app/src/assets/.gitkeep -------------------------------------------------------------------------------- /apps/angular-ivy-app/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /apps/angular-ivy-app/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /apps/angular-ivy-app/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RGunning/Angular-React-hybrid/51034938cc44bbd2dbe0e9356d8833611cea3aef/apps/angular-ivy-app/src/favicon.ico -------------------------------------------------------------------------------- /apps/angular-ivy-app/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AngularApp 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /apps/angular-ivy-app/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic() 12 | .bootstrapModule(AppModule) 13 | .catch(err => console.error(err)); 14 | -------------------------------------------------------------------------------- /apps/angular-ivy-app/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 22 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 23 | 24 | /** 25 | * Web Animations `@angular/platform-browser/animations` 26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 28 | */ 29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 30 | 31 | /** 32 | * By default, zone.js will patch all possible macroTask and DomEvents 33 | * user can disable parts of macroTask/DomEvents patch by setting following flags 34 | * because those flags need to be set before `zone.js` being loaded, and webpack 35 | * will put import in the top of bundle, so user need to create a separate file 36 | * in this directory (for example: zone-flags.ts), and put the following flags 37 | * into that file, and then add the following code before importing zone.js. 38 | * import './zone-flags.ts'; 39 | * 40 | * The flags allowed in zone-flags.ts are listed here. 41 | * 42 | * The following flags will work for all browsers. 43 | * 44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 46 | * (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 47 | * 48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 50 | * 51 | * (window as any).__Zone_enable_cross_context_check = true; 52 | * 53 | */ 54 | 55 | /*************************************************************************************************** 56 | * Zone JS is required by default for Angular itself. 57 | */ 58 | import 'zone.js/dist/zone'; // Included with Angular CLI. 59 | 60 | /*************************************************************************************************** 61 | * APPLICATION IMPORTS 62 | */ 63 | -------------------------------------------------------------------------------- /apps/angular-ivy-app/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /apps/angular-ivy-app/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular'; 2 | -------------------------------------------------------------------------------- /apps/angular-ivy-app/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "exclude": ["src/test-setup.ts", "**/*.spec.ts"], 8 | "include": ["**/*.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /apps/angular-ivy-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "types": ["node", "jest"] 5 | }, 6 | "include": ["**/*.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /apps/angular-ivy-app/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/angular-ivy-app/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tslint.json", 3 | "rules": { 4 | "directive-selector": [true, "attribute", "hybrid", "camelCase"], 5 | "component-selector": [true, "element", "hybrid", "kebab-case"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/react-app/browserslist: -------------------------------------------------------------------------------- 1 | # This file is currently used by autoprefixer to adjust CSS to support the below specified browsers 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | # 5 | # For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed 6 | 7 | > 0.5% 8 | last 2 versions 9 | Firefox ESR 10 | not dead 11 | not IE 9-11 -------------------------------------------------------------------------------- /apps/react-app/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: "react-app", 3 | preset: "../../jest.config.js", 4 | transform: { 5 | "^.+\\.[tj]sx?$": "ts-jest" 6 | }, 7 | moduleFileExtensions: ["ts", "tsx", "js", "jsx", "html"], 8 | coverageDirectory: "../../coverage/apps/react-app/" 9 | }; 10 | -------------------------------------------------------------------------------- /apps/react-app/src/app/app.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { ReactTimerComponent, ReactHelloComponent } from '@hybrid/react-wrappers'; 3 | import { HelloJSX } from '@hybrid/react-component-library' 4 | export class App extends React.Component { 5 | constructor(props) { 6 | super(props); 7 | 8 | this.state = { 9 | name: "project-react", 10 | }; 11 | } 12 | 13 | componentDidMount() { 14 | setTimeout(() => { 15 | this.setState({ name: "project-angular-react" }) 16 | }, 2000); 17 | } 18 | 19 | onStuff(e) { 20 | console.log(`stuff happened ${e}`) 21 | } 22 | 23 | render() { 24 | return ( 25 |
26 |
27 | 28 |
29 | 30 |
31 | 32 | 33 |
34 |
35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /apps/react-app/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RGunning/Angular-React-hybrid/51034938cc44bbd2dbe0e9356d8833611cea3aef/apps/react-app/src/assets/.gitkeep -------------------------------------------------------------------------------- /apps/react-app/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /apps/react-app/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /apps/react-app/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RGunning/Angular-React-hybrid/51034938cc44bbd2dbe0e9356d8833611cea3aef/apps/react-app/src/favicon.ico -------------------------------------------------------------------------------- /apps/react-app/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | TestWorkspace 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /apps/react-app/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import { App } from "./app/app"; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | 8 | -------------------------------------------------------------------------------- /apps/react-app/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file contains polyfills loaded on all browsers 3 | **/ 4 | //import 'core-js/stable'; 5 | 6 | import 'regenerator-runtime/runtime'; 7 | -------------------------------------------------------------------------------- /apps/react-app/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /apps/react-app/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "exclude": ["src/test-setup.ts", "**/*.spec.ts"], 8 | "include": ["**/*.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /apps/react-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "jsx": "react", 5 | "allowJs": true, 6 | "esModuleInterop": true, 7 | "allowSyntheticDefaultImports": true, 8 | "types": ["node", "jest"] 9 | }, 10 | "include": ["**/*.ts", "**/*.tsx"] 11 | } 12 | -------------------------------------------------------------------------------- /apps/react-app/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "**/*.spec.ts", 10 | "**/*.spec.tsx", 11 | "**/*.spec.js", 12 | "**/*.spec.jsx", 13 | "**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /apps/react-app/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tslint.json", 3 | "rules": [] 4 | } 5 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testMatch: ['**/+(*.)+(spec|test).+(ts|js)?(x)'], 3 | transform: { 4 | '^.+\\.(ts|js|html)$': 'ts-jest' 5 | }, 6 | resolver: '@nrwl/jest/plugins/resolver', 7 | moduleFileExtensions: ['ts', 'js', 'html'], 8 | coverageReporters: ['html'] 9 | }; 10 | -------------------------------------------------------------------------------- /libs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RGunning/Angular-React-hybrid/51034938cc44bbd2dbe0e9356d8833611cea3aef/libs/.gitkeep -------------------------------------------------------------------------------- /libs/angular-component-library/README.md: -------------------------------------------------------------------------------- 1 | # angular-component-library 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | -------------------------------------------------------------------------------- /libs/angular-component-library/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/angular-component-library", 4 | "lib": { 5 | "entryFile": "src/index.ts", 6 | "umdModuleIds": { 7 | "react": "React", 8 | "react-dom": "ReactDOM" 9 | }, 10 | "jsx": "react" 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /libs/angular-component-library/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@hybrid/angular-component-library", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^8.2.5", 6 | "@angular/core": "^8.2.5" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /libs/angular-component-library/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/angular-component-library.module'; 2 | export * from './lib/timer/timer.component'; 3 | export * from './lib/hello-world/hello-world.component'; 4 | -------------------------------------------------------------------------------- /libs/angular-component-library/src/lib/angular-component-library.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { TimerComponent } from './timer/timer.component'; 4 | import { HelloWorldComponent } from './hello-world/hello-world.component'; 5 | 6 | @NgModule({ 7 | imports: [CommonModule], 8 | declarations: [TimerComponent, HelloWorldComponent], 9 | exports: [TimerComponent, HelloWorldComponent] 10 | }) 11 | export class AngularComponentLibraryModule { } 12 | -------------------------------------------------------------------------------- /libs/angular-component-library/src/lib/hello-world/hello-world.component.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Input, 3 | Output, 4 | EventEmitter, 5 | OnInit, 6 | Component, 7 | OnChanges, 8 | } from '@angular/core'; 9 | 10 | @Component({ selector: 'hybrid-hello-world', template: 'Hello {{name}}!' }) 11 | export class HelloWorldComponent implements OnInit, OnChanges { 12 | @Input() name = 'world'; 13 | @Output() stuff = new EventEmitter(); 14 | 15 | ngOnInit() { 16 | setTimeout(() => { 17 | this.stuff.next('loaded'); 18 | }, 1000); 19 | } 20 | 21 | ngOnChanges(changes){ 22 | console.log(changes) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /libs/angular-component-library/src/lib/timer/timer.component.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Component, 3 | OnInit, 4 | OnDestroy, 5 | ɵmarkDirty as markDirty, 6 | ChangeDetectionStrategy 7 | } from '@angular/core'; 8 | import { Subscription, timer } from 'rxjs'; 9 | 10 | @Component({ 11 | selector: 'hybrid-timer', 12 | template: `counter: {{counter}}`, 13 | changeDetection: ChangeDetectionStrategy.OnPush 14 | }) 15 | export class TimerComponent implements OnInit, OnDestroy { 16 | 17 | private counterSubscription: Subscription; 18 | public counter: number; 19 | 20 | constructor() { } 21 | 22 | ngOnInit() { 23 | this.counterSubscription = timer(0, 1000) 24 | .subscribe(c => { 25 | this.counter = c; 26 | markDirty(this); 27 | }); 28 | } 29 | 30 | ngOnDestroy() { 31 | this.counterSubscription.unsubscribe(); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /libs/angular-component-library/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "types": [] 5 | }, 6 | "include": ["**/*.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /libs/angular-component-library/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "target": "es2015", 6 | "declaration": true, 7 | "inlineSources": true, 8 | "types": [], 9 | "lib": ["dom", "es2018"] 10 | }, 11 | "angularCompilerOptions": { 12 | "annotateForClosureCompiler": true, 13 | "skipTemplateCodegen": true, 14 | "strictMetadataEmit": true, 15 | "fullTemplateTypeCheck": true, 16 | "strictInjectionParameters": true, 17 | "enableResourceInlining": true 18 | }, 19 | "exclude": ["src/test.ts", "**/*.spec.ts"] 20 | } 21 | -------------------------------------------------------------------------------- /libs/angular-component-library/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tslint.json", 3 | "rules": { 4 | "directive-selector": [true, "attribute", "hybrid", "camelCase"], 5 | "component-selector": [true, "element", "hybrid", "kebab-case"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /libs/angular-wrappers/README.md: -------------------------------------------------------------------------------- 1 | # TestReact 2 | 3 | This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 7.2.0. 4 | 5 | ## Code scaffolding 6 | 7 | Run `ng generate component component-name --project angular-wrappers` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project angular-wrappers`. 8 | 9 | > Note: Don't forget to add `--project angular-wrappers` or else it will be added to the default project in your `angular.json` file. 10 | 11 | ## Build 12 | 13 | Run `ng build angular-wrappers` to build the project. The build artifacts will be stored in the `dist/` directory. 14 | 15 | ## Publishing 16 | 17 | After building your library with `ng build angular-wrappers`, go to the dist folder `cd dist/angular-wrappers` and run `npm publish`. 18 | 19 | ## Running unit tests 20 | 21 | Run `ng test angular-wrappers` to execute the unit tests via [Karma](https://karma-runner.github.io). 22 | 23 | ## Further help 24 | 25 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 26 | -------------------------------------------------------------------------------- /libs/angular-wrappers/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'angular-wrappers', 3 | preset: '../../jest.config.js', 4 | coverageDirectory: '../../coverage/libs/angular-wrappers' 5 | }; 6 | -------------------------------------------------------------------------------- /libs/angular-wrappers/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/angular-wrappers", 4 | "lib": { 5 | "entryFile": "src/public_api.ts", 6 | "umdModuleIds": { 7 | "react": "React", 8 | "react-dom": "ReactDOM" 9 | }, 10 | "jsx": "react" 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /libs/angular-wrappers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@hybrid/angular-wrappers", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^8.2.5", 6 | "@angular/core": "^8.2.5" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /libs/angular-wrappers/src/lib/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RGunning/Angular-React-hybrid/51034938cc44bbd2dbe0e9356d8833611cea3aef/libs/angular-wrappers/src/lib/.gitkeep -------------------------------------------------------------------------------- /libs/angular-wrappers/src/lib/angular-wrapper.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { HelloJSXComponent } from './hello-jsx.component'; 4 | 5 | @NgModule({ 6 | declarations: [HelloJSXComponent], 7 | imports: [CommonModule], 8 | exports: [HelloJSXComponent], 9 | providers: [], 10 | }) 11 | export class AngularWrapperModule {} 12 | -------------------------------------------------------------------------------- /libs/angular-wrappers/src/lib/hello-jsx.component.tsx: -------------------------------------------------------------------------------- 1 | import { Component, AfterViewInit, ElementRef } from '@angular/core'; 2 | import * as React from 'react'; 3 | import * as ReactDOM from 'react-dom'; 4 | import { HelloJSX } from '@hybrid/react-component-library'; 5 | 6 | @Component({ 7 | selector: 'hybrid-hello-jsx', 8 | template: ``, 9 | styles: [``] 10 | }) 11 | export class HelloJSXComponent implements AfterViewInit { 12 | 13 | constructor(private hostRef: ElementRef) { } 14 | 15 | ngAfterViewInit(): void { 16 | const hostElement = this.hostRef.nativeElement; 17 | const LabelToShow = () => ( 18 | // Actual use here, might include data-binding in a real world scenario 19 | 20 | ); 21 | ReactDOM.render(, hostElement); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /libs/angular-wrappers/src/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/hello-jsx.component'; 2 | export * from './lib/angular-wrapper.module'; 3 | -------------------------------------------------------------------------------- /libs/angular-wrappers/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "jsx": "react", 5 | "esModuleInterop": true, 6 | "allowSyntheticDefaultImports": true, 7 | "types": ["node", "jest"] 8 | }, 9 | "include": ["**/*.ts", "src/lib/index.tsx"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/angular-wrappers/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "target": "es2015", 6 | "module": "es2015", 7 | "moduleResolution": "node", 8 | "declaration": true, 9 | "sourceMap": true, 10 | "inlineSources": true, 11 | "emitDecoratorMetadata": true, 12 | "experimentalDecorators": true, 13 | "allowSyntheticDefaultImports": true, 14 | "importHelpers": true, 15 | "types": [], 16 | "lib": ["dom", "es2018"] 17 | }, 18 | "exclude": ["src/test.ts", "**/*.spec.ts"] 19 | } 20 | -------------------------------------------------------------------------------- /libs/angular-wrappers/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": ["**/*.spec.ts", "**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /libs/angular-wrappers/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tslint.json", 3 | "rules": [] 4 | } 5 | -------------------------------------------------------------------------------- /libs/react-component-library/README.md: -------------------------------------------------------------------------------- 1 | # TestReact 2 | 3 | This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 7.2.0. 4 | 5 | ## Code scaffolding 6 | 7 | Run `ng generate component component-name --project angular-wrappers` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project angular-wrappers`. 8 | 9 | > Note: Don't forget to add `--project angular-wrappers` or else it will be added to the default project in your `angular.json` file. 10 | 11 | ## Build 12 | 13 | Run `ng build angular-wrappers` to build the project. The build artifacts will be stored in the `dist/` directory. 14 | 15 | ## Publishing 16 | 17 | After building your library with `ng build angular-wrappers`, go to the dist folder `cd dist/angular-wrappers` and run `npm publish`. 18 | 19 | ## Running unit tests 20 | 21 | Run `ng test angular-wrappers` to execute the unit tests via [Karma](https://karma-runner.github.io). 22 | 23 | ## Further help 24 | 25 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 26 | -------------------------------------------------------------------------------- /libs/react-component-library/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'angular-wrappers', 3 | preset: '../../jest.config.js', 4 | coverageDirectory: '../../coverage/libs/angular-wrappers' 5 | }; 6 | -------------------------------------------------------------------------------- /libs/react-component-library/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/react-component-library", 4 | "lib": { 5 | "entryFile": "src/public_api.ts", 6 | "umdModuleIds": { 7 | "react": "React", 8 | "react-dom": "ReactDOM" 9 | }, 10 | "jsx": "react" 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /libs/react-component-library/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@hybrid/react-component-library", 3 | "version": "0.0.1" 4 | } 5 | -------------------------------------------------------------------------------- /libs/react-component-library/src/lib/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RGunning/Angular-React-hybrid/51034938cc44bbd2dbe0e9356d8833611cea3aef/libs/react-component-library/src/lib/.gitkeep -------------------------------------------------------------------------------- /libs/react-component-library/src/lib/react.component.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | // Simulating the use of an external library that contains React Components 4 | export class HelloJSX extends React.Component { 5 | render() { 6 | return ( 7 | 8 | ); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /libs/react-component-library/src/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/react.component'; 2 | -------------------------------------------------------------------------------- /libs/react-component-library/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "jsx": "react", 5 | "esModuleInterop": true, 6 | "allowSyntheticDefaultImports": true, 7 | "types": ["node", "jest"] 8 | }, 9 | "include": ["**/*.ts", "src/lib/index.tsx"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/react-component-library/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "target": "es2015", 6 | "module": "es2015", 7 | "moduleResolution": "node", 8 | "declaration": true, 9 | "sourceMap": true, 10 | "inlineSources": true, 11 | "emitDecoratorMetadata": true, 12 | "experimentalDecorators": true, 13 | "allowSyntheticDefaultImports": true, 14 | "importHelpers": true, 15 | "types": [], 16 | "lib": ["dom", "es2018"] 17 | }, 18 | "exclude": ["src/test.ts", "**/*.spec.ts"] 19 | } 20 | -------------------------------------------------------------------------------- /libs/react-component-library/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": ["**/*.spec.ts", "**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /libs/react-component-library/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tslint.json", 3 | "rules": [] 4 | } 5 | -------------------------------------------------------------------------------- /libs/react-ng-wrapper/README.md: -------------------------------------------------------------------------------- 1 | # react-ng-wrapper 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Running unit tests 6 | 7 | Run `nx test react-ng-wrapper` to execute the unit tests via [Jest](https://jestjs.io). 8 | -------------------------------------------------------------------------------- /libs/react-ng-wrapper/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/react-ng-wrapper", 4 | "lib": { 5 | "entryFile": "src/index.ts", 6 | "umdModuleIds": { 7 | "react": "React", 8 | "react-dom": "ReactDOM" 9 | }, 10 | "jsx": "react" 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /libs/react-ng-wrapper/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@hybrid/react-ng-wrapper", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^8.2.5", 6 | "@angular/core": "^8.2.5" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /libs/react-ng-wrapper/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/react-ng-wrapper'; 2 | -------------------------------------------------------------------------------- /libs/react-ng-wrapper/src/lib/react-ng-wrapper.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { 4 | ɵrenderComponent as renderComponent, 5 | ɵmarkDirty as markDirty, 6 | ɵLifecycleHooksFeature as LifecycleHooksFeature, 7 | ɵComponentType as componentType, 8 | ɵComponentDef as ComponentDef, 9 | ɵNG_COMPONENT_DEF as NG_COMPONENT_DEF, 10 | SimpleChange, 11 | SimpleChanges, 12 | OnChanges 13 | } from '@angular/core'; 14 | import { Subscription } from 'rxjs'; 15 | 16 | declare global { 17 | namespace JSX { 18 | interface IntrinsicElements { 19 | [key: string]: any; 20 | } 21 | } 22 | } 23 | 24 | export class ReactNgWrapper extends React.Component }> { 25 | private _childComponent: T & Partial; 26 | private _componentDef: ComponentDef; 27 | private _subscriptions: Subscription[] = []; 28 | 29 | constructor(props: Readonly, private componentFactory: componentType) { 30 | super(props); 31 | 32 | this._componentDef = componentFactory[NG_COMPONENT_DEF] || null; 33 | 34 | if (!this._componentDef) { 35 | throw new Error(`A component with a ${NG_COMPONENT_DEF} is required`); 36 | } 37 | 38 | this.state = { 39 | selector: this._componentDef.selectors[0][0] as string, 40 | propChanged: new Set() 41 | }; 42 | } 43 | 44 | componentWillUnmount() { 45 | this._subscriptions.forEach(subscription => subscription.unsubscribe()) 46 | } 47 | 48 | // After the component did mount, we set the state each second. 49 | componentDidMount() { 50 | // render component after selector is in DOM 51 | this._childComponent = renderComponent(this.componentFactory, { hostFeatures: [LifecycleHooksFeature] }); 52 | 53 | // listen to outputs 54 | this._subscriptions.push( 55 | ...Object.keys(this._componentDef.outputs).map( 56 | (output) => { 57 | return this._childComponent[output].subscribe((e) => { 58 | if (this.props[output] && typeof this.props[output] === "function") { 59 | this.props[output](e) 60 | } 61 | }) 62 | } 63 | ) 64 | ) 65 | 66 | // bind inputs 67 | this.updateComponent(); 68 | } 69 | 70 | componentDidUpdate() { 71 | this.updateComponent(); 72 | } 73 | 74 | updateComponent() { 75 | if (this._childComponent) { 76 | const changes: SimpleChanges = {} 77 | // update inputs and detect changes 78 | Object.keys(this.props).forEach(prop => { 79 | if (this._childComponent[prop] && 80 | Object.keys(this._componentDef.inputs).includes(prop) && 81 | this._childComponent[prop] !== this.props[prop]) { 82 | 83 | changes[prop] = new SimpleChange(this._childComponent[prop], this.props[prop], !this.state.propChanged.has(prop)) 84 | this.state.propChanged.add(prop); 85 | this._childComponent[prop] = this.props[prop] 86 | } 87 | }) 88 | 89 | if (typeof this._childComponent.ngOnChanges === "function") { 90 | this._childComponent.ngOnChanges(changes); 91 | } 92 | 93 | markDirty(this._childComponent); 94 | } 95 | } 96 | 97 | // render will know everything! 98 | render() { 99 | const CustomTag = `${this.state.selector}`; 100 | 101 | return ( 102 | 103 | ) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /libs/react-ng-wrapper/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "jsx": "react", 5 | "allowJs": false, 6 | "esModuleInterop": true, 7 | "allowSyntheticDefaultImports": true, 8 | "types": [] 9 | }, 10 | "include": ["**/*.ts", "**/*.tsx"] 11 | } 12 | -------------------------------------------------------------------------------- /libs/react-ng-wrapper/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "exclude": ["**/*.spec.ts", "**/*.spec.tsx"], 8 | "include": ["**/*.ts", "**/*.tsx"] 9 | } 10 | -------------------------------------------------------------------------------- /libs/react-ng-wrapper/tslint.json: -------------------------------------------------------------------------------- 1 | { "extends": "../../tslint.json", "rules": [] } 2 | -------------------------------------------------------------------------------- /libs/react-wrappers/README.md: -------------------------------------------------------------------------------- 1 | # react-wrappers 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Running unit tests 6 | 7 | Run `nx test react-wrappers` to execute the unit tests via [Jest](https://jestjs.io). 8 | -------------------------------------------------------------------------------- /libs/react-wrappers/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'react-wrappers', 3 | preset: '../../jest.config.js', 4 | transform: { 5 | '^.+\\.[tj]sx?$': 'ts-jest' 6 | }, 7 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'], 8 | coverageDirectory: '../../coverage/libs/react-wrappers' 9 | }; 10 | -------------------------------------------------------------------------------- /libs/react-wrappers/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/react-wrappers", 4 | "lib": { 5 | "entryFile": "src/index.ts" 6 | } 7 | 8 | } 9 | -------------------------------------------------------------------------------- /libs/react-wrappers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@hybrid/react-wrappers", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^8.2.5", 6 | "@angular/core": "^8.2.5", 7 | "@hybrid/react-ng-wrapper": "*" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /libs/react-wrappers/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/timer'; 2 | export * from './lib/hello'; 3 | -------------------------------------------------------------------------------- /libs/react-wrappers/src/lib/hello.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNgWrapper } from '@hybrid/react-ng-wrapper' 2 | import { HelloWorldComponent } from '@hybrid/angular-component-library'; 3 | 4 | export class ReactHelloComponent extends ReactNgWrapper { 5 | constructor(props){ 6 | super(props, HelloWorldComponent as any) 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /libs/react-wrappers/src/lib/timer.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNgWrapper } from '@hybrid/react-ng-wrapper' 2 | import { TimerComponent } from '@hybrid/angular-component-library'; 3 | 4 | export class ReactTimerComponent extends ReactNgWrapper { 5 | constructor(props) { 6 | super(props, TimerComponent as any) 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /libs/react-wrappers/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "jsx": "react", 5 | "allowJs": false, 6 | "esModuleInterop": true, 7 | "allowSyntheticDefaultImports": true, 8 | "types": ["node", "jest"] 9 | }, 10 | "include": ["**/*.ts", "**/*.tsx"] 11 | } 12 | -------------------------------------------------------------------------------- /libs/react-wrappers/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "exclude": ["**/*.spec.ts", "**/*.spec.tsx"], 8 | "include": ["**/*.ts", "**/*.tsx"] 9 | } 10 | -------------------------------------------------------------------------------- /libs/react-wrappers/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "**/*.spec.ts", 10 | "**/*.spec.tsx", 11 | "**/*.spec.js", 12 | "**/*.spec.jsx", 13 | "**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /libs/react-wrappers/tslint.json: -------------------------------------------------------------------------------- 1 | { "extends": "../../tslint.json", "rules": [] } 2 | -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmScope": "hybrid", 3 | "implicitDependencies": { 4 | "angular.json": "*", 5 | "package.json": "*", 6 | "tsconfig.json": "*", 7 | "tslint.json": "*", 8 | "nx.json": "*" 9 | }, 10 | "projects": { 11 | "react-app": { 12 | "tags": [] 13 | }, 14 | "angular-app": { 15 | "tags": [] 16 | }, 17 | "angular-ivy-app": { 18 | "tags": [] 19 | }, 20 | "react-ng-wrapper": { 21 | "tags": [] 22 | }, 23 | "react-wrappers": { 24 | "tags": [] 25 | }, 26 | "angular-component-library": { 27 | "tags": [] 28 | }, 29 | "angular-wrappers": { 30 | "tags": [] 31 | }, 32 | "react-component-library": { 33 | "tags": [] 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-react-hybrid", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "ng": "ng", 7 | "start": "ng serve", 8 | "start:react": "yarn build:all && ng serve react-app", 9 | "start:angular": "yarn build:all && ng serve angular-app", 10 | "build": "ng build", 11 | "build:reactWrapper": "ng build react-ng-wrapper && ng build angular-component-library && ng build react-wrappers", 12 | "build:angularWrapper": "ng build react-component-library && ng build angular-wrappers", 13 | "build:all": "yarn build:reactWrapper && yarn build:angularWrapper", 14 | "test": "ng test", 15 | "lint": "./node_modules/.bin/nx workspace-lint && ng lint", 16 | "e2e": "ng e2e", 17 | "affected:apps": "./node_modules/.bin/nx affected:apps", 18 | "affected:libs": "./node_modules/.bin/nx affected:libs", 19 | "affected:build": "./node_modules/.bin/nx affected:build", 20 | "affected:e2e": "./node_modules/.bin/nx affected:e2e", 21 | "affected:test": "./node_modules/.bin/nx affected:test", 22 | "affected:lint": "./node_modules/.bin/nx affected:lint", 23 | "affected:dep-graph": "./node_modules/.bin/nx affected:dep-graph", 24 | "affected": "./node_modules/.bin/nx affected", 25 | "format": "./node_modules/.bin/nx format:write", 26 | "format:write": "./node_modules/.bin/nx format:write", 27 | "format:check": "./node_modules/.bin/nx format:check", 28 | "update": "ng update @nrwl/workspace", 29 | "update:check": "ng update", 30 | "workspace-schematic": "./node_modules/.bin/nx workspace-schematic", 31 | "dep-graph": "./node_modules/.bin/nx dep-graph", 32 | "help": "./node_modules/.bin/nx help", 33 | "nx": "nx" 34 | }, 35 | "private": true, 36 | "dependencies": { 37 | "@angular/animations": "8.2.11", 38 | "@angular/common": "8.2.11", 39 | "@angular/compiler": "8.2.11", 40 | "@angular/core": "8.2.11", 41 | "@angular/forms": "8.2.11", 42 | "@angular/platform-browser": "8.2.11", 43 | "@angular/platform-browser-dynamic": "8.2.11", 44 | "@angular/router": "8.2.11", 45 | "@nrwl/angular": "8.6.0", 46 | "core-js": "2.6.9", 47 | "document-register-element": "1.13.1", 48 | "react": "16.9.0", 49 | "react-dom": "16.9.0", 50 | "rxjs": "6.5.3", 51 | "zone.js": "0.9.1" 52 | }, 53 | "devDependencies": { 54 | "@angular-devkit/build-angular": "0.803.12", 55 | "@angular-devkit/build-ng-packagr": "0.803.12", 56 | "@angular-devkit/core": "8.3.3", 57 | "@angular/cli": "8.3.12", 58 | "@angular/compiler-cli": "8.2.11", 59 | "@angular/language-service": "8.2.11", 60 | "@babel/preset-react": "7.0.0", 61 | "@nrwl/cypress": "8.6.0", 62 | "@nrwl/eslint-plugin-nx": "8.6.0", 63 | "@nrwl/jest": "8.6.0", 64 | "@nrwl/react": "8.6.0", 65 | "@nrwl/web": "8.6.0", 66 | "@nrwl/workspace": "8.6.0", 67 | "@testing-library/react": "8.0.5", 68 | "@types/jest": "24.0.9", 69 | "@types/jquery": "3.3.6", 70 | "@types/node": "8.9.5", 71 | "@types/react": "16.9.1", 72 | "@types/react-dom": "16.8.5", 73 | "@typescript-eslint/eslint-plugin": "2.0.0-alpha.4", 74 | "@typescript-eslint/parser": "2.0.0-alpha.4", 75 | "codelyzer": "4.5.0", 76 | "cypress": "3.4.0", 77 | "dotenv": "6.2.0", 78 | "eslint": "6.3.0", 79 | "eslint-config-prettier": "6.0.0", 80 | "eslint-plugin-import": "2.18.2", 81 | "eslint-plugin-jsx-a11y": "6.2.3", 82 | "eslint-plugin-react": "7.14.3", 83 | "eslint-plugin-react-hooks": "1.6.1", 84 | "jest": "24.1.0", 85 | "jest-preset-angular": "7.0.0", 86 | "ng-packagr": "5.5.0", 87 | "prettier": "1.15.2", 88 | "ts-jest": "24.0.0", 89 | "ts-node": "7.0.1", 90 | "tsickle": "0.37.0", 91 | "tslib": "1.10.0", 92 | "tslint": "5.11.0", 93 | "typescript": "3.5.3" 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base", 4 | "group:all", 5 | ":automergeMinor", 6 | ":maintainLockFilesMonthly" 7 | ], 8 | "lockFileMaintenance": { 9 | "extends": [ 10 | "group:all" 11 | ], 12 | "commitMessageAction": "Update" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tools/schematics/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RGunning/Angular-React-hybrid/51034938cc44bbd2dbe0e9356d8833611cea3aef/tools/schematics/.gitkeep -------------------------------------------------------------------------------- /tools/tsconfig.tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc", 5 | "rootDir": ".", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": ["node"] 9 | }, 10 | "include": ["**/*.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "sourceMap": true, 5 | "declaration": false, 6 | "moduleResolution": "node", 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "importHelpers": true, 10 | "target": "es2015", 11 | "module": "es2015", 12 | "typeRoots": ["node_modules/@types"], 13 | "lib": ["es2017", "dom"], 14 | "skipLibCheck": true, 15 | "skipDefaultLibCheck": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "@hybrid/react-ng-wrapper": ["dist/libs/react-ng-wrapper"], 19 | "@hybrid/react-wrappers": ["dist/libs/react-wrappers"], 20 | "@hybrid/angular-wrappers": ["dist/libs/angular-wrappers"], 21 | "@hybrid/angular-component-library": [ 22 | "dist/libs/angular-component-library/" 23 | ], 24 | "@hybrid/react-component-library": [ 25 | "dist/libs/react-component-library/" 26 | ] 27 | }, 28 | "rootDir": "." 29 | }, 30 | "angularCompilerOptions": { 31 | "enableIvy": true 32 | }, 33 | "exclude": ["node_modules", "tmp"] 34 | } 35 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/@nrwl/workspace/src/tslint", 4 | "node_modules/codelyzer" 5 | ], 6 | "rules": { 7 | "arrow-return-shorthand": true, 8 | "callable-types": true, 9 | "class-name": true, 10 | "deprecation": { 11 | "severity": "warn" 12 | }, 13 | "forin": true, 14 | "import-blacklist": [true, "rxjs/Rx"], 15 | "interface-over-type-literal": true, 16 | "member-access": false, 17 | "member-ordering": [ 18 | true, 19 | { 20 | "order": [ 21 | "static-field", 22 | "instance-field", 23 | "static-method", 24 | "instance-method" 25 | ] 26 | } 27 | ], 28 | "no-arg": true, 29 | "no-bitwise": true, 30 | "no-console": [true, "debug", "info", "time", "timeEnd", "trace"], 31 | "no-construct": true, 32 | "no-debugger": true, 33 | "no-duplicate-super": true, 34 | "no-empty": false, 35 | "no-empty-interface": true, 36 | "no-eval": true, 37 | "no-inferrable-types": [true, "ignore-params"], 38 | "no-misused-new": true, 39 | "no-non-null-assertion": true, 40 | "no-shadowed-variable": true, 41 | "no-string-literal": false, 42 | "no-string-throw": true, 43 | "no-switch-case-fall-through": true, 44 | "no-unnecessary-initializer": true, 45 | "no-unused-expression": true, 46 | "no-use-before-declare": true, 47 | "no-var-keyword": true, 48 | "object-literal-sort-keys": false, 49 | "prefer-const": true, 50 | "radix": true, 51 | "triple-equals": [true, "allow-null-check"], 52 | "unified-signatures": true, 53 | "variable-name": false, 54 | "nx-enforce-module-boundaries": [ 55 | true, 56 | { 57 | "allow": [], 58 | "depConstraints": [ 59 | { 60 | "sourceTag": "*", 61 | "onlyDependOnLibsWithTags": ["*"] 62 | } 63 | ] 64 | } 65 | ], 66 | "directive-selector": [true, "attribute", "app", "camelCase"], 67 | "component-selector": [true, "element", "app", "kebab-case"], 68 | "no-output-on-prefix": true, 69 | "use-input-property-decorator": true, 70 | "use-output-property-decorator": true, 71 | "use-host-property-decorator": true, 72 | "no-input-rename": true, 73 | "no-output-rename": true, 74 | "use-life-cycle-interface": true, 75 | "use-pipe-transform-interface": true, 76 | "component-class-suffix": true, 77 | "directive-class-suffix": true 78 | } 79 | } 80 | --------------------------------------------------------------------------------