hermes-io 1.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/. quokka +25 -0
- package/.editorconfig +32 -0
- package/.eslintrc.js +24 -0
- package/README.md +112 -0
- package/context.js +74 -0
- package/examples/sneaker-store/. quokka +25 -0
- package/examples/sneaker-store/.editorconfig +32 -0
- package/examples/sneaker-store/.eslintrc.js +24 -0
- package/examples/sneaker-store/LICENSE +21 -0
- package/examples/sneaker-store/README.md +1 -0
- package/examples/sneaker-store/config-overrides.js +35 -0
- package/examples/sneaker-store/jsconfig.json +20 -0
- package/examples/sneaker-store/package-lock.json +39849 -0
- package/examples/sneaker-store/package.json +48 -0
- package/examples/sneaker-store/public/assets/images/addidas.webp +0 -0
- package/examples/sneaker-store/public/assets/images/jordan_3.webp +0 -0
- package/examples/sneaker-store/public/favicon.ico +0 -0
- package/examples/sneaker-store/public/index.html +46 -0
- package/examples/sneaker-store/public/logo192.png +0 -0
- package/examples/sneaker-store/public/logo512.png +0 -0
- package/examples/sneaker-store/public/manifest.json +25 -0
- package/examples/sneaker-store/public/reset.css +48 -0
- package/examples/sneaker-store/public/robots.txt +3 -0
- package/examples/sneaker-store/src/core/App.js +73 -0
- package/examples/sneaker-store/src/core/actions/Theme.js +5 -0
- package/examples/sneaker-store/src/core/actions/index.js +3 -0
- package/examples/sneaker-store/src/core/constants.js +4 -0
- package/examples/sneaker-store/src/core/contexts.js +4 -0
- package/examples/sneaker-store/src/core/factory/Actions.js +8 -0
- package/examples/sneaker-store/src/core/factory/Observer.js +3 -0
- package/examples/sneaker-store/src/core/observers/products.js +6 -0
- package/examples/sneaker-store/src/core/theme.js +26 -0
- package/examples/sneaker-store/src/core/views/components/Products/Products.js +56 -0
- package/examples/sneaker-store/src/core/views/components/Products/Styles.js +112 -0
- package/examples/sneaker-store/src/core/views/components/ShoppingCar/ShoppingCar.js +56 -0
- package/examples/sneaker-store/src/core/views/components/ShoppingCar/Styles.js +59 -0
- package/examples/sneaker-store/src/core/views/hooks/index.js +0 -0
- package/examples/sneaker-store/src/index.js +10 -0
- package/hooks/useObserver.js +7 -6
- package/index.js +1 -0
- package/main.js +3 -1
- package/package.json +6 -3
package/. quokka
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"babel": {
|
|
3
|
+
"presets": [
|
|
4
|
+
"react-app"
|
|
5
|
+
]
|
|
6
|
+
},
|
|
7
|
+
"plugins": [
|
|
8
|
+
"alias-quokka-plugin",
|
|
9
|
+
"jsdom-quokka-plugin"
|
|
10
|
+
],
|
|
11
|
+
"alias": {
|
|
12
|
+
"@core": "./src/core",
|
|
13
|
+
"@components": "./src/core/components",
|
|
14
|
+
"@contexts": "./src/core/contexts",
|
|
15
|
+
"@factory": "./src/core/factory",
|
|
16
|
+
"@hooks": "./src/core/hooks",
|
|
17
|
+
"@utils": "./src/core/utils",
|
|
18
|
+
"@libs": "./src/libs",
|
|
19
|
+
"@constants": "./src/core/constants",
|
|
20
|
+
"@translations": "./src/core/translations",
|
|
21
|
+
"@theme": "./src/core/theme",
|
|
22
|
+
"@routes": "./src/core/routes"
|
|
23
|
+
},
|
|
24
|
+
"node": "~/.nvm/versions/node/v16.18.1/bin/node"
|
|
25
|
+
}
|
package/.editorconfig
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# EditorConfig is awesome: https://EditorConfig.org
|
|
2
|
+
|
|
3
|
+
# top-most EditorConfig file
|
|
4
|
+
root = true
|
|
5
|
+
|
|
6
|
+
# Unix-style newlines with a newline ending every file
|
|
7
|
+
[*]
|
|
8
|
+
end_of_line = lf
|
|
9
|
+
insert_final_newline = true
|
|
10
|
+
|
|
11
|
+
# Matches multiple files with brace expansion notation
|
|
12
|
+
# Set default charset
|
|
13
|
+
[*.{js,py}]
|
|
14
|
+
charset = utf-8
|
|
15
|
+
|
|
16
|
+
# 4 space indentation
|
|
17
|
+
[*.py]
|
|
18
|
+
indent_style = space
|
|
19
|
+
indent_size = 4
|
|
20
|
+
|
|
21
|
+
# Tab indentation (no size specified)
|
|
22
|
+
[Makefile]
|
|
23
|
+
indent_style = tab
|
|
24
|
+
|
|
25
|
+
# Indentation override for all JS under lib directory
|
|
26
|
+
[*.js]
|
|
27
|
+
indent_style = space
|
|
28
|
+
indent_size = 2
|
|
29
|
+
|
|
30
|
+
[{package.json,.travis.yml}]
|
|
31
|
+
indent_style = space
|
|
32
|
+
indent_size = 2
|
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
"env": {
|
|
3
|
+
"browser": true,
|
|
4
|
+
"es2021": true
|
|
5
|
+
},
|
|
6
|
+
"extends": [
|
|
7
|
+
"eslint:recommended",
|
|
8
|
+
"plugin:react/recommended"
|
|
9
|
+
],
|
|
10
|
+
"overrides": [
|
|
11
|
+
],
|
|
12
|
+
"parserOptions": {
|
|
13
|
+
"ecmaVersion": "latest",
|
|
14
|
+
"sourceType": "module"
|
|
15
|
+
},
|
|
16
|
+
"plugins": [
|
|
17
|
+
"react"
|
|
18
|
+
],
|
|
19
|
+
"rules": {
|
|
20
|
+
"react/prop-types": "off",
|
|
21
|
+
"no-unused-vars": 0,
|
|
22
|
+
"react/display-name": 0
|
|
23
|
+
}
|
|
24
|
+
}
|
package/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# hermes-io
|
|
2
|
+
A lightweight javascript library that allows communication between Reactjs components by using the observer pattern and the hook api.
|
|
3
|
+
|
|
4
|
+
# Installation
|
|
5
|
+
```
|
|
6
|
+
npm i hermes-io --save
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
# Get started
|
|
10
|
+
In order to use `hermes-io` you need to create a react project by using something like [Create-react-app](https://create-react-app.dev/), hermes-io is Reactjs hook that communication between components,
|
|
11
|
+
let's see it in action, follow the next example:
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
// observers.js
|
|
15
|
+
export const AddProductObserver = new Observer();
|
|
16
|
+
export const RemoveProductObserver = new Observer();
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
// App.js
|
|
20
|
+
import { useState } from 'react';
|
|
21
|
+
import { useObserver, Observer } from 'hermes-io';
|
|
22
|
+
import { RemoveProductObserver, AddProductObserver } from './observers';
|
|
23
|
+
import { Products } from './components/Products';
|
|
24
|
+
import { ShoppingCar } from './components/ShoppingCar';
|
|
25
|
+
|
|
26
|
+
export const App = (props = {}) => {
|
|
27
|
+
const [productsToBy, setProductsToBy] = useState([]);
|
|
28
|
+
const productsStore = useProductStore(); // get products from some store
|
|
29
|
+
const products = productsStore.get();
|
|
30
|
+
|
|
31
|
+
const handleRemoveProduct = (product = {}) => {
|
|
32
|
+
const newProducts = [...productsToBy].filter(({ id = '' }) => id !== product.id);
|
|
33
|
+
setProductsToBy(newProducts);
|
|
34
|
+
productsStore.remove(product);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const handleAddProduct = (product = {}) => {
|
|
38
|
+
setProductsToBy([...productsToBy, product]);
|
|
39
|
+
productsStore.update(product, { selected: true });
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
useObserver({
|
|
43
|
+
observer: AddProductObserver,
|
|
44
|
+
listener: handleAddProduct,
|
|
45
|
+
from: ['products-list'],
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
useObserver({
|
|
49
|
+
observer: RemoveProductObserver,
|
|
50
|
+
listener: handleRemoveProduct,
|
|
51
|
+
from: ['shopping-car'],
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return <div>
|
|
55
|
+
<Products data={products} />
|
|
56
|
+
<ShoppingCar data={productsToBy}/>
|
|
57
|
+
</div>
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
// ShoppingCar.js
|
|
62
|
+
import { RemoveProductObserver } from '../observers';
|
|
63
|
+
|
|
64
|
+
export const ShoppingCar = (props = {}) => {
|
|
65
|
+
const handleRemoveProduct = (product = {}) => {
|
|
66
|
+
RemoveProductObserver.notify({ value: product, from 'shopping-car' });
|
|
67
|
+
};
|
|
68
|
+
return <div>
|
|
69
|
+
<ul>
|
|
70
|
+
{
|
|
71
|
+
data.map((product = {}) =>
|
|
72
|
+
<li key={product.id}>
|
|
73
|
+
<span>{product.name}</<span>
|
|
74
|
+
<p>{product.description}</p>
|
|
75
|
+
<small>${product.price}</<small>
|
|
76
|
+
<button onClick={() => handleRemoveProduct(product)}>Remove</<button>
|
|
77
|
+
</li>
|
|
78
|
+
))
|
|
79
|
+
}
|
|
80
|
+
</ul>
|
|
81
|
+
</div>
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// Products.js
|
|
85
|
+
import { AddProductObserver } from '../observers';
|
|
86
|
+
|
|
87
|
+
export const Products = (props = {}) => {
|
|
88
|
+
const { data = [] } = props;
|
|
89
|
+
|
|
90
|
+
const handleAddProduct = (product = {}) => {
|
|
91
|
+
AddProductObserver.notify({ value: product, from 'products-list' });
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
return <ul>
|
|
95
|
+
{
|
|
96
|
+
data.map((product = {}) =>
|
|
97
|
+
<li key={product.id}>
|
|
98
|
+
<span>{product.name}</<span>
|
|
99
|
+
<p>{product.description}</p>
|
|
100
|
+
<small>${product.price}</<small>
|
|
101
|
+
<button disabled={product.selected} onClick={() => handleAddProduct(product)}>Add to car</<button>
|
|
102
|
+
</li>
|
|
103
|
+
))
|
|
104
|
+
}
|
|
105
|
+
</ul>
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
|
package/context.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
let recording = false;
|
|
2
|
+
let collection = [];
|
|
3
|
+
|
|
4
|
+
const handleMessageFromDevtools = (event) => {
|
|
5
|
+
const { source, payload } = event.data;
|
|
6
|
+
if (source === "hermes-io-devtools") {
|
|
7
|
+
if (payload === "START_RECORDING") {
|
|
8
|
+
recording = true;
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (payload === "STOP_RECORDING") {
|
|
12
|
+
recording = false;
|
|
13
|
+
}
|
|
14
|
+
if (payload === "RESET_RECORDING") {
|
|
15
|
+
collection = [];
|
|
16
|
+
recording = false;
|
|
17
|
+
}
|
|
18
|
+
if (payload?.type === "SET_CONTEXT") {
|
|
19
|
+
const context = collection.find((context) => context._internalId === payload.id);
|
|
20
|
+
if (context) {
|
|
21
|
+
context.listener(context.value);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
window.addEventListener("message", handleMessageFromDevtools);
|
|
28
|
+
|
|
29
|
+
export class Context {
|
|
30
|
+
id = null;
|
|
31
|
+
_internalId = null;
|
|
32
|
+
date = null;
|
|
33
|
+
value = null;
|
|
34
|
+
listener = null;
|
|
35
|
+
stackTrace = null;
|
|
36
|
+
constructor(description) {
|
|
37
|
+
this.id = Symbol(description);
|
|
38
|
+
}
|
|
39
|
+
update = ({ value, listener }) => {
|
|
40
|
+
this.date = new Date();
|
|
41
|
+
this.value = value;
|
|
42
|
+
this.stackTrace = this.getStackTrace();
|
|
43
|
+
this.listener = listener;
|
|
44
|
+
if (recording) {
|
|
45
|
+
this.sendSnapshot();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
sendSnapshot = () => {
|
|
49
|
+
const snapshot = this.takeSnapshot();
|
|
50
|
+
const { listener, stackTrace, value, date, _internalId } = snapshot;
|
|
51
|
+
collection.push(snapshot);
|
|
52
|
+
window.postMessage(
|
|
53
|
+
{
|
|
54
|
+
type: "CONTEXT_SNAPSHOT",
|
|
55
|
+
payload: { value: JSON.stringify(value.value), listener: listener.name, stackTrace, date, id: _internalId },
|
|
56
|
+
source: "hermes-io",
|
|
57
|
+
},
|
|
58
|
+
"*"
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
takeSnapshot = () => {
|
|
62
|
+
return {
|
|
63
|
+
_internalId: crypto.randomUUID(),
|
|
64
|
+
value: this.value,
|
|
65
|
+
date: this.date,
|
|
66
|
+
listener: this.listener,
|
|
67
|
+
stackTrace: this.stackTrace,
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
getStackTrace = () => {
|
|
71
|
+
const err = new Error();
|
|
72
|
+
return err.stack;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"babel": {
|
|
3
|
+
"presets": [
|
|
4
|
+
"react-app"
|
|
5
|
+
]
|
|
6
|
+
},
|
|
7
|
+
"plugins": [
|
|
8
|
+
"alias-quokka-plugin",
|
|
9
|
+
"jsdom-quokka-plugin"
|
|
10
|
+
],
|
|
11
|
+
"alias": {
|
|
12
|
+
"@core": "./src/core",
|
|
13
|
+
"@components": "./src/core/components",
|
|
14
|
+
"@contexts": "./src/core/contexts",
|
|
15
|
+
"@factory": "./src/core/factory",
|
|
16
|
+
"@hooks": "./src/core/hooks",
|
|
17
|
+
"@utils": "./src/core/utils",
|
|
18
|
+
"@libs": "./src/libs",
|
|
19
|
+
"@constants": "./src/core/constants",
|
|
20
|
+
"@translations": "./src/core/translations",
|
|
21
|
+
"@theme": "./src/core/theme",
|
|
22
|
+
"@routes": "./src/core/routes"
|
|
23
|
+
},
|
|
24
|
+
"node": "~/.nvm/versions/node/v16.18.1/bin/node"
|
|
25
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# EditorConfig is awesome: https://EditorConfig.org
|
|
2
|
+
|
|
3
|
+
# top-most EditorConfig file
|
|
4
|
+
root = true
|
|
5
|
+
|
|
6
|
+
# Unix-style newlines with a newline ending every file
|
|
7
|
+
[*]
|
|
8
|
+
end_of_line = lf
|
|
9
|
+
insert_final_newline = true
|
|
10
|
+
|
|
11
|
+
# Matches multiple files with brace expansion notation
|
|
12
|
+
# Set default charset
|
|
13
|
+
[*.{js,py}]
|
|
14
|
+
charset = utf-8
|
|
15
|
+
|
|
16
|
+
# 4 space indentation
|
|
17
|
+
[*.py]
|
|
18
|
+
indent_style = space
|
|
19
|
+
indent_size = 4
|
|
20
|
+
|
|
21
|
+
# Tab indentation (no size specified)
|
|
22
|
+
[Makefile]
|
|
23
|
+
indent_style = tab
|
|
24
|
+
|
|
25
|
+
# Indentation override for all JS under lib directory
|
|
26
|
+
[*.js]
|
|
27
|
+
indent_style = space
|
|
28
|
+
indent_size = 2
|
|
29
|
+
|
|
30
|
+
[{package.json,.travis.yml}]
|
|
31
|
+
indent_style = space
|
|
32
|
+
indent_size = 2
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
"env": {
|
|
3
|
+
"browser": true,
|
|
4
|
+
"es2021": true
|
|
5
|
+
},
|
|
6
|
+
"extends": [
|
|
7
|
+
"eslint:recommended",
|
|
8
|
+
"plugin:react/recommended"
|
|
9
|
+
],
|
|
10
|
+
"overrides": [
|
|
11
|
+
],
|
|
12
|
+
"parserOptions": {
|
|
13
|
+
"ecmaVersion": "latest",
|
|
14
|
+
"sourceType": "module"
|
|
15
|
+
},
|
|
16
|
+
"plugins": [
|
|
17
|
+
"react"
|
|
18
|
+
],
|
|
19
|
+
"rules": {
|
|
20
|
+
"react/prop-types": "off",
|
|
21
|
+
"no-unused-vars": 0,
|
|
22
|
+
"react/display-name": 0
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Esneyder Amin
|
|
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.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# atomic-client
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
webpack: function (config) {
|
|
5
|
+
config.devtool = "source-map";
|
|
6
|
+
config.resolve = {
|
|
7
|
+
extensions: [".js", ".html"],
|
|
8
|
+
alias: {
|
|
9
|
+
"@actions": path.resolve(__dirname, "src/core/actions"),
|
|
10
|
+
"@core": path.resolve(__dirname, "src/core"),
|
|
11
|
+
"@views": path.resolve(__dirname, "src/core/views"),
|
|
12
|
+
"@components": path.resolve(__dirname, "src/core/views/components"),
|
|
13
|
+
"@factory": path.resolve(__dirname, "src/core/factory"),
|
|
14
|
+
"@hooks": path.resolve(__dirname, "src/core/views/hooks"),
|
|
15
|
+
"@constants": path.resolve(__dirname, "src/core/constants"),
|
|
16
|
+
"@contexts": path.resolve(__dirname, "src/core/contexts"),
|
|
17
|
+
"@observers": path.resolve(__dirname, "src/core/observers"),
|
|
18
|
+
"@theme": path.resolve(__dirname, "src/core/theme"),
|
|
19
|
+
"@src": path.resolve(__dirname, "src"),
|
|
20
|
+
"hermes-io": path.resolve(__dirname, "../../"),
|
|
21
|
+
"react": path.resolve(__dirname, "../../node_modules/react"),
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
config.module.rules.push({
|
|
25
|
+
test: /\.js$/,
|
|
26
|
+
loader: "esbuild-loader",
|
|
27
|
+
options: {
|
|
28
|
+
loader: "jsx",
|
|
29
|
+
target: "es2020",
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
console.log(JSON.stringify(config));
|
|
33
|
+
return config;
|
|
34
|
+
},
|
|
35
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"baseUrl": ".",
|
|
4
|
+
"paths": {
|
|
5
|
+
"actions/*": ["src/core/actions/*"],
|
|
6
|
+
"@core/*": ["src/core/*"],
|
|
7
|
+
"@views/*": ["src/core/views/*"],
|
|
8
|
+
"@components/*": ["src/core/views/components/*"],
|
|
9
|
+
"@factory/*": ["src/core/factory/*"],
|
|
10
|
+
"@hooks/*": ["src/core/views/hooks/*"],
|
|
11
|
+
"@constants": ["src/core/constants"],
|
|
12
|
+
"@observers/*": ["src/core/observers/*"],
|
|
13
|
+
"@contexts/*": ["src/core/contexts"],
|
|
14
|
+
"@src/*": ["src/*"],
|
|
15
|
+
"@hermes-io/*": ["../../*"],
|
|
16
|
+
"react": ["../../node_modules/react"]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"exclude": ["node_modules"]
|
|
20
|
+
}
|