amateras 0.13.2 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -38
- package/build/core.js +1 -1
- package/build/css-keyframes.js +1 -0
- package/build/css-property.js +1 -0
- package/build/css-variable.js +1 -0
- package/build/for.js +1 -1
- package/build/i18n.js +1 -1
- package/build/if.js +1 -1
- package/build/import-map.js +1 -1
- package/build/match.js +1 -1
- package/build/meta.js +1 -1
- package/build/prefetch.js +1 -1
- package/build/router.js +1 -1
- package/build/signal.js +1 -1
- package/build/store.js +1 -1
- package/build/ui.js +1 -1
- package/build/utils.js +1 -1
- package/build/widget.js +1 -1
- package/package.json +3 -2
- package/packages/core/src/index.ts +86 -31
- package/packages/core/src/lib/hmr.ts +4 -4
- package/packages/core/src/structure/ElementProto.ts +33 -11
- package/packages/core/src/structure/GlobalState.ts +13 -4
- package/packages/core/src/structure/NodeProto.ts +2 -4
- package/packages/core/src/structure/Proto.ts +37 -23
- package/packages/core/src/structure/TextProto.ts +1 -2
- package/packages/css/README.md +18 -15
- package/packages/css/src/ext/property.ts +2 -3
- package/packages/css/src/index.ts +1 -1
- package/packages/css/src/structure/$CSSProperty.ts +4 -0
- package/packages/css/src/structure/$CSSVariable.ts +1 -1
- package/packages/css/src/types.ts +5 -0
- package/packages/for/src/global.ts +12 -3
- package/packages/for/src/structure/For.ts +5 -3
- package/packages/i18n/README.md +16 -24
- package/packages/i18n/src/index.ts +26 -5
- package/packages/i18n/src/structure/I18n.ts +2 -4
- package/packages/i18n/src/structure/I18nSession.ts +4 -2
- package/packages/i18n/src/structure/I18nTranslation.ts +15 -26
- package/packages/idb/src/structure/$IDBStore.ts +2 -2
- package/packages/if/src/global.ts +15 -4
- package/packages/if/src/index.ts +18 -8
- package/packages/if/src/structure/Condition.ts +16 -13
- package/packages/if/src/structure/ConditionStatement.ts +9 -9
- package/packages/match/src/global.ts +9 -3
- package/packages/match/src/structure/Match.ts +1 -1
- package/packages/meta/src/index.ts +4 -5
- package/packages/prefetch/src/index.ts +30 -9
- package/packages/router/src/global.ts +17 -4
- package/packages/router/src/index.ts +25 -18
- package/packages/router/src/structure/Route.ts +2 -1
- package/packages/router/src/structure/RouteNode.ts +8 -6
- package/packages/router/src/structure/RouteSlot.ts +15 -2
- package/packages/router/src/structure/Router.ts +28 -19
- package/packages/router/src/structure/RouterConstructor.ts +5 -5
- package/packages/router/src/types.ts +2 -2
- package/packages/signal/README.md +28 -48
- package/packages/signal/src/index.ts +61 -38
- package/packages/signal/src/structure/Signal.ts +40 -7
- package/packages/store/src/structure/Store.ts +1 -1
- package/packages/ui/package.json +2 -1
- package/packages/ui/src/icon/check.svg.ts +1 -0
- package/packages/ui/src/icon/x.svg.ts +1 -0
- package/packages/ui/src/index.ts +9 -2
- package/packages/ui/src/lib/combobox_style.ts +20 -0
- package/packages/ui/src/lib/hover.ts +2 -0
- package/packages/ui/src/structure/Badge.ts +10 -1
- package/packages/ui/src/structure/Button.ts +54 -27
- package/packages/ui/src/structure/Card.ts +3 -4
- package/packages/ui/src/structure/Combobox/Combobox.ts +312 -0
- package/packages/ui/src/structure/Combobox/ComboboxChips.ts +178 -0
- package/packages/ui/src/structure/Combobox/ComboboxList.ts +209 -0
- package/packages/ui/src/structure/ContextMenu.ts +89 -0
- package/packages/ui/src/structure/Field.ts +109 -0
- package/packages/ui/src/structure/Input.ts +29 -0
- package/packages/ui/src/structure/Select/Select.ts +18 -8
- package/packages/ui/src/structure/Select/SelectContent.ts +6 -1
- package/packages/ui/src/structure/Select/SelectItem.ts +2 -1
- package/packages/ui/src/structure/Slideshow.ts +2 -2
- package/packages/ui/src/structure/Switch.ts +45 -0
- package/packages/ui/src/structure/Tabs.ts +3 -3
- package/packages/ui/src/structure/Toggle.ts +155 -0
- package/packages/ui/src/structure/Waterfall.ts +1 -1
- package/packages/ui/src/structure/WaterfallItem.ts +1 -1
- package/packages/utils/src/lib/utils.ts +30 -8
- package/packages/utils/src/structure/UID.ts +1 -1
- package/packages/widget/src/index.ts +29 -9
- package/packages/widget/src/structure/Widget.ts +7 -3
- package/packages/ui/src/structure/TextBlock.ts +0 -11
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import * as _Link from "#structure/Link";
|
|
2
2
|
import * as _NavLink from "#structure/NavLink";
|
|
3
3
|
import * as _Router from "#structure/Router";
|
|
4
|
-
import type {
|
|
4
|
+
import type { RouterConstructor, RouterHandle } from "#structure/RouterConstructor";
|
|
5
|
+
import type { RouteSlot } from "#structure/RouteSlot";
|
|
6
|
+
import type { Proto } from "@amateras/core";
|
|
5
7
|
|
|
6
8
|
declare global {
|
|
7
9
|
export var Link: typeof _Link.Link;
|
|
8
10
|
export var NavLink: typeof _NavLink.NavLink;
|
|
9
|
-
export function $(Router: Router): _Router.RouterProto;
|
|
10
11
|
|
|
11
12
|
export type Link = _Link.Link;
|
|
12
13
|
export type NavLink = _NavLink.NavLink;
|
|
13
14
|
|
|
14
15
|
export namespace $ {
|
|
15
|
-
export function router(handle: RouterHandle):
|
|
16
|
+
export function router(handle: RouterHandle): RouterConstructor;
|
|
16
17
|
|
|
17
18
|
export function open(path: string, target?: string): void;
|
|
18
19
|
export function forward(): void;
|
|
@@ -20,6 +21,18 @@ declare global {
|
|
|
20
21
|
export function replace(path: string): void;
|
|
21
22
|
export function scrollRestoration(): void;
|
|
22
23
|
|
|
23
|
-
export function title(title: OrPromise<string
|
|
24
|
+
export function title(title: OrPromise<string>, parent?: Proto | null): void;
|
|
25
|
+
|
|
26
|
+
interface ProtoEventMap<P extends Proto> {
|
|
27
|
+
pageswitch: [slot: RouteSlot, direction: _Router.RouterDicrection]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface Overload<I> {
|
|
31
|
+
router: [
|
|
32
|
+
input: [RouterConstructor],
|
|
33
|
+
output: [_Router.Router],
|
|
34
|
+
args: []
|
|
35
|
+
]
|
|
36
|
+
}
|
|
24
37
|
}
|
|
25
38
|
}
|
|
@@ -4,7 +4,7 @@ import { Page } from '#structure/Page';
|
|
|
4
4
|
import { Route } from '#structure/Route';
|
|
5
5
|
import { RouteGroup } from '#structure/RouteGroup';
|
|
6
6
|
import { RouteNode } from '#structure/RouteNode';
|
|
7
|
-
import {
|
|
7
|
+
import { Router } from '#structure/Router';
|
|
8
8
|
import { RouterConstructor } from '#structure/RouterConstructor';
|
|
9
9
|
import { symbol_ProtoType } from '@amateras/core';
|
|
10
10
|
import { GlobalState } from '@amateras/core';
|
|
@@ -17,25 +17,27 @@ declare module "@amateras/core" {
|
|
|
17
17
|
export interface GlobalState {
|
|
18
18
|
title: string | null
|
|
19
19
|
router: {
|
|
20
|
-
routers: Set<
|
|
20
|
+
routers: Set<Router>;
|
|
21
21
|
resolve: (path: string) => Promise<void>[];
|
|
22
22
|
href: URL;
|
|
23
23
|
routes: Route[];
|
|
24
24
|
matchPaths: string[];
|
|
25
25
|
navlinks: Set<NavLink>;
|
|
26
|
+
scrollQueue: Set<Promise<any>>;
|
|
27
|
+
postScrollRestoration(promise: Promise<any>): void;
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
let routePlannerPrototype = {
|
|
31
|
-
route(this: Route |
|
|
33
|
+
route(this: Route | Router, path: string, layout: PageLayout<string>, handle?: (route: Route) => void) {
|
|
32
34
|
let route = new RouteNode(path, layout);
|
|
33
35
|
this.routes.set(path, route);
|
|
34
36
|
handle?.(route);
|
|
35
37
|
return this;
|
|
36
38
|
},
|
|
37
39
|
|
|
38
|
-
group(this: Route |
|
|
40
|
+
group(this: Route | Router, path: string, handle?: (route: Route) => void) {
|
|
39
41
|
let group = new RouteGroup(path);
|
|
40
42
|
this.routes.set(path, group);
|
|
41
43
|
handle?.(group);
|
|
@@ -48,19 +50,24 @@ let routePlannerPrototype = {
|
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
_Object_assign(Route.prototype, routePlannerPrototype);
|
|
51
|
-
_Object_assign(
|
|
52
|
-
|
|
53
|
+
_Object_assign(Router.prototype, routePlannerPrototype);
|
|
54
|
+
GlobalState.assign(() => ({
|
|
53
55
|
router: {
|
|
54
|
-
routers: new Set<
|
|
56
|
+
routers: new Set<Router>(),
|
|
55
57
|
resolve(this, path: string) {
|
|
56
58
|
return map(this.routers, router => router.resolve(path));
|
|
57
59
|
},
|
|
58
60
|
href: new URL('http://localhost'),
|
|
59
61
|
routes: [],
|
|
60
62
|
matchPaths: [],
|
|
61
|
-
navlinks: new Set()
|
|
63
|
+
navlinks: new Set(),
|
|
64
|
+
scrollQueue: new Set<Promise<any>>(),
|
|
65
|
+
postScrollRestoration(promise: Promise<any>) {
|
|
66
|
+
promise.finally(() => this.scrollQueue.delete(promise));
|
|
67
|
+
this.scrollQueue.add(promise);
|
|
68
|
+
}
|
|
62
69
|
}
|
|
63
|
-
})
|
|
70
|
+
}))
|
|
64
71
|
|
|
65
72
|
GlobalState.disposers.add(({router}) => {
|
|
66
73
|
router.routers.clear();
|
|
@@ -70,15 +77,15 @@ GlobalState.disposers.add(({router}) => {
|
|
|
70
77
|
})
|
|
71
78
|
|
|
72
79
|
_Object_assign($, {
|
|
73
|
-
router: (handle: ($$:
|
|
74
|
-
open:
|
|
75
|
-
replace:
|
|
76
|
-
back:
|
|
77
|
-
forward:
|
|
78
|
-
scrollRestoration:
|
|
80
|
+
router: (handle: ($$: Router) => void) => RouterConstructor(handle),
|
|
81
|
+
open: Router.open,
|
|
82
|
+
replace: Router.replace,
|
|
83
|
+
back: Router.back,
|
|
84
|
+
forward: Router.forward,
|
|
85
|
+
scrollRestoration: Router.scrollRestoration,
|
|
79
86
|
|
|
80
|
-
title(title: OrPromise<string
|
|
81
|
-
let page =
|
|
87
|
+
title(title: OrPromise<string>, parent: Proto | null = Proto.proto) {
|
|
88
|
+
let page = parent?.findAbove<Page>(proto => is(proto, Page));
|
|
82
89
|
if (page) {
|
|
83
90
|
page.title = title;
|
|
84
91
|
page.updateTitle();
|
|
@@ -92,7 +99,7 @@ globalThis.NavLink = NavLink;
|
|
|
92
99
|
$.process.craft.add((value) => {
|
|
93
100
|
if (isFunction(value) && value[symbol_ProtoType] === 'Router') {
|
|
94
101
|
let proto = Proto.proto;
|
|
95
|
-
let router = new value() as
|
|
102
|
+
let router = new value() as Router;
|
|
96
103
|
proto?.global.router.routers.add(router);
|
|
97
104
|
return router;
|
|
98
105
|
}
|
|
@@ -87,9 +87,10 @@ export abstract class Route<ParentPath extends RoutePath = any, Path extends Rou
|
|
|
87
87
|
_Path extends RoutePath,
|
|
88
88
|
_Params extends AliasRequired<Params, PathToParamsMap<_Path>>,
|
|
89
89
|
Required extends keyof _Params extends [never] ? [] : [_Params | (() => _Params)]
|
|
90
|
-
>(path: _Path, ...required: Required):
|
|
90
|
+
>(path: _Path, ...required: Required): this;
|
|
91
91
|
alias(path: string, required?: RouteParams | (() => RouteParams)) {
|
|
92
92
|
this.paths.set(path, required)
|
|
93
|
+
return this;
|
|
93
94
|
}
|
|
94
95
|
}
|
|
95
96
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Proto, symbol_ProtoType } from "@amateras/core";
|
|
1
|
+
import { onclient, Proto, symbol_ProtoType } from "@amateras/core";
|
|
2
2
|
import { _null, isArray } from "@amateras/utils";
|
|
3
|
-
import type {
|
|
3
|
+
import type { WidgetConstructor } from "@amateras/widget";
|
|
4
4
|
import type { AsyncWidget, PageLayout } from "../types";
|
|
5
5
|
import { Page } from "./Page";
|
|
6
6
|
import { Route } from "./Route";
|
|
@@ -9,8 +9,8 @@ import type { RouteSlot } from "./RouteSlot";
|
|
|
9
9
|
export class RouteNode extends Route {
|
|
10
10
|
pages = new Map<string, Page>();
|
|
11
11
|
page: Page | null = _null;
|
|
12
|
-
#layout:
|
|
13
|
-
constructor(path: string, layout:
|
|
12
|
+
#layout: WidgetConstructor | PageLayout | AsyncWidget;
|
|
13
|
+
constructor(path: string, layout: WidgetConstructor | PageLayout | AsyncWidget) {
|
|
14
14
|
super(path);
|
|
15
15
|
this.#layout = layout;
|
|
16
16
|
}
|
|
@@ -36,12 +36,14 @@ export class RouteNode extends Route {
|
|
|
36
36
|
let layout = this.#layout;
|
|
37
37
|
let _layout;
|
|
38
38
|
if (isArray(layout)) {
|
|
39
|
-
let
|
|
39
|
+
let promise = layout[0]()
|
|
40
|
+
if (onclient()) promise.catch(() => location.reload());
|
|
41
|
+
let widget = await promise.then(mod => mod.default);
|
|
40
42
|
_layout = () => $(widget, params, () => $(page!.slot));
|
|
41
43
|
} else {
|
|
42
44
|
//@ts-ignore
|
|
43
45
|
_layout = this.#layout[symbol_ProtoType] === 'Widget' // is widget constructor
|
|
44
|
-
? () => $(this.#layout as
|
|
46
|
+
? () => $(this.#layout as WidgetConstructor, params, () => $(page!.slot))
|
|
45
47
|
: this.#layout as PageLayout;
|
|
46
48
|
}
|
|
47
49
|
$.context(Proto, slot, () => {
|
|
@@ -2,26 +2,39 @@ import { onclient } from "@amateras/core";
|
|
|
2
2
|
import { ProxyProto } from "@amateras/core";
|
|
3
3
|
import { _null } from "@amateras/utils";
|
|
4
4
|
import { Page } from "./Page";
|
|
5
|
+
import { Router } from "./Router";
|
|
5
6
|
|
|
6
7
|
export class RouteSlot extends ProxyProto {
|
|
7
8
|
page: Page | null = _null;
|
|
9
|
+
prevPage: Page | null = _null;
|
|
8
10
|
constructor() {
|
|
9
11
|
super();
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
switch(page: Page) {
|
|
13
15
|
if (this.page === page) return;
|
|
16
|
+
this.prevPage = this.page;
|
|
14
17
|
this.clear();
|
|
15
18
|
this.layout = () => $(page);
|
|
16
19
|
this.append(page);
|
|
17
|
-
if (this.page !== page) this.page?.removeNode();
|
|
18
20
|
this.page = page;
|
|
19
21
|
if (!page.builded) page.build();
|
|
20
22
|
page.updateTitle();
|
|
21
|
-
|
|
23
|
+
|
|
24
|
+
if (!this.dispatch('pageswitch', [this, Router.direction], {bubbles: true})) this.render();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
render() {
|
|
22
28
|
if (onclient()) {
|
|
29
|
+
this.prevPage?.removeNode();
|
|
23
30
|
let nodes = this.toDOM();
|
|
24
31
|
this.node?.replaceWith(...nodes);
|
|
25
32
|
}
|
|
26
33
|
}
|
|
34
|
+
|
|
35
|
+
override dispose(): void {
|
|
36
|
+
super.dispose();
|
|
37
|
+
this.page = _null;
|
|
38
|
+
this.prevPage = _null;
|
|
39
|
+
}
|
|
27
40
|
}
|
|
@@ -7,7 +7,7 @@ import type { Route } from "./Route";
|
|
|
7
7
|
import { RouteSlot } from "./RouteSlot";
|
|
8
8
|
|
|
9
9
|
type Mode = 1 | 2;
|
|
10
|
-
type RouterDicrection = 'forward' | 'back';
|
|
10
|
+
export type RouterDicrection = 'forward' | 'back';
|
|
11
11
|
|
|
12
12
|
let index = 0;
|
|
13
13
|
const [PUSH, REPLACE] = [1, 2] as const;
|
|
@@ -21,7 +21,7 @@ if (onclient()) history.scrollRestoration = 'manual';
|
|
|
21
21
|
type ScrollData = {[key: number]: { [id: string]: { x: number, y: number }}};
|
|
22
22
|
|
|
23
23
|
const scrollRecord = (e?: Event) => {
|
|
24
|
-
const data =
|
|
24
|
+
const data = Router.scrollHistory;
|
|
25
25
|
if (e) {
|
|
26
26
|
let element = e.target as HTMLElement;
|
|
27
27
|
if (element.nodeName === '#document') {
|
|
@@ -34,15 +34,16 @@ const scrollRecord = (e?: Event) => {
|
|
|
34
34
|
storage?.setItem(SCROLL_KEY, _JSON_stringify(data));
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
export class
|
|
38
|
-
direction: RouterDicrection = FORWARD;
|
|
37
|
+
export class Router extends Proto {
|
|
38
|
+
static direction: RouterDicrection = FORWARD;
|
|
39
39
|
prev: URL | null = _null;
|
|
40
|
+
url: URL | null = _null;
|
|
40
41
|
routes = new Map<string, Route>();
|
|
41
42
|
slot = new RouteSlot();
|
|
42
|
-
static routers = new Set<
|
|
43
|
+
static routers = new Set<Router>();
|
|
43
44
|
constructor() {
|
|
44
45
|
super(() => $(this.slot));
|
|
45
|
-
if (onclient())
|
|
46
|
+
if (onclient()) Router.routers.add(this);
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
set href(url: URL) {
|
|
@@ -53,8 +54,8 @@ export class RouterProto extends Proto {
|
|
|
53
54
|
if (onclient()) {
|
|
54
55
|
const resolve = () => {
|
|
55
56
|
const stateIndex = history.state?.index ?? 0;
|
|
56
|
-
if (index > stateIndex)
|
|
57
|
-
if (index < stateIndex)
|
|
57
|
+
if (index > stateIndex) Router.direction = BACK;
|
|
58
|
+
if (index < stateIndex) Router.direction = FORWARD;
|
|
58
59
|
index = stateIndex;
|
|
59
60
|
this.prev = this.href;
|
|
60
61
|
this.href = toURL(location.href);
|
|
@@ -66,7 +67,7 @@ export class RouterProto extends Proto {
|
|
|
66
67
|
capture: true,
|
|
67
68
|
passive: false
|
|
68
69
|
});
|
|
69
|
-
this.
|
|
70
|
+
this.listen('dispose', () => {
|
|
70
71
|
_removeEventListener?.('popstate', resolve);
|
|
71
72
|
_removeEventListener?.('scroll', scrollRecord, {
|
|
72
73
|
capture: true
|
|
@@ -79,6 +80,7 @@ export class RouterProto extends Proto {
|
|
|
79
80
|
async resolve(path: string | URL) {
|
|
80
81
|
if (!path) return;
|
|
81
82
|
let url = toURL(path);
|
|
83
|
+
this.global.router.scrollQueue.clear();
|
|
82
84
|
for (let [,route] of this.routes) {
|
|
83
85
|
let routes = await route.resolve(url.pathname, this.slot, {});
|
|
84
86
|
// 一旦有一个 route 解析成功就跳过剩下的 routes
|
|
@@ -98,17 +100,21 @@ export class RouterProto extends Proto {
|
|
|
98
100
|
break;
|
|
99
101
|
};
|
|
100
102
|
}
|
|
103
|
+
this.url = url;
|
|
101
104
|
// NavLink 检测匹配
|
|
102
105
|
forEach(this.global.router.navlinks, navlink => navlink.checkActive())
|
|
103
106
|
// location 变更事件触发
|
|
104
|
-
|
|
107
|
+
Router.dispatchEvent();
|
|
105
108
|
// restore scroll position
|
|
106
|
-
|
|
109
|
+
Promise.all(this.global.router.scrollQueue).then(() => {
|
|
110
|
+
// make sure after scroll queue promises resolved is still the same page
|
|
111
|
+
if (url === this.url) Router.scrollRestoration()
|
|
112
|
+
});
|
|
107
113
|
}
|
|
108
114
|
|
|
109
115
|
static open(path: string, target: string = '_self') {
|
|
110
116
|
if (toURL(path).origin !== origin) open(path, target);
|
|
111
|
-
else
|
|
117
|
+
else Router.writeState(path, PUSH, target);
|
|
112
118
|
}
|
|
113
119
|
|
|
114
120
|
static forward() {
|
|
@@ -120,7 +126,7 @@ export class RouterProto extends Proto {
|
|
|
120
126
|
}
|
|
121
127
|
|
|
122
128
|
static replace(path: string) {
|
|
123
|
-
|
|
129
|
+
Router.writeState(path, REPLACE);
|
|
124
130
|
}
|
|
125
131
|
|
|
126
132
|
static get scrollData(): ScrollData[number] {
|
|
@@ -133,14 +139,17 @@ export class RouterProto extends Proto {
|
|
|
133
139
|
|
|
134
140
|
static scrollRestoration() {
|
|
135
141
|
if (onclient()) {
|
|
136
|
-
let scrollData =
|
|
142
|
+
let scrollData = Router.scrollData ?? {x: 0, y: 0};
|
|
137
143
|
let scrollDataElements = _Object_entries(scrollData);
|
|
138
144
|
if (scrollDataElements.length)
|
|
139
145
|
forEach(scrollDataElements, ([id, {x, y}]) => {
|
|
140
146
|
if (id === '#document') window.scrollTo(x, y);
|
|
141
|
-
else document.
|
|
147
|
+
else document.getElementById(id)?.scrollTo(x, y)
|
|
142
148
|
});
|
|
143
|
-
else
|
|
149
|
+
else {
|
|
150
|
+
document.querySelectorAll('*').forEach(el => el.scrollTo(0, 0))
|
|
151
|
+
window.scrollTo(0, 0)
|
|
152
|
+
}
|
|
144
153
|
}
|
|
145
154
|
}
|
|
146
155
|
|
|
@@ -152,7 +161,7 @@ export class RouterProto extends Proto {
|
|
|
152
161
|
if (mode === PUSH) index++;
|
|
153
162
|
if (onclient()) scrollRecord();
|
|
154
163
|
forEach(this.routers, router => {
|
|
155
|
-
|
|
164
|
+
Router.direction = FORWARD;
|
|
156
165
|
if (onclient()) {
|
|
157
166
|
router.prev = toURL(location.href);
|
|
158
167
|
history[mode === PUSH ? 'pushState' : 'replaceState']({index}, '', url);
|
|
@@ -160,7 +169,7 @@ export class RouterProto extends Proto {
|
|
|
160
169
|
router.href = url;
|
|
161
170
|
router.resolve(path)
|
|
162
171
|
})
|
|
163
|
-
|
|
172
|
+
Router.dispatchEvent();
|
|
164
173
|
}
|
|
165
174
|
|
|
166
175
|
private static dispatchEvent() {
|
|
@@ -175,7 +184,7 @@ declare global {
|
|
|
175
184
|
}
|
|
176
185
|
|
|
177
186
|
|
|
178
|
-
export interface
|
|
187
|
+
export interface Router {
|
|
179
188
|
route<_Path extends RoutePath, Props>(
|
|
180
189
|
path: ValidatePath<_Path, Props, _Path>,
|
|
181
190
|
widget: Widget<Props>,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { symbol_ProtoType } from "@amateras/core";
|
|
2
|
-
import {
|
|
2
|
+
import { Router } from "./Router";
|
|
3
3
|
|
|
4
|
-
export type RouterHandle = ($$:
|
|
4
|
+
export type RouterHandle = ($$: Router) => void;
|
|
5
5
|
|
|
6
|
-
export interface
|
|
7
|
-
new():
|
|
6
|
+
export interface RouterConstructor {
|
|
7
|
+
new(): Router;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export const RouterConstructor = (handle: RouterHandle) => {
|
|
11
|
-
return class extends
|
|
11
|
+
return class extends Router {
|
|
12
12
|
static override [symbol_ProtoType] = 'Router';
|
|
13
13
|
constructor() {
|
|
14
14
|
super();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RouteSlot } from "#structure/RouteSlot";
|
|
2
|
-
import type {
|
|
2
|
+
import type { WidgetConstructor } from "@amateras/widget";
|
|
3
3
|
|
|
4
4
|
export type RoutePath = string;
|
|
5
5
|
|
|
@@ -7,7 +7,7 @@ export type RouteParams = { [key: string]: string }
|
|
|
7
7
|
|
|
8
8
|
export type PageLayout<Path extends RoutePath = any> = (context: { params: PathToParamsMap<Path>, slot: RouteSlot }) => void;
|
|
9
9
|
|
|
10
|
-
export type AsyncWidget<Params = any> = [() => Promise<{ default:
|
|
10
|
+
export type AsyncWidget<Params = any> = [() => Promise<{ default: WidgetConstructor<Params> }>]
|
|
11
11
|
|
|
12
12
|
export type PathToParamsUnion<T extends RoutePath> =
|
|
13
13
|
T extends `${infer _Start}:${infer Param}/${infer Rest}`
|
|
@@ -1,34 +1,12 @@
|
|
|
1
1
|
# amateras/signal
|
|
2
2
|
|
|
3
|
-
##
|
|
4
|
-
|
|
3
|
+
## Import
|
|
5
4
|
```ts
|
|
6
5
|
import 'amateras';
|
|
7
6
|
import 'amateras/signal';
|
|
8
|
-
|
|
9
|
-
// define a signal with value 0
|
|
10
|
-
const count$ = $.signal(0);
|
|
11
|
-
|
|
12
|
-
// this variable will be auto recalculate when count$ changes
|
|
13
|
-
const doubleCount$ = $.compute(() => count$() * 2);
|
|
14
|
-
|
|
15
|
-
// the console message will fired when count$ changes
|
|
16
|
-
$.effect(() => console.log( count$() ))
|
|
17
|
-
|
|
18
|
-
$(document.body).content([
|
|
19
|
-
// Display Counts
|
|
20
|
-
$('p').content( $`Counts: ${count$}` ),
|
|
21
|
-
|
|
22
|
-
// Display Double Counts
|
|
23
|
-
$('p').content( $`Double Counts: ${doubleCount$}` ),
|
|
24
|
-
|
|
25
|
-
// Create a button that make counts plus 1 on click
|
|
26
|
-
$('button').content('Add Count').on('click', () => count$.set(value => value + 1))
|
|
27
|
-
])
|
|
28
7
|
```
|
|
29
8
|
|
|
30
9
|
## Read and Write
|
|
31
|
-
|
|
32
10
|
```ts
|
|
33
11
|
const number$ = $.signal(0);
|
|
34
12
|
const string$ = $.singal('');
|
|
@@ -48,21 +26,22 @@ boolean$(); // true
|
|
|
48
26
|
object$(); // { number: 42 }
|
|
49
27
|
```
|
|
50
28
|
|
|
51
|
-
##
|
|
52
|
-
|
|
29
|
+
## Set as Attribute Value
|
|
53
30
|
```ts
|
|
54
31
|
const src$ = $.signal('/image-1.png');
|
|
55
32
|
|
|
56
|
-
$(
|
|
33
|
+
$('div', $$ => {
|
|
57
34
|
// you can set signal variable in attribute
|
|
58
|
-
$('img'
|
|
35
|
+
$('img', { src: src$ }),
|
|
59
36
|
|
|
60
|
-
$('button'
|
|
61
|
-
|
|
37
|
+
$('button', $$ => {
|
|
38
|
+
$$.on('click', () => src$.set('/image-2.png'))
|
|
39
|
+
$`Change Image`
|
|
40
|
+
})
|
|
41
|
+
})
|
|
62
42
|
```
|
|
63
43
|
|
|
64
|
-
##
|
|
65
|
-
|
|
44
|
+
## Signal Object
|
|
66
45
|
```ts
|
|
67
46
|
const user$ = $.signal({
|
|
68
47
|
name: 'Amateras',
|
|
@@ -73,21 +52,22 @@ const user$ = $.signal({
|
|
|
73
52
|
}
|
|
74
53
|
})
|
|
75
54
|
|
|
76
|
-
$(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
55
|
+
user$.name$() // "Amateras"
|
|
56
|
+
user$.age$() // 16
|
|
57
|
+
user$.avatar$.url() // "/amateras/avatar.png"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Compute and Effect
|
|
61
|
+
```ts
|
|
62
|
+
const count$ = $.signal(0);
|
|
63
|
+
const double$ = $.compute(() => count$() + 1);
|
|
64
|
+
|
|
65
|
+
$.effect(() => {
|
|
66
|
+
console.log(`Count is ${count$()}`)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
$('button', $$ => {
|
|
70
|
+
$$.on('click', () => count$.set(value => value + 1))
|
|
71
|
+
$`You have clicked this button in half of ${double$} times.`
|
|
72
|
+
})
|
|
93
73
|
```
|