~repos /atoms-element

#js

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
Files changed (3) hide show
  1. example/styles.css +0 -2
  2. page.test.js +6 -7
  3. 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
- div: {
11
+ div: {
13
- color: 'red',
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
  ![Test](https://github.com/pyros2097/atoms-element/actions/workflows/main.yml/badge.svg)
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 { defineElement, html, object, number, string, useState } from 'atoms-element';
37
+ import { createElement, html, css, object, number, string } from 'atoms-element/element.js';
39
- import { ssr } from 'atoms-element/src/ssr.js';
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.isRequired,
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 Counter = ({ name, meta }) => {
96
+ const render = ({ attrs, state, computed }) => {
97
+ const { name, meta } = attrs;
49
- const [count, setCount] = useState(meta?.start || 0);
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
- <div class="font-bold mb-2">Counter: ${name}</div>
105
+ <span class=${styles.span}>starts at ${meta?.start}</span>
106
+ </div>
54
- <div class="flex flex-1 flex-row text-3xl text-gray-700">
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="mx-20">
109
+ <div class=${styles.mx}>
57
- <h1 class="text-1xl">${count}</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
- defineElement('app-counter', Counter, attrTypes);
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 'node_modules/atoms-element/index.js'
135
+ the import 'atoms-element/element.js'