Skip to content

Commit 8ccec10

Browse files
committed
[add] Animate.css wrap component
[fix] bugs of Observed Attribute , Async Cell & Read Me
1 parent 01be249 commit 8ccec10

File tree

11 files changed

+201
-49
lines changed

11 files changed

+201
-49
lines changed

Contributing.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
git clone https://github.com/EasyWebApp/WebCell.git ~/Desktop/WebCell
77
cd ~/Desktop/WebCell
88

9-
npm install
9+
npm i pnpm -g
10+
pnpm i
1011
npm test
11-
npm run build
12+
pnpm build
1213
```

ReadMe.md

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -454,11 +454,28 @@ export default AsyncTag;
454454
#### `index.tsx`
455455

456456
```tsx
457+
import { DOMRenderer } from 'dom-renderer';
458+
import { lazy } from 'web-cell';
459+
457460
const AsyncTag = lazy(() => import('./AsyncTag'));
458461

459462
new DOMRenderer().render(<AsyncTag />);
460463
```
461464

465+
### Animate CSS component
466+
467+
```tsx
468+
import { DOMRenderer } from 'dom-renderer';
469+
import { AnimateCSS } from 'web-cell';
470+
471+
new DOMRenderer().render(
472+
<AnimateCSS
473+
type="fadeIn"
474+
component={props => <h1 {...props}>Fade In</h1>}
475+
/>
476+
);
477+
```
478+
462479
## Node.js usage
463480

464481
### Tool chain
@@ -505,7 +522,7 @@ import 'web-cell/polyfill';
505522

506523
We recommend these libraries to use with WebCell:
507524

508-
- **State management**: [MobX][42] (also powered by **TypeScript** & **Decorator**)
525+
- **State management**: [MobX][3] (also powered by **TypeScript** & **Decorator**)
509526
- **Router**: [Cell Router][43]
510527
- **UI components**
511528

@@ -520,14 +537,13 @@ We recommend these libraries to use with WebCell:
520537

521538
## Roadmap
522539

523-
- [x] [Extend **Build-in Elements** with Virtual DOM][51]
524-
- [x] [Server-side Render][52]
525-
- [x] [Async Component loading][53]
540+
- [x] [Server-side Render][51]
541+
- [x] [Async Component loading][52]
526542

527543
## More guides
528544

529-
1. [v2 to v3 migration][54]
530-
2. [Development contribution][55]
545+
1. [v2 to v3 migration][53]
546+
2. [Development contribution][54]
531547

532548
[1]: https://www.webcomponents.org/
533549
[2]: https://facebook.github.io/jsx/
@@ -539,7 +555,7 @@ We recommend these libraries to use with WebCell:
539555
[8]: https://github.com/jaywcjlove/awesome-uikit
540556
[9]: https://tech-query.me/programming/web-components-practise/slide.html
541557
[10]: https://gitter.im/EasyWebApp/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
542-
[11]: https://codesandbox.io/s/webcell-demo-9gyll?autoresize=1&fontsize=14&hidenavigation=1&module=%2Fsrc%2FClock.tsx&theme=dark
558+
[11]: https://codesandbox.io/p/devbox/9gyll?embed=1&file=%2Fsrc%2FClock.tsx
543559
[12]: https://nodei.co/npm/web-cell/
544560
[13]: https://www.typescriptlang.org/
545561
[14]: https://github.com/tc39/proposal-decorators
@@ -570,7 +586,6 @@ We recommend these libraries to use with WebCell:
570586
[39]: https://github.com/EasyWebApp/scaffold
571587
[40]: https://github.com/EasyWebApp/DashBoard
572588
[41]: https://github.com/EasyWebApp/mark-wiki
573-
[42]: https://github.com/mobxjs/mobx/blob/mobx4and5/docs/
574589
[43]: https://web-cell.dev/cell-router/
575590
[44]: https://bootstrap.web-cell.dev/
576591
[45]: https://material.web-cell.dev/
@@ -579,8 +594,7 @@ We recommend these libraries to use with WebCell:
579594
[48]: https://web-cell.dev/web-utility/
580595
[49]: https://web-cell.dev/iterable-observer/
581596
[50]: https://github.com/EasyWebApp/MarkCell
582-
[51]: https://github.com/snabbdom/snabbdom/pull/829
583-
[52]: https://web.dev/declarative-shadow-dom/
584-
[53]: https://reactjs.org/docs/react-api.html#reactlazy
585-
[54]: https://github.com/EasyWebApp/WebCell/blob/main/Migrating.md
586-
[55]: https://github.com/EasyWebApp/WebCell/blob/main/Contributing.md
597+
[51]: https://web.dev/declarative-shadow-dom/
598+
[52]: https://reactjs.org/docs/react-api.html#reactlazy
599+
[53]: https://github.com/EasyWebApp/WebCell/blob/main/Migrating.md
600+
[54]: https://github.com/EasyWebApp/WebCell/blob/main/Contributing.md

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "web-cell",
3-
"version": "3.0.0-rc.5",
3+
"version": "3.0.0-rc.7",
44
"description": "Web Components engine based on VDOM, JSX, MobX & TypeScript",
55
"keywords": [
66
"web",
@@ -58,7 +58,7 @@
5858
"lint-staged": "^15.2.0",
5959
"open-cli": "^8.0.0",
6060
"parcel": "~2.11.0",
61-
"prettier": "^3.1.1",
61+
"prettier": "^3.2.0",
6262
"rimraf": "^5.0.5",
6363
"ts-jest": "^29.1.1",
6464
"ts-node": "^10.9.2",

pnpm-lock.yaml

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

preview/Home.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
import { formToJSON } from 'web-utility';
2-
import { FC, PropsWithChildren, lazy } from '../source';
2+
import { AnimateCSS, FC, WebCellProps, lazy } from '../source';
33

44
import { ClassClock, FunctionClock } from './Clock';
55
import { TestField } from './Field';
66

77
const Async = lazy(() => import('./Async'));
88

9-
const Hello: FC<PropsWithChildren> = ({ children }) => (
10-
<h1>Hello {children}!</h1>
9+
const Hello: FC<WebCellProps> = ({ className, children }) => (
10+
<h1 className={className}>Hello {children}!</h1>
1111
);
1212

1313
export const HomePage = () => (
1414
<>
15-
<Hello>WebCell</Hello>
15+
<AnimateCSS
16+
type="fadeIn"
17+
component={props => <Hello {...props}>WebCell</Hello>}
18+
/>
1619
<div>
1720
We use the same configuration as Parcel to bundle this sandbox, you
1821
can find more info about Parcel

source/Animation/index.tsx

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { observable } from 'mobx';
2+
import { importCSS } from 'web-utility';
3+
4+
import { WebCellProps } from '../Async';
5+
import { animated } from '../MobX';
6+
import { WebCell, component } from '../WebCell';
7+
import { FC, attribute, observer, reaction } from '../decorator';
8+
import { AnimationType } from './type';
9+
10+
export * from './type';
11+
12+
export interface AnimateCSS extends WebCell {}
13+
14+
export interface AnimateCSSProps {
15+
type: AnimationType;
16+
component: FC<WebCellProps>;
17+
}
18+
19+
@component({ tagName: 'animation-css' })
20+
@observer
21+
export class AnimateCSS extends HTMLElement implements WebCell {
22+
declare props: AnimateCSSProps;
23+
24+
@attribute
25+
@observable
26+
accessor type: AnimationType;
27+
28+
@attribute
29+
@observable
30+
accessor playing = false;
31+
32+
component: FC<WebCellProps>;
33+
34+
async connectedCallback() {
35+
await importCSS('https://unpkg.com/animate.css@4/animate.min.css');
36+
37+
this.typeChanged();
38+
}
39+
40+
@reaction(({ type }) => type)
41+
async typeChanged() {
42+
this.playing = true;
43+
44+
await animated(this, '.animate__animated');
45+
46+
this.playing = false;
47+
}
48+
49+
render() {
50+
const { type, playing, component: Tag } = this;
51+
52+
return playing ? (
53+
<Tag className={`animate__animated animate__${type}`} />
54+
) : type.includes('Out') ? (
55+
<></>
56+
) : (
57+
<Tag />
58+
);
59+
}
60+
}

source/Animation/type.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
export type PositionY = 'Top' | 'Bottom';
2+
export type DirectionX = 'Left' | 'Right';
3+
export type DirectionY = 'Up' | 'Down';
4+
export type Direction = DirectionX | DirectionY;
5+
export type AnimationMode = 'In' | 'Out';
6+
7+
export type AttentionSeekers =
8+
| 'bounce'
9+
| 'flash'
10+
| 'pulse'
11+
| 'rubberBand'
12+
| `shake${'X' | 'Y'}`
13+
| 'headShake'
14+
| 'swing'
15+
| 'tada'
16+
| 'wobble'
17+
| 'jello'
18+
| 'heartBeat';
19+
export type BackEntrances = `backIn${Direction}`;
20+
export type BackExits = `backOut${Direction}`;
21+
export type BouncingEntrances = `bounceIn${'' | Direction}`;
22+
export type BouncingExits = `bounceOut${'' | Direction}`;
23+
export type FadingEntrances =
24+
| `fadeIn${'' | `${Direction}${'' | 'Big'}`}`
25+
| `fadeIn${PositionY}${DirectionX}`;
26+
export type FadingExits = `fadeOut${
27+
| ''
28+
| `${Direction}${'' | 'Big'}`
29+
| `${PositionY}${DirectionX}`}`;
30+
export type Flippers = `flip${'' | `${AnimationMode}${'X' | 'Y'}`}`;
31+
export type Lightspeed = `lightSpeed${AnimationMode}${DirectionX}`;
32+
export type RotatingEntrances = `rotateIn${'' | `${DirectionY}${DirectionX}`}`;
33+
export type RotatingExits = `rotateOut${'' | `${DirectionY}${DirectionX}`}`;
34+
export type Specials = 'hinge' | 'jackInTheBox' | `roll${'In' | 'Out'}`;
35+
export type ZoomingEntrances = `zoomIn${'' | Direction}`;
36+
export type ZoomingExits = `zoomOut${'' | Direction}`;
37+
export type SlidingEntrances = `slideIn${Direction}`;
38+
export type SlidingExits = `slideOut${Direction}`;
39+
40+
export type AnimationType =
41+
| AttentionSeekers
42+
| BackEntrances
43+
| BackExits
44+
| BouncingEntrances
45+
| BouncingExits
46+
| FadingEntrances
47+
| FadingExits
48+
| Flippers
49+
| Lightspeed
50+
| RotatingEntrances
51+
| RotatingExits
52+
| Specials
53+
| ZoomingEntrances
54+
| ZoomingExits
55+
| SlidingEntrances
56+
| SlidingExits;

source/Async.tsx

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,45 @@
1-
import { observable } from 'mobx';
21
import { JsxProps } from 'dom-renderer';
2+
import { observable } from 'mobx';
33

44
import { ClassComponent, WebCell, component } from './WebCell';
55
import {
66
FC,
77
FunctionComponent,
88
PropsWithChildren,
99
WebCellComponent,
10-
observer,
11-
reaction
10+
observer
1211
} from './decorator';
1312

1413
export type ComponentTag = string | WebCellComponent;
1514

1615
export type WebCellProps<T extends HTMLElement = HTMLElement> = JsxProps<T>;
1716

18-
export interface AsyncBoxProps extends WebCellProps {
17+
export interface AsyncCellProps extends WebCellProps {
1918
loader: () => Promise<ComponentTag>;
2019
delegatedProps?: WebCellProps;
2120
}
2221

23-
export interface AsyncBox extends WebCell {}
22+
export interface AsyncCell extends WebCell {}
2423

2524
@component({
26-
tagName: 'async-box'
25+
tagName: 'async-cell'
2726
})
2827
@observer
29-
export class AsyncBox extends HTMLElement {
30-
declare props: AsyncBoxProps;
28+
export class AsyncCell extends HTMLElement {
29+
declare props: AsyncCellProps;
3130

32-
@observable
33-
accessor loader: AsyncBoxProps['loader'];
31+
loader: AsyncCellProps['loader'];
3432

3533
@observable
3634
accessor component: FC<PropsWithChildren>;
3735

3836
@observable
39-
accessor delegatedProps: AsyncBoxProps['delegatedProps'];
37+
accessor delegatedProps: AsyncCellProps['delegatedProps'];
4038

4139
connectedCallback() {
4240
this.load();
4341
}
4442

45-
@reaction((element: AsyncBox) => element.loader)
4643
protected async load() {
4744
this.component = undefined;
4845

@@ -72,7 +69,7 @@ export function lazy<
7269
T extends () => Promise<{ default: FunctionComponent | ClassComponent }>
7370
>(loader: T) {
7471
return (props: GetAsyncProps<T>) => (
75-
<AsyncBox
72+
<AsyncCell
7673
delegatedProps={props}
7774
loader={async () => (await loader()).default}
7875
/>

source/MobX.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { DataObject } from 'dom-renderer';
22
import { ObservableValue } from 'mobx/dist/internal';
3+
import { delegate } from 'web-utility';
34

45
export function getMobxData<T extends DataObject>(observable: T) {
56
for (const key of Object.getOwnPropertySymbols(observable)) {
@@ -13,3 +14,18 @@ export function getMobxData<T extends DataObject>(observable: T) {
1314
) as T;
1415
}
1516
}
17+
18+
export const animated = <T extends HTMLElement | SVGElement>(
19+
root: T,
20+
targetSelector: string
21+
) =>
22+
new Promise<AnimationEvent>(resolve => {
23+
const ended = delegate(targetSelector, (event: AnimationEvent) => {
24+
root.removeEventListener('animationend', ended);
25+
root.removeEventListener('animationcancel', ended);
26+
resolve(event);
27+
});
28+
29+
root.addEventListener('animationend', ended);
30+
root.addEventListener('animationcancel', ended);
31+
});

0 commit comments

Comments
 (0)