Skip to content

Commit cd1f523

Browse files
committed
[optimize] support extending Original HTML tags
[optimize] support Declarative Shadow DOM [add] Migration guide document [optimize] upgrade ReadMe document [add] Jest configuration of VS Code debugger
1 parent 91ee45e commit cd1f523

File tree

17 files changed

+770
-495
lines changed

17 files changed

+770
-495
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ jobs:
1616
registry-url: https://registry.npmjs.org
1717
cache: yarn
1818
- name: Install, Build & Publish
19-
run: |
20-
yarn
21-
yarn publish
19+
run: yarn && yarn publish
2220
env:
2321
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
2422
- name: Update document
@@ -27,10 +25,3 @@ jobs:
2725
publish_dir: ./docs
2826
personal_token: ${{ secrets.GITHUB_TOKEN }}
2927
force_orphan: true
30-
- name: Publish Adapter
31-
run: |
32-
cd MobX/
33-
yarn
34-
yarn publish
35-
env:
36-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ package-lock.json
33
dist/
44
.parcel-cache/
55
docs/
6-
.vscode/
6+
.vscode/settings.json

.npmignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,4 @@ Contributing.md
66
docs/
77
.husky/
88
.github/
9-
.vscode/
10-
MobX/
9+
.vscode/

.vscode/launch.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"version": "0.2.0",
3+
"configurations": [
4+
{
5+
"name": "Debug Jest",
6+
"type": "node",
7+
"request": "launch",
8+
"port": 9229,
9+
"runtimeArgs": [
10+
"--inspect-brk",
11+
"${workspaceRoot}/node_modules/jest/bin/jest.js",
12+
"--runInBand"
13+
],
14+
"console": "integratedTerminal",
15+
"internalConsoleOptions": "neverOpen"
16+
}
17+
]
18+
}

Migrating.md

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# WebCell v2 to v3 migration
2+
3+
## "state" concept has been totally dropped
4+
5+
**WebCell v3** is heavily inspired by [the **Local Observable State** idea of **MobX**][1], and [not only React][2], Web Components can be much easier to manage the **Inner State & Logic**, without any complex things:
6+
7+
1. State type declaration
8+
2. `this.state` declaration & its type annotation/assertion
9+
3. `this.setState()` method calling & its callback
10+
4. confusive _Hooks API_...
11+
12+
Just declare a **State Store class** as what the **Global State Managment** does, and initial it on the `this` (a **Web Component instance**). Then use the state, and observe them, as [MobX][3]'s usual, everything is done.
13+
14+
```diff
15+
import {
16+
component,
17+
+ observer,
18+
- mixin,
19+
+ WebCell,
20+
createCell,
21+
Fragment
22+
} from 'web-cell';
23+
+import { observable } from 'mobx';
24+
25+
-interface State {
26+
+class State {
27+
+ @observable
28+
key: string;
29+
}
30+
31+
@component({
32+
tagName: 'my-tag'
33+
})
34+
+@observer
35+
-export class MyTag extends mixin<{}, State>() {
36+
+export class MyTag extends WebCell() {
37+
- state: Readonly<State> = {
38+
- key: 'value'
39+
- };
40+
+ state = new State();
41+
42+
- render({}: any, { key }: State) {
43+
+ render() {
44+
+ const { key } = this.state;
45+
46+
return <>{value}</>;
47+
}
48+
}
49+
```
50+
51+
At the same time, `shouldUpdate() {}` life-cycle has been dropped. You just need to control the logic before states changed in your `State` class methods.
52+
53+
## DOM properties become observable data
54+
55+
**DOM properties** aren't like React's props, they're **reactive**. They are not only responsible to **update Component views**, but also **synchronize with HTML attriutes**.
56+
57+
MobX's [`@observable`][4] & [`reaction()`][5] are awesome APIs to implement these above with clear codes, so we add `mobx` package as a dependency:
58+
59+
```shell
60+
npm install mobx@5
61+
```
62+
63+
On the other hand, [`mobx-web-cell` adapter][6] has been merged into the core package. And cause of replacing **Prototype Overwrite** with **Class Inheritance** to refactor **Class Mixins**, `@observer` decorator should follow strict order to make observation work:
64+
65+
```diff
66+
import {
67+
WebCellProps,
68+
component,
69+
attribute,
70+
- watch,
71+
+ observer,
72+
- mixin,
73+
+ WebCell,
74+
createCell,
75+
Fragment
76+
} from 'web-cell';
77+
-import { observer } from 'mobx-web-cell';
78+
+import { observable } from 'mobx';
79+
80+
export interface MyTagProps extends WebCellProps {
81+
count?: number
82+
}
83+
84+
@component({
85+
tagName: 'my-tag'
86+
})
87+
@observer
88+
-export class MyTag extends mixin<MyTagProps>() {
89+
+export class MyTag extends WebCell<MyTagProps>() {
90+
@attribute
91+
- @watch
92+
+ @observable
93+
count = 0;
94+
95+
- render({ count }: MyTagProps) {
96+
+ render() {
97+
+ const { count } = this;
98+
99+
return <>{count}</>;
100+
}
101+
}
102+
```
103+
104+
## control Render Target with Shadow DOM Mode option
105+
106+
### render to `children`
107+
108+
```diff
109+
import {
110+
component,
111+
- mixin
112+
+ WebCell
113+
} from 'web-cell';
114+
115+
@component({
116+
tagName: 'my-tag',
117+
- renderTarget: 'children'
118+
})
119+
-export class MyTag extends mixin() {
120+
+export class MyTag extends WebCell() {
121+
}
122+
```
123+
124+
### render to `shadowRoot`
125+
126+
```diff
127+
import {
128+
component,
129+
- mixin
130+
+ WebCell
131+
} from 'web-cell';
132+
133+
@component({
134+
tagName: 'my-tag',
135+
- renderTarget: 'shadowRoot'
136+
+ mode: 'open'
137+
})
138+
-export class MyTag extends mixin() {
139+
+export class MyTag extends WebCell() {
140+
}
141+
```
142+
143+
## move Shadow CSS injection into `render()`
144+
145+
This makes **Shadow CSS** to react with the data of component instances.
146+
147+
```diff
148+
+import { stringifyCSS } from 'web-utility';
149+
import {
150+
component,
151+
- mixin
152+
+ WebCell
153+
} from 'web-cell';
154+
155+
@component({
156+
tagName: 'my-tag',
157+
- renderTarget: 'shadowRoot',
158+
+ mode: 'open',
159+
- style: {
160+
- ':host(.active)': {
161+
- color: 'red'
162+
- }
163+
- }
164+
})
165+
-export class MyTag extends mixin() {
166+
+export class MyTag extends WebCell() {
167+
render() {
168+
return <>
169+
+ <style>
170+
+ {stringifyCSS({
171+
+ ':host(.active)': {
172+
+ color: 'red'
173+
+ }
174+
+ })}
175+
+ </style>
176+
test
177+
</>;
178+
}
179+
}
180+
```
181+
182+
## rename some APIs
183+
184+
[JSDoc's `@deprecated` hints][7] will lead your way to rename them:
185+
186+
1. `mixin()` => `WebCell()`
187+
2. `mixinForm()` => `WebField()`
188+
3. `@watch` => `@observable`
189+
190+
## Appendix: v3 prototype
191+
192+
1. https://codesandbox.io/s/web-components-jsx-i7u60?file=/index.tsx
193+
2. https://codesandbox.io/s/mobx-lite-791eg?file=/src/index.ts
194+
195+
[1]: https://github.com/mobxjs/mobx/blob/mobx4and5/docs/refguide/observer-component.md#local-observable-state-in-class-based-components
196+
[2]: https://blog.cloudboost.io/3-reasons-why-i-stopped-using-react-setstate-ab73fc67a42e
197+
[3]: https://github.com/mobxjs/mobx/tree/mobx4and5/docs
198+
[4]: https://github.com/mobxjs/mobx/blob/mobx4and5/docs/refguide/observable-decorator.md
199+
[5]: https://github.com/mobxjs/mobx/blob/mobx4and5/docs/refguide/reaction.md
200+
[6]: https://github.com/EasyWebApp/WebCell/tree/v2/MobX
201+
[7]: https://jsdoc.app/tags-deprecated.html

0 commit comments

Comments
 (0)