~repos /atoms-element
git clone https://pyrossh.dev/repos/atoms-element.git
A simple web component library for defining your custom elements. It works on both client and server.
93854007
—
Peter John 4 years ago
fix tests
- example/styles.css +0 -2
- page.test.js +6 -7
- readme.md +83 -20
example/styles.css
CHANGED
|
@@ -557,8 +557,6 @@ body {
|
|
|
557
557
|
min-width: 320px;
|
|
558
558
|
margin: 0px;
|
|
559
559
|
min-height: 100vh;
|
|
560
|
-
/* font-size: 1rem; */
|
|
561
|
-
/* line-height: 1.5rem; */
|
|
562
560
|
line-height: 1.4;
|
|
563
561
|
font-weight: 400;
|
|
564
562
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
page.test.js
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import { expect, test } from '@jest/globals';
|
|
2
2
|
import { html, css } from './element.js';
|
|
3
|
-
import createPage from './page.js';
|
|
3
|
+
import { createPage } from './page.js';
|
|
4
4
|
|
|
5
5
|
test('Page', () => {
|
|
6
6
|
const route = () => {
|
|
7
7
|
const langPart = this.config.lang === 'en' ? '' : `/${this.config.lang}`;
|
|
8
8
|
return `${langPart}`;
|
|
9
9
|
};
|
|
10
|
-
const styles = (
|
|
10
|
+
const styles = css({
|
|
11
|
-
css({
|
|
12
|
-
|
|
11
|
+
div: {
|
|
13
|
-
|
|
12
|
+
color: 'red',
|
|
14
|
-
|
|
13
|
+
},
|
|
15
|
-
|
|
14
|
+
});
|
|
16
15
|
const head = ({ config }) => {
|
|
17
16
|
return html`
|
|
18
17
|
<title>${config.title}</title>
|
readme.md
CHANGED
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|

|
|
5
5
|
|
|
6
6
|
A simple web component library for defining your custom elements. It works on both client and server. It supports hooks and follows the same
|
|
7
|
-
principles of react. Data props are attributes on the custom element by default so its easier to debug and functions/handlers are
|
|
7
|
+
principles of react. Data props are attributes on the custom element by default so its easier to debug and functions/handlers are attached to the element.
|
|
8
|
-
methods attached to the element.
|
|
9
8
|
|
|
10
9
|
I initially started researching if it was possible to server render web components but found out not one framework supported it. I liked using
|
|
11
10
|
[haunted](https://github.com/matthewp/haunted) as it was react like with hooks but was lost on how to implement server rendering. Libraries like
|
|
@@ -23,7 +22,7 @@ After going through all these libraries,
|
|
|
23
22
|
5. [Atomico](https://github.com/atomicojs/atomico)
|
|
24
23
|
6. [fuco](https://github.com/wtnbass/fuco)
|
|
25
24
|
|
|
26
|
-
And figuring out how each one implemented their on custom elements I came up with atoms-element. It still doesn't have proper rehydration lit-html just replaces the DOM under the web component for now. Atomico has implemented proper SSR with hydration so I might need to look into that in the future or
|
|
25
|
+
And figuring out how each one implemented their on custom elements I came up with atoms-element. It still doesn't have proper rehydration lit-html just replaces the DOM under the server rendered web component for now. Atomico has implemented proper SSR with hydration so I might need to look into that in the future or
|
|
27
26
|
use it instead of lit-html. Since I made a few modifications like json attributes and attrTypes I don't know if it will easy.
|
|
28
27
|
|
|
29
28
|
## Installation
|
|
@@ -35,38 +34,102 @@ npm i atoms-element
|
|
|
35
34
|
## Example
|
|
36
35
|
|
|
37
36
|
```js
|
|
38
|
-
import {
|
|
37
|
+
import { createElement, html, css, object, number, string } from 'atoms-element/element.js';
|
|
39
|
-
import { ssr } from 'atoms-element/
|
|
38
|
+
import { ssr } from 'atoms-element/page.js';
|
|
40
39
|
|
|
40
|
+
const name = () => 'app-counter';
|
|
41
|
+
|
|
41
|
-
const attrTypes = {
|
|
42
|
+
const attrTypes = () => ({
|
|
42
|
-
name: string.
|
|
43
|
+
name: string().required(),
|
|
43
44
|
meta: object({
|
|
44
|
-
start: number,
|
|
45
|
+
start: number(),
|
|
45
46
|
}),
|
|
46
|
-
};
|
|
47
|
+
});
|
|
48
|
+
|
|
47
|
-
|
|
49
|
+
const stateTypes = () => ({
|
|
50
|
+
count: number()
|
|
51
|
+
.required()
|
|
52
|
+
.default((attrs) => attrs.meta?.start || 0),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const computedTypes = () => ({
|
|
56
|
+
sum: number()
|
|
57
|
+
.required()
|
|
58
|
+
.compute('count', (count) => {
|
|
59
|
+
return count + 10;
|
|
60
|
+
}),
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const styles = css({
|
|
64
|
+
title: {
|
|
65
|
+
fontSize: '20px',
|
|
66
|
+
marginBottom: '0.5rem',
|
|
67
|
+
textAlign: 'center',
|
|
68
|
+
},
|
|
69
|
+
span: {
|
|
70
|
+
fontSize: '16px',
|
|
71
|
+
},
|
|
72
|
+
container: {
|
|
73
|
+
display: 'flex',
|
|
74
|
+
flex: 1,
|
|
75
|
+
flexDirection: 'row',
|
|
76
|
+
fontSize: '32px',
|
|
77
|
+
color: 'rgba(55, 65, 81, 1)',
|
|
78
|
+
},
|
|
79
|
+
mx: {
|
|
80
|
+
marginLeft: '5rem',
|
|
81
|
+
marginRight: '5rem',
|
|
82
|
+
fontSize: '30px',
|
|
83
|
+
fontFamily: `ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace`,
|
|
84
|
+
},
|
|
85
|
+
button: {
|
|
86
|
+
paddingTop: '0.5rem',
|
|
87
|
+
paddingBottom: '0.5rem',
|
|
88
|
+
paddingLeft: '1rem',
|
|
89
|
+
paddingRight: '1rem',
|
|
90
|
+
color: 'rgba(55, 65, 81, 1)',
|
|
91
|
+
borderRadius: '0.25rem',
|
|
92
|
+
backgroundColor: 'rgba(209, 213, 219, 1)',
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
48
|
-
const
|
|
96
|
+
const render = ({ attrs, state, computed }) => {
|
|
97
|
+
const { name, meta } = attrs;
|
|
49
|
-
const
|
|
98
|
+
const { count, setCount } = state;
|
|
99
|
+
const { sum } = computed;
|
|
50
100
|
|
|
51
101
|
return html`
|
|
52
102
|
<div>
|
|
103
|
+
<div class=${styles.title}>
|
|
104
|
+
Counter: ${name}
|
|
53
|
-
|
|
105
|
+
<span class=${styles.span}>starts at ${meta?.start}</span>
|
|
106
|
+
</div>
|
|
54
|
-
<div class=
|
|
107
|
+
<div class=${styles.container}>
|
|
55
|
-
<button @click=${() => setCount((v) => v - 1)}>-</button>
|
|
108
|
+
<button class=${styles.button} @click=${() => setCount((v) => v - 1)}>-</button>
|
|
56
|
-
<div class=
|
|
109
|
+
<div class=${styles.mx}>
|
|
57
|
-
<h1
|
|
110
|
+
<h1>${count}</h1>
|
|
58
111
|
</div>
|
|
59
|
-
<button @click=${() => setCount((v) => v + 1)}>+</button>
|
|
112
|
+
<button class=${styles.button} @click=${() => setCount((v) => v + 1)}>+</button>
|
|
113
|
+
</div>
|
|
114
|
+
<div class=${styles.mx}>
|
|
115
|
+
<h1>Sum: ${sum}</h1>
|
|
60
116
|
</div>
|
|
61
117
|
</div>
|
|
62
118
|
`;
|
|
63
119
|
};
|
|
64
120
|
|
|
65
|
-
|
|
121
|
+
export default createElement({
|
|
122
|
+
name,
|
|
123
|
+
attrTypes,
|
|
124
|
+
stateTypes,
|
|
125
|
+
computedTypes,
|
|
126
|
+
styles,
|
|
127
|
+
render,
|
|
128
|
+
});
|
|
66
129
|
|
|
67
130
|
console.log(ssr(html`<app-counter name="1"></app-counter>`));
|
|
68
131
|
```
|
|
69
132
|
|
|
70
133
|
This works in node, to make it work in the client side you need to either compile atoms-element using esintall or esbuild to an esm module and then
|
|
71
134
|
rewrite the path from 'atoms-element' to 'web_modules/atoms-element/index.js' or if you can host the node_modules in a web server and change the path to
|
|
72
|
-
the import '
|
|
135
|
+
the import 'atoms-element/element.js'
|