Skip to content

Commit

Permalink
Web component working locally
Browse files Browse the repository at this point in the history
  • Loading branch information
ArayB committed May 9, 2022
1 parent a4eb0a5 commit 072c36c
Show file tree
Hide file tree
Showing 8 changed files with 324 additions and 22 deletions.
3 changes: 1 addition & 2 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
"react-app",
]
}
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@babel/core": "^7.17.10",
"@codemirror/lang-html": "^0.19.3",
"@codemirror/lang-javascript": "^0.19.2",
"@codemirror/lang-python": "^0.19.2",
Expand All @@ -18,7 +19,7 @@
"axios": "^0.24.0",
"babel-eslint": "^10.1.0",
"babel-jest": "^26.6.0",
"babel-loader": "8.1.0",
"babel-loader": "^8.2.5",
"babel-plugin-named-asset-import": "^0.3.7",
"babel-preset-react-app": "^10.0.1",
"bfj": "^7.0.2",
Expand Down Expand Up @@ -80,6 +81,7 @@
"sass-loader": "^10.0.5",
"semver": "7.3.2",
"skulpt": "^1.2.0",
"style-it": "^2.1.4",
"style-loader": "1.3.0",
"terser-webpack-plugin": "4.2.3",
"three": "^0.137.5",
Expand All @@ -95,7 +97,8 @@
"scripts": {
"start": "node scripts/start.js",
"build": "node scripts/build.js",
"test": "node scripts/test.js --transformIgnorePatterns 'node_modules/(?!three)/'"
"test": "node scripts/test.js --transformIgnorePatterns 'node_modules/(?!three)/'",
"start:wc": "NODE_ENV=development webpack serve -c ./webpack.component.config.js --mode development"
},
"eslintConfig": {
"extends": [
Expand All @@ -116,13 +119,15 @@
]
},
"devDependencies": {
"@babel/preset-env": "^7.17.10",
"@codemirror/basic-setup": "^0.19.0",
"@codemirror/commands": "^0.19.5",
"@codemirror/highlight": "^0.19.6",
"@codemirror/lang-css": "^0.19.3",
"jest-junit": "^13.0.0",
"react-test-renderer": "^17.0.2",
"sass": "^1.49.11"
"sass": "^1.49.11",
"webpack-cli": "^4.9.2"
},
"jest": {
"roots": [
Expand Down
25 changes: 25 additions & 0 deletions public/web-component/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>Editor Web component</title>
</head>
<body>
<editor-wc title="a web component!"></editor-wc>
<script src="./bundle.js"></script>
</body>

<script>
document.addEventListener('DOMContentLoaded', (e) => {
const webComp = document.querySelector('editor-wc');

webComp.menuItems = ['one', 'two']

// subscribe to the 'custom' event which is pushed by the Foo component in a click handler
webComp.addEventListener('custom', function(e) {
console.log('listener in index html');
});
});
</script>
</html>
5 changes: 5 additions & 0 deletions src/components/Foo/Foo.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.foo {
color: red;
cursor: pointer;
font-weight: 900;
}
37 changes: 37 additions & 0 deletions src/components/Foo/Foo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import Style from 'style-it';
import styles from './Foo.css';

const Foo = (props) => {
console.log(props)
const { title } = props;

const clickHandler = () => {

const customEvent = new CustomEvent("custom", {
bubbles: true,
cancelable: false,
composed: true
});

// This seems to be easiest way of firing an event on the web component
const foo = document.querySelector('editor-wc')
console.log('click event in react component')
foo.dispatchEvent(customEvent)
}

return (
<Style>
{styles.toString()}
<div className="App">
<header className="App-header">
<p className='foo'>
<span onClick={clickHandler}>Wow {title}!</span>
</p>
</header>
</div>
</Style>
);
}

export default Foo
63 changes: 63 additions & 0 deletions src/web-component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React from 'react';
import ReactDOM from 'react-dom';
import * as ReactDOMClient from 'react-dom/client';
import Foo from './components/Foo/Foo.js';

class WebComponent extends HTMLElement {
mountPoint;
componentAttributes = {};
componentProperties = {};

connectedCallback() {
console.log('connected')
this.mountReactApp();
}

disconnectedCallback() {
ReactDOM.unmountComponentAtNode(this.mountPoint);
}

static get observedAttributes() {
return ['title'];
}

attributeChangedCallback(name, oldVal, newVal) {
console.log('attr changed')
console.log(name, newVal)
this.componentAttributes[name] = newVal;

// this.mountReactApp();
}

get menuItems() {
// console.log('get menuitems')
return this.componentProperties.menuItems;
}

set menuItems(newValue) {
console.log('menu items set')
this.componentProperties.menuItems = newValue;

this.mountReactApp();
}

reactProps() {
return { ...this.componentAttributes, ...this.componentProperties };
}

mountReactApp() {
// console.log('mount')
let root;
if (!this.mountPoint) {
console.log('no mountpoint')
this.mountPoint = document.createElement('div');
this.mountPoint.setAttribute("id", "root");
this.attachShadow({ mode: 'open' }).appendChild(this.mountPoint);
root = ReactDOMClient.createRoot(this.mountPoint);

root.render(<Foo { ...this.reactProps() }/>);
}
}
}

window.customElements.define('editor-wc', WebComponent);
31 changes: 31 additions & 0 deletions webpack.component.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const path = require('path');

module.exports = {
entry: path.resolve(__dirname, './src/web-component.js'),
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader']
},
{
test: /\.css$/,
use: [
'css-loader',
]
}
]
},
resolve: {
extensions: ['*', '.js', '.jsx', '.css']
},
output: {
path: path.resolve(__dirname, './public'),
filename: 'bundle.js',
},
devServer: {
contentBase: path.resolve(__dirname, './public/web-component'),
port: 9000
},
};
Loading

0 comments on commit 072c36c

Please sign in to comment.