Skip to content

Commit ab5661b

Browse files
committed
[refactor] replace CSS Transition with Animate.css
[remove] useless Utility methods & types
1 parent 18f6cee commit ab5661b

File tree

10 files changed

+99
-123
lines changed

10 files changed

+99
-123
lines changed

ReadMe.md

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ https://web-cell.dev/scaffold/
2424

2525
- [x] **Path Mode**: `location.hash` (default) & `history.pushState()`
2626

27-
- [x] **Async Loading** (recommend to use with `import()` ECMAScript syntax)
27+
- [x] **Async Loading** (based on `import()` ECMAScript syntax)
2828

29-
- [x] CSS based **Page Transition Animation** (example [CSS][7] & [TSX][8])
29+
- [x] [Animate.css][7] based **Page Transition Animation**
3030

3131
## Installation
3232

@@ -74,8 +74,14 @@ import { createRouter, PageProps } from 'cell-router';
7474

7575
const { Route, Link } = createRouter();
7676

77-
const TestPage: FC<PageProps> = ({ path, history, defaultSlot, ...data }) => (
78-
<ul>
77+
const TestPage: FC<PageProps> = ({
78+
className,
79+
style,
80+
path,
81+
history,
82+
...data
83+
}) => (
84+
<ul {...{ className, style }}>
7985
<li>Path: {path}</li>
8086
<li>Data: {JSON.stringify(data)}</li>
8187
</ul>
@@ -88,6 +94,10 @@ new DOMRenderer().render(
8894
<Link to="example/2">Example</Link>
8995
</nav>
9096
<main className="router">
97+
<Route
98+
path=""
99+
component={props => <div {...props}>Home Page</div>}
100+
/>
91101
<Route path="test" component={TestPage} />
92102
<Route path="example/:id" component={TestPage} />
93103
</main>
@@ -116,8 +126,14 @@ import { createRouter, PageProps } from 'cell-router';
116126

117127
const { Route, Link } = createRouter();
118128

119-
const TestPage: FC<PageProps> = ({ path, history, defaultSlot, ...data }) => (
120-
<ul>
129+
const TestPage: FC<PageProps> = ({
130+
className,
131+
style,
132+
path,
133+
history,
134+
...data
135+
}) => (
136+
<ul {...{ className, style }}>
121137
<li>Path: {path}</li>
122138
<li>Data: {JSON.stringify(data)}</li>
123139
</ul>
@@ -131,6 +147,10 @@ new DOMRenderer().render(
131147
<Link to="example/2">Example</Link>
132148
</nav>
133149
<main className="router">
150+
<Route
151+
path=""
152+
component={props => <div {...props}>Home Page</div>}
153+
/>
134154
<Route path="test" component={TestPage} />
135155
<Route path="example/:id" component={AsyncPage} />
136156
</main>
@@ -144,5 +164,4 @@ new DOMRenderer().render(
144164
[4]: https://libraries.io/npm/cell-router
145165
[5]: https://github.com/EasyWebApp/cell-router/actions/workflows/main.yml
146166
[6]: https://nodei.co/npm/cell-router/
147-
[7]: https://github.com/EasyWebApp/cell-router/blob/b7f98243834f9226088c15b111428e211bbfaa9f/test/source/index.less#L5-L25
148-
[8]: https://github.com/EasyWebApp/cell-router/blob/b7f98243834f9226088c15b111428e211bbfaa9f/test/source/page/index.tsx#L19-L32
167+
[7]: https://animate.style/

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cell-router",
3-
"version": "3.0.0-rc.2",
3+
"version": "3.0.0-rc.3",
44
"license": "LGPL-3.0",
55
"description": "Web Component Router based on WebCell & MobX",
66
"keywords": [
@@ -29,7 +29,7 @@
2929
"mobx": ">=6.11",
3030
"regenerator-runtime": "^0.14.1",
3131
"urlpattern-polyfill": "^9.0.0",
32-
"web-cell": "^3.0.0-rc.6",
32+
"web-cell": "^3.0.0-rc.7",
3333
"web-utility": "^4.1.3"
3434
},
3535
"devDependencies": {
@@ -47,7 +47,7 @@
4747
"koapache": "^2.2.2",
4848
"lint-staged": "^15.2.0",
4949
"parcel": "~2.11.0",
50-
"prettier": "^3.1.1",
50+
"prettier": "^3.2.1",
5151
"process": "^0.11.10",
5252
"puppeteer-core": "^21.7.0",
5353
"rimraf": "^5.0.5",

pnpm-lock.yaml

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

source/Router.tsx

Lines changed: 47 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,31 @@
1-
import { JsxProps } from 'dom-renderer';
21
import { computed, observable } from 'mobx';
32
import {
3+
AnimateCSS,
4+
AnimationType,
45
ClassComponent,
5-
FunctionComponent,
6+
FC,
7+
WebCell,
8+
WebCellProps,
69
attribute,
710
component,
8-
observer,
9-
reaction
11+
observer
1012
} from 'web-cell';
1113

1214
import history, { History } from './History';
13-
import { PageProps, nextTick, watchStop } from './utility';
15+
import { IncludeText, PageProps } from './utility';
1416

15-
export interface CellRouteProps extends JsxProps<HTMLElement> {
17+
export interface CellRouteProps extends WebCellProps {
1618
path: string;
17-
component: FunctionComponent<PageProps> | ClassComponent;
18-
startClass?: string;
19-
endClass?: string;
19+
component: FC<PageProps> | ClassComponent;
20+
inAnimation?: IncludeText<AnimationType, 'In'>;
21+
outAnimation?: IncludeText<AnimationType, 'Out'>;
2022
}
2123

24+
export interface CellRoute extends WebCell {}
25+
2226
@component({ tagName: 'cell-route' })
2327
@observer
24-
export class CellRoute extends HTMLElement {
28+
export class CellRoute extends HTMLElement implements WebCell {
2529
declare props: CellRouteProps;
2630

2731
@attribute
@@ -32,17 +36,11 @@ export class CellRoute extends HTMLElement {
3236

3337
@attribute
3438
@observable
35-
accessor startClass = '';
39+
accessor inAnimation: CellRouteProps['inAnimation'] = 'fadeIn';
3640

3741
@attribute
3842
@observable
39-
accessor endClass = '';
40-
41-
@observable
42-
accessor moveClass = '';
43-
44-
@observable
45-
accessor moved = !this.endClass;
43+
accessor outAnimation: CellRouteProps['outAnimation'] = 'fadeOut';
4644

4745
@computed
4846
get matched() {
@@ -54,44 +52,45 @@ export class CellRoute extends HTMLElement {
5452
return History.match(this.path, history.oldPath);
5553
}
5654

57-
@reaction(({ matched }) => matched)
58-
protected async toggleMotion(enter?: any) {
59-
if (!this.startClass || !this.endClass) return;
60-
61-
this.moved = false;
62-
if (enter) {
63-
this.moveClass = this.startClass;
64-
await nextTick();
65-
} else {
66-
const end = watchStop(this, `.${this.endClass}`);
67-
this.moveClass = this.endClass;
68-
await end;
69-
this.moved = true;
70-
}
71-
this.moveClass = undefined;
55+
connectedCallback() {
56+
if (getComputedStyle(this.parentElement).position === 'static')
57+
this.parentElement.style.position = 'relative';
7258
}
7359

7460
render() {
75-
const { matched, oldMatched, component: Page, moveClass, moved } = this,
61+
const { inAnimation, outAnimation, matched, oldMatched } = this,
62+
Tag = this.component,
7663
{ path, oldPath } = history;
7764

7865
return matched ? (
79-
<Page
80-
className={moveClass}
81-
{...matched}
82-
{...History.dataOf(path)}
83-
{...{ path, history }}
66+
<AnimateCSS
67+
type={inAnimation}
68+
component={props => (
69+
<Tag
70+
{...props}
71+
style={{ position: 'absolute', top: '0', left: '0' }}
72+
{...matched}
73+
{...History.dataOf(path)}
74+
{...{ path, history }}
75+
/>
76+
)}
77+
/>
78+
) : oldMatched ? (
79+
<AnimateCSS
80+
type={outAnimation}
81+
component={props => (
82+
<Tag
83+
{...props}
84+
style={{ position: 'absolute', top: '0', left: '0' }}
85+
{...oldMatched}
86+
{...History.dataOf(oldPath)}
87+
path={oldPath}
88+
history={history}
89+
/>
90+
)}
8491
/>
8592
) : (
86-
oldMatched && !moved && (
87-
<Page
88-
className={moveClass}
89-
{...oldMatched}
90-
{...History.dataOf(oldPath)}
91-
path={oldPath}
92-
history={history}
93-
/>
94-
)
93+
<></>
9594
);
9695
}
9796
}

source/scope.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { PropsWithChildren } from 'web-cell';
44
import { CellRoute, CellRouteProps } from './Router';
55

66
export interface RouterOptions
7-
extends Pick<CellRouteProps, 'startClass' | 'endClass'> {
7+
extends Pick<CellRouteProps, 'inAnimation' | 'outAnimation'> {
88
mode?: 'hash' | 'history';
99
}
1010

source/utility.ts

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,12 @@ import { JsxProps } from 'dom-renderer';
22

33
import { History } from './History';
44

5-
export function watchStop<T extends HTMLElement | SVGElement>(
6-
root: T,
7-
targetSelector: string
8-
) {
9-
return new Promise<MotionEvent>(resolve => {
10-
function end(event: MotionEvent) {
11-
if (!(event.target as Element).matches(targetSelector)) return;
12-
13-
root.removeEventListener('transitionend', end);
14-
root.removeEventListener('transitioncancel', end);
15-
root.removeEventListener('animationend', end);
16-
root.removeEventListener('animationcancel', end);
17-
18-
resolve(event);
19-
}
20-
21-
root.addEventListener('transitionend', end);
22-
root.addEventListener('transitioncancel', end);
23-
root.addEventListener('animationend', end);
24-
root.addEventListener('animationcancel', end);
25-
});
26-
}
5+
export type IncludeText<Raw extends string, Sub extends string> = {
6+
[K in Raw]: K extends `${string}${Sub}${string}` ? K : never;
7+
}[Raw];
278

289
export interface PageProps extends JsxProps<HTMLElement> {
2910
path: string;
3011
history: History;
3112
[key: string]: any;
3213
}
33-
34-
export type MotionEvent = TransitionEvent | AnimationEvent;
35-
36-
export function nextTick() {
37-
return new Promise(resolve => self.requestAnimationFrame(resolve));
38-
}

test/source/index.less

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,4 @@ nav {
44
}
55
.router {
66
height: 100vh;
7-
overflow: auto;
8-
position: relative;
9-
.page {
10-
position: absolute;
11-
top: 0;
12-
left: 0;
13-
transform: translateX(0);
14-
opacity: 1;
15-
transition: 0.25s;
16-
}
17-
.start {
18-
transform: translateX(100%);
19-
opacity: 0;
20-
}
21-
.end {
22-
transform: translateX(-100%);
23-
opacity: 0;
24-
}
257
}

test/source/page/async.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { FC } from 'web-cell';
22
import { PageProps } from '../../../source';
33

4-
const AsyncPage: FC<PageProps> = props => (
5-
<div className={`page ${props.className}`}>
4+
const AsyncPage: FC<PageProps> = ({ path, id, edit, ...props }) => (
5+
<div {...props}>
66
<h1>Async</h1>
77
<pre>
8-
<code>{JSON.stringify(props, null, 4)}</code>
8+
<code>{JSON.stringify({ path, id, edit, ...props }, null, 4)}</code>
99
</pre>
1010
</div>
1111
);

test/source/page/example.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ export interface TestPageProps extends PageProps {
55
edit: boolean;
66
}
77

8-
export const TestPage: FC<TestPageProps> = ({ className, path, id, edit }) => (
9-
<ul className={`page ${className}`}>
8+
export const TestPage: FC<TestPageProps> = ({ path, id, edit, ...props }) => (
9+
<ul {...props}>
1010
<li>Path: {path}</li>
1111
<li>Data: {JSON.stringify({ id, edit })}</li>
1212
</ul>

0 commit comments

Comments
 (0)