amateras 0.10.0 → 0.10.2
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 +29 -25
- package/build/core.js +1 -0
- package/build/css.js +1 -0
- package/build/for.js +1 -0
- package/build/i18n.js +1 -0
- package/build/idb.js +1 -0
- package/build/if.js +1 -0
- package/build/import-map.js +1 -0
- package/build/markdown.js +1 -0
- package/build/match.js +1 -0
- package/build/meta.js +1 -0
- package/build/prefetch.js +1 -0
- package/build/router.js +1 -0
- package/build/signal.js +1 -0
- package/build/ui.js +1 -0
- package/build/widget.js +1 -0
- package/package.json +7 -5
- package/packages/core/package.json +19 -0
- package/packages/core/src/env.browser.ts +21 -0
- package/packages/core/src/env.node.ts +21 -0
- package/packages/core/src/global.ts +5 -0
- package/packages/core/src/index.ts +184 -0
- package/packages/core/src/lib/hmr.ts +145 -0
- package/packages/core/src/lib/symbols.ts +2 -0
- package/packages/core/src/structure/ElementProto.ts +95 -0
- package/packages/core/src/structure/GlobalState.ts +9 -0
- package/packages/core/src/structure/NodeProto.ts +18 -0
- package/packages/core/src/structure/Proto.ts +90 -0
- package/packages/core/src/structure/ProxyProto.ts +20 -0
- package/packages/core/src/structure/TextProto.ts +22 -0
- package/packages/core/src/structure/WidgetEvent.ts +17 -0
- package/packages/css/README.md +128 -0
- package/packages/css/package.json +15 -0
- package/packages/css/src/ext/colors/amber.ts +25 -0
- package/packages/css/src/ext/colors/blackwhite.ts +13 -0
- package/packages/css/src/ext/colors/blue.ts +25 -0
- package/packages/css/src/ext/colors/cyan.ts +25 -0
- package/packages/css/src/ext/colors/emerald.ts +25 -0
- package/packages/css/src/ext/colors/fuchsia.ts +25 -0
- package/packages/css/src/ext/colors/gray.ts +25 -0
- package/packages/css/src/ext/colors/green.ts +25 -0
- package/packages/css/src/ext/colors/indigo.ts +25 -0
- package/packages/css/src/ext/colors/lime.ts +25 -0
- package/packages/css/src/ext/colors/neutral.ts +25 -0
- package/packages/css/src/ext/colors/orange.ts +25 -0
- package/packages/css/src/ext/colors/pink.ts +25 -0
- package/packages/css/src/ext/colors/purple.ts +25 -0
- package/packages/css/src/ext/colors/red.ts +25 -0
- package/packages/css/src/ext/colors/rose.ts +25 -0
- package/packages/css/src/ext/colors/sky.ts +25 -0
- package/packages/css/src/ext/colors/slate.ts +25 -0
- package/packages/css/src/ext/colors/stone.ts +25 -0
- package/packages/css/src/ext/colors/teal.ts +25 -0
- package/packages/css/src/ext/colors/violet.ts +25 -0
- package/packages/css/src/ext/colors/yellow.ts +25 -0
- package/packages/css/src/ext/colors/zinc.ts +25 -0
- package/packages/css/src/ext/colors.ts +23 -0
- package/packages/css/src/ext/keyframes.ts +37 -0
- package/packages/css/src/ext/property.ts +68 -0
- package/packages/css/src/ext/variable.ts +51 -0
- package/packages/css/src/index.ts +103 -0
- package/packages/css/src/lib/cache.ts +27 -0
- package/packages/css/src/lib/colorAssign.ts +6 -0
- package/packages/css/src/lib/createRule.ts +31 -0
- package/packages/css/src/lib/utils.ts +1 -0
- package/packages/css/src/structure/$CSS.ts +4 -0
- package/packages/css/src/structure/$CSSKeyframes.ts +13 -0
- package/packages/css/src/structure/$CSSProperty.ts +21 -0
- package/packages/css/src/structure/$CSSRule.ts +39 -0
- package/packages/css/src/structure/$CSSVariable.ts +34 -0
- package/packages/css/src/types.ts +300 -0
- package/packages/for/package.json +15 -0
- package/packages/for/src/global.ts +7 -0
- package/packages/for/src/index.ts +15 -0
- package/packages/for/src/structure/For.ts +74 -0
- package/packages/hmr/package.json +13 -0
- package/packages/hmr/src/index.ts +27 -0
- package/packages/i18n/README.md +73 -0
- package/packages/i18n/package.json +15 -0
- package/packages/i18n/src/index.ts +78 -0
- package/packages/i18n/src/structure/I18n.ts +51 -0
- package/packages/i18n/src/structure/I18nDictionary.ts +31 -0
- package/packages/i18n/src/structure/I18nTranslation.ts +51 -0
- package/packages/i18n/src/types.ts +77 -0
- package/packages/idb/README.md +127 -0
- package/packages/idb/package.json +16 -0
- package/packages/idb/src/core.ts +6 -0
- package/packages/idb/src/index.ts +17 -0
- package/packages/idb/src/lib/$IDBRequest.ts +8 -0
- package/packages/idb/src/structure/$IDB.ts +63 -0
- package/packages/idb/src/structure/$IDBCursor.ts +34 -0
- package/packages/idb/src/structure/$IDBIndex.ts +48 -0
- package/packages/idb/src/structure/$IDBStore.ts +103 -0
- package/packages/idb/src/structure/$IDBStoreBase.ts +30 -0
- package/packages/idb/src/structure/$IDBTransaction.ts +38 -0
- package/packages/idb/src/structure/builder/$IDBBuilder.ts +229 -0
- package/packages/idb/src/structure/builder/$IDBStoreBuilder.ts +100 -0
- package/packages/if/package.json +15 -0
- package/packages/if/src/global.ts +15 -0
- package/packages/if/src/index.ts +51 -0
- package/packages/if/src/structure/Condition.ts +44 -0
- package/packages/if/src/structure/ConditionStatement.ts +25 -0
- package/packages/if/src/structure/Else.ts +6 -0
- package/packages/if/src/structure/ElseIf.ts +6 -0
- package/packages/if/src/structure/If.ts +6 -0
- package/packages/markdown/README.md +53 -0
- package/packages/markdown/package.json +15 -0
- package/packages/markdown/src/index.ts +3 -0
- package/packages/markdown/src/lib/type.ts +26 -0
- package/packages/markdown/src/lib/util.ts +21 -0
- package/packages/markdown/src/structure/Markdown.ts +57 -0
- package/packages/markdown/src/structure/MarkdownLexer.ts +111 -0
- package/packages/markdown/src/structure/MarkdownParser.ts +34 -0
- package/packages/markdown/src/syntax/alert.ts +46 -0
- package/packages/markdown/src/syntax/blockquote.ts +35 -0
- package/packages/markdown/src/syntax/bold.ts +11 -0
- package/packages/markdown/src/syntax/code.ts +11 -0
- package/packages/markdown/src/syntax/codeblock.ts +44 -0
- package/packages/markdown/src/syntax/heading.ts +14 -0
- package/packages/markdown/src/syntax/horizontalRule.ts +11 -0
- package/packages/markdown/src/syntax/image.ts +23 -0
- package/packages/markdown/src/syntax/italic.ts +11 -0
- package/packages/markdown/src/syntax/link.ts +46 -0
- package/packages/markdown/src/syntax/list.ts +121 -0
- package/packages/markdown/src/syntax/table.ts +67 -0
- package/packages/markdown/src/syntax/text.ts +19 -0
- package/packages/match/package.json +15 -0
- package/packages/match/src/global.ts +14 -0
- package/packages/match/src/index.ts +33 -0
- package/packages/match/src/structure/Case.ts +15 -0
- package/packages/match/src/structure/Default.ts +12 -0
- package/packages/match/src/structure/Match.ts +78 -0
- package/packages/meta/package.json +14 -0
- package/packages/meta/src/index.ts +36 -0
- package/packages/meta/src/lib/resolveMeta.ts +27 -0
- package/packages/meta/src/types.ts +36 -0
- package/packages/prefetch/package.json +14 -0
- package/packages/prefetch/src/index.ts +70 -0
- package/packages/router/README.md +18 -0
- package/packages/router/package.json +16 -0
- package/packages/router/src/global.ts +22 -0
- package/packages/router/src/index.ts +106 -0
- package/packages/router/src/structure/Link.ts +17 -0
- package/packages/router/src/structure/NavLink.ts +19 -0
- package/packages/router/src/structure/Page.ts +30 -0
- package/packages/router/src/structure/Route.ts +123 -0
- package/packages/router/src/structure/RouteGroup.ts +24 -0
- package/packages/router/src/structure/RouteNode.ts +54 -0
- package/packages/router/src/structure/RouteSlot.ts +34 -0
- package/packages/router/src/structure/Router.ts +192 -0
- package/packages/router/src/structure/RouterConstructor.ts +18 -0
- package/packages/router/src/types.ts +41 -0
- package/packages/signal/README.md +93 -0
- package/packages/signal/package.json +15 -0
- package/packages/signal/src/index.ts +97 -0
- package/packages/signal/src/lib/track.ts +18 -0
- package/packages/signal/src/structure/Signal.ts +59 -0
- package/packages/ui/package.json +14 -0
- package/packages/ui/src/index.ts +4 -0
- package/packages/ui/src/lib/slideshowAnimations.ts +39 -0
- package/packages/ui/src/structure/Radio.ts +77 -0
- package/packages/ui/src/structure/Slide.ts +11 -0
- package/packages/ui/src/structure/Slideshow.ts +99 -0
- package/packages/utils/package.json +18 -0
- package/packages/utils/src/global.ts +39 -0
- package/packages/utils/src/index.bun.ts +3 -0
- package/packages/utils/src/index.ts +2 -0
- package/packages/utils/src/lib/debugger.ts +14 -0
- package/packages/utils/src/lib/utils.ts +119 -0
- package/packages/utils/src/structure/UID.ts +18 -0
- package/packages/widget/README.md +29 -0
- package/packages/widget/package.json +14 -0
- package/packages/widget/src/index.ts +82 -0
- package/packages/widget/src/structure/Widget.ts +42 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { ElementProto } from "@amateras/core";
|
|
2
|
+
import { _null } from "@amateras/utils";
|
|
3
|
+
import { Slide } from "./Slide";
|
|
4
|
+
|
|
5
|
+
export interface SlideshowOptions {
|
|
6
|
+
/**第一个播放的位置 */
|
|
7
|
+
index?: number;
|
|
8
|
+
/**Slide 间隔时间,单位为秒 */
|
|
9
|
+
interval?: number;
|
|
10
|
+
/**是否自动播放 */
|
|
11
|
+
autoplay?: boolean;
|
|
12
|
+
/**动画函数 */
|
|
13
|
+
animation?: SlideshowAnimationHandle;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class Slideshow extends ElementProto {
|
|
17
|
+
declare __child__: Slide;
|
|
18
|
+
slide: Slide | null = _null;
|
|
19
|
+
index: number;
|
|
20
|
+
timer: NodeJS.Timeout | null = _null;
|
|
21
|
+
interval: number;
|
|
22
|
+
autoplay: boolean;
|
|
23
|
+
animation: SlideshowAnimationHandle | null;
|
|
24
|
+
#passed = 0;
|
|
25
|
+
constructor({index, interval, autoplay, animation, ...props}: $.Props<SlideshowOptions>, layout?: $.Layout<Slideshow>) {
|
|
26
|
+
super('slideshow', props, layout);
|
|
27
|
+
this.index = index ?? 0;
|
|
28
|
+
this.interval = interval ?? 5;
|
|
29
|
+
this.autoplay = autoplay ?? false;
|
|
30
|
+
this.animation = animation ?? _null;
|
|
31
|
+
this.disposers.add(() => this.pause());
|
|
32
|
+
this.ondom(() => {
|
|
33
|
+
if (this.autoplay) this.play();
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static {
|
|
38
|
+
$.style(Slideshow, 'slideshow{display:block;position:relative;overflow:clip}')
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
override build(): this {
|
|
42
|
+
super.build();
|
|
43
|
+
this.switch(this.index);
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
override toString(): string {
|
|
48
|
+
return this.parseHTML({children: this.slide?.toString()});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
override toDOM(children = true): HTMLElement[] {
|
|
52
|
+
super.toDOM(false);
|
|
53
|
+
if (children && this.slide) this.node?.append(...this.slide.toDOM());
|
|
54
|
+
return [this.node!]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
play() {
|
|
58
|
+
this.timer = setInterval(() => {
|
|
59
|
+
this.#passed++;
|
|
60
|
+
if (this.#passed >= this.interval * 100) {
|
|
61
|
+
this.next();
|
|
62
|
+
this.#passed = 0;
|
|
63
|
+
}
|
|
64
|
+
}, 10);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
pause() {
|
|
68
|
+
if (this.timer) clearTimeout(this.timer);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
next() {
|
|
72
|
+
let size = this.children.length;
|
|
73
|
+
let nextIndex = this.index + 1;
|
|
74
|
+
if (nextIndex >= size) nextIndex = 0;
|
|
75
|
+
this.switch(nextIndex);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
prev() {
|
|
79
|
+
let size = this.children.length;
|
|
80
|
+
let prevIndex = this.index - 1;
|
|
81
|
+
if (prevIndex <= 0) prevIndex = size - 1;
|
|
82
|
+
this.switch(prevIndex);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
switch(index: number) {
|
|
86
|
+
this.index = index;
|
|
87
|
+
let slide = this.children.at(index);
|
|
88
|
+
if (this.slide === slide) return;
|
|
89
|
+
if (!slide) return;
|
|
90
|
+
if (this.animation) this.animation(this, slide, this.slide);
|
|
91
|
+
else {
|
|
92
|
+
slide.parent = this;
|
|
93
|
+
this.slide = slide;
|
|
94
|
+
this.node?.replaceChildren(...slide.toDOM());
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export type SlideshowAnimationHandle = (slideshow: Slideshow, newSlide: Slide, oldSlide: Slide | null) => void;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@amateras/utils",
|
|
3
|
+
"peerDependencies": {
|
|
4
|
+
"@amateras/core": "workspace:*"
|
|
5
|
+
},
|
|
6
|
+
"imports": {
|
|
7
|
+
"#structure/*": "./src/structure/*.ts",
|
|
8
|
+
"#lib/*": "./src/lib/*.ts",
|
|
9
|
+
"#node/*": "./src/node/*.ts"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"browser": "./src/index.ts",
|
|
14
|
+
"bun": "./src/index.bun.ts",
|
|
15
|
+
"default": "./src/index.ts"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
type Nullish = null | undefined;
|
|
3
|
+
type OrArray<T> = T | T[];
|
|
4
|
+
type OrMatrix<T> = T | OrMatrix<T>[];
|
|
5
|
+
type OrPromise<T> = T | Promise<T>;
|
|
6
|
+
type OrNullish<T> = T | Nullish;
|
|
7
|
+
type Constructor<T = any> = abstract new (...args: any[]) => T;
|
|
8
|
+
type Mutable<T> = {
|
|
9
|
+
-readonly [P in keyof T]: T[P];
|
|
10
|
+
}
|
|
11
|
+
type AsyncFunction<T> = (...args: any[]) => Promise<T>;
|
|
12
|
+
type Ok<D> = [data: D, err: null];
|
|
13
|
+
type Err<E> = [data: null, err: E]
|
|
14
|
+
type Result<D, E> = Ok<D> | Err<E>
|
|
15
|
+
type Repeat<T, N extends number, Acc extends T[] = []> =
|
|
16
|
+
Acc['length'] extends 500
|
|
17
|
+
? T[]
|
|
18
|
+
: Acc['length'] extends N
|
|
19
|
+
? Acc
|
|
20
|
+
: Repeat<T, N, [...Acc, T]>;
|
|
21
|
+
type Prettify<T> = {
|
|
22
|
+
[K in keyof T]: T[K];
|
|
23
|
+
} & {};
|
|
24
|
+
type Narrow<T> = T extends boolean ? boolean : T;
|
|
25
|
+
type ValueOf<T> = T[keyof T];
|
|
26
|
+
type RequiredKeys<T> = {
|
|
27
|
+
[K in keyof T]-?: {} extends Pick<T, K> ? never : K;
|
|
28
|
+
}[keyof T];
|
|
29
|
+
type RemoveIndexSignature<T> = {
|
|
30
|
+
[K in keyof T as string extends K
|
|
31
|
+
? never
|
|
32
|
+
: number extends K
|
|
33
|
+
? never
|
|
34
|
+
: symbol extends K
|
|
35
|
+
? never
|
|
36
|
+
: K
|
|
37
|
+
]: T[K];
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
declare global {
|
|
3
|
+
export import debug = Debug
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export namespace Debug {
|
|
7
|
+
export const generateHeapsnapshot = async () => {
|
|
8
|
+
let snapshot = Bun.generateHeapSnapshot('v8');
|
|
9
|
+
let size = await Bun.write(`./heapsnapshot/${new Date().toISOString()}.heapsnapshot`, snapshot);
|
|
10
|
+
return size
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
global.debug = Debug;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { onclient } from '@amateras/core';
|
|
2
|
+
import '../global';
|
|
3
|
+
|
|
4
|
+
// Value
|
|
5
|
+
export const _null = null;
|
|
6
|
+
export const _undefined = undefined;
|
|
7
|
+
// Object
|
|
8
|
+
const _Object = Object;
|
|
9
|
+
export const _Object_fromEntries = _Object.fromEntries;
|
|
10
|
+
export const _Object_entries = _Object.entries;
|
|
11
|
+
export const _Object_assign = _Object.assign;
|
|
12
|
+
export const _Object_values = _Object.values;
|
|
13
|
+
export const _Object_defineProperty = _Object.defineProperty;
|
|
14
|
+
export const _Object_getOwnPropertyDescriptors = _Object.getOwnPropertyDescriptors;
|
|
15
|
+
// Array
|
|
16
|
+
const _Array = Array;
|
|
17
|
+
export const _Array_from = _Array.from;
|
|
18
|
+
interface forEach {
|
|
19
|
+
<T>(arr: Array<T>, fn: (value: T, index: number, array: Array<T>) => Promise<void>): Promise<void>;
|
|
20
|
+
<T>(arr: Array<T>, fn: (value: T, index: number, array: Array<T>) => void): void;
|
|
21
|
+
<T>(set: Set<T>, fn: (value: T, index: number, set: Set<T>) => Promise<void>): void;
|
|
22
|
+
<T>(set: Set<T>, fn: (value: T, index: number, set: Set<T>) => void): void;
|
|
23
|
+
<T extends WeakKey>(set: WeakSet<T>, fn: (value: T, index: number, set: WeakSet<T>) => Promise<void>): void;
|
|
24
|
+
<T extends WeakKey>(set: WeakSet<T>, fn: (value: T, index: number, set: WeakSet<T>) => void): void;
|
|
25
|
+
<T>(list: Array<T> | Set<T>, fn: (value: T, index: number, set: Array<T> | Set<T>) => Promise<void>): void;
|
|
26
|
+
<T>(list: Array<T> | Set<T>, fn: (value: T, index: number, set: Array<T> | Set<T>) => void): void;
|
|
27
|
+
<K, V>(map: Map<K, V>, fn: (value: [K, V], index: number, map: Map<K, V>) => Promise<void>): void;
|
|
28
|
+
<K, V>(map: Map<K, V>, fn: (value: [K, V], index: number, map: Map<K, V>) => void): void;
|
|
29
|
+
<N extends Node>(set: NodeListOf<N>, fn: (value: N, index: number, parent: NodeListOf<N>) => Promise<void>): void;
|
|
30
|
+
<N extends Node>(set: NodeListOf<N>, fn: (value: N, index: number, parent: NodeListOf<N>) => void): void;
|
|
31
|
+
}
|
|
32
|
+
export const forEach: forEach = async (arr: any, fn: any) => {
|
|
33
|
+
let i = 0;
|
|
34
|
+
let asyncHandle = async () => { for (let item of arr) { await fn(item, i, arr); i++; } };
|
|
35
|
+
let handle = () => { for (let item of arr) { fn(item, i, arr); i++; } };
|
|
36
|
+
return isAsyncFunction(fn) ? asyncHandle() : handle();
|
|
37
|
+
};
|
|
38
|
+
interface map {
|
|
39
|
+
<T, R>(arr: Array<T>, fn: (value: T, index: number, array: Array<T>) => R): R[];
|
|
40
|
+
<T, R>(set: Set<T>, fn: (value: T, index: number, set: Set<T>) => R): R[];
|
|
41
|
+
<T extends WeakKey>(set: WeakSet<T>, fn: (value: T, index: number, set: WeakSet<T>) => Promise<void>): T[];
|
|
42
|
+
<T extends WeakKey>(set: WeakSet<T>, fn: (value: T, index: number, set: WeakSet<T>) => void): T[];
|
|
43
|
+
<T, R>(list: Array<T> | Set<T>, fn: (value: T, index: number, set: Array<T> | Set<T>) => R): R[];
|
|
44
|
+
<K, V, R>(map: Map<K, V>, fn: (value: [K, V], index: number, map: Map<K, V>) => R): R[];
|
|
45
|
+
<N extends Node, R>(set: NodeListOf<N>, fn: (value: N, index: number, parent: NodeListOf<N>) => R): R[];
|
|
46
|
+
}
|
|
47
|
+
export const map: map = (arr: any, fn: any) => _Array_from(arr).map(fn);
|
|
48
|
+
|
|
49
|
+
// type check
|
|
50
|
+
export const _typeof = (target: any, type: 'string' | 'number' | 'object' | 'boolean' | 'function' | 'bigint' | 'symbol' | 'undefined') => typeof target === type;
|
|
51
|
+
export const isEqual = <T, V>(target: T, args: V[]): target is V & T => args.includes(target as any);
|
|
52
|
+
export const isString = (target: any): target is string => _typeof(target, 'string');
|
|
53
|
+
export const isBoolean = (target: any): target is boolean => _typeof(target, 'boolean');
|
|
54
|
+
export const isNumber = (target: any): target is number => _typeof(target, 'number');
|
|
55
|
+
export const isObject = (target: any): target is object => _typeof(target, 'object');
|
|
56
|
+
export const isFunction = (target: any): target is Function => _typeof(target, 'function');
|
|
57
|
+
export const isAsyncFunction = (target: any): target is AsyncFunction<Awaited<ReturnType<typeof target>>> => _instanceof(target, (async () => 0).constructor as any)
|
|
58
|
+
export const isUndefined = (target: any): target is undefined => target === undefined;
|
|
59
|
+
export const isNull = (target: any): target is null => target === _null;
|
|
60
|
+
export const isArray = _Array.isArray;
|
|
61
|
+
export const _instanceof = <T extends (abstract new (...args: any[]) => any)[]>(target: any, ...instance: T): target is InstanceType<T[number]> => !!instance.find(i => target instanceof i);
|
|
62
|
+
export const is = <T extends abstract new (...args: any[]) => any>(target: any, instance: T): InstanceType<T> | null => _instanceof(target, instance) ? target : _null;
|
|
63
|
+
// JSON
|
|
64
|
+
export const _JSON_stringify = JSON.stringify;
|
|
65
|
+
export const _JSON_parse = JSON.parse;
|
|
66
|
+
// String
|
|
67
|
+
export const startsWith = (target: string, ...str: string[]) => !!str.find(s => target.startsWith(s));
|
|
68
|
+
// String & Array
|
|
69
|
+
interface slice {
|
|
70
|
+
(target: string, start?: number, end?: number): string;
|
|
71
|
+
<T>(target: Array<T>, start?: number, end?: number): T[];
|
|
72
|
+
}
|
|
73
|
+
export const slice: slice = (target: any, start?: number, end?: number) => target.slice(start, end);
|
|
74
|
+
// Function
|
|
75
|
+
export const _bind = <T extends Function>(target: T, obj: Object): T => target.bind(obj);
|
|
76
|
+
// Promise
|
|
77
|
+
export const _Promise = Promise;
|
|
78
|
+
|
|
79
|
+
// utils function
|
|
80
|
+
export const debounce = () => {
|
|
81
|
+
let timer: number;
|
|
82
|
+
return (fn: Function, timeout: number) => {
|
|
83
|
+
if (timer) clearTimeout(timer);
|
|
84
|
+
timer = setTimeout(fn, timeout);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const LOWER = 'abcdefghijklmnopqrstuvwxyz';
|
|
89
|
+
const UPPER = LOWER.toUpperCase();
|
|
90
|
+
export interface RandomIdOptions {
|
|
91
|
+
length?: number;
|
|
92
|
+
lettercase?: 'any' | 'lower' | 'upper';
|
|
93
|
+
}
|
|
94
|
+
export const randomId = (options?: RandomIdOptions): string => {
|
|
95
|
+
options = {length: 5, lettercase: 'any', ...options};
|
|
96
|
+
const char = options.lettercase === 'any' ? LOWER + UPPER : options.lettercase === 'lower' ? LOWER : UPPER;
|
|
97
|
+
return _Array_from({length: options.length as number}, (_, i) => char[Math.round(Math.random() * char.length)]).join('');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export const sleep = async (ms: number) => new _Promise(resolve => setTimeout(resolve, ms));
|
|
101
|
+
|
|
102
|
+
export const toArray = <T>(item: OrArray<T>): T[] => _instanceof(item, Array) ? item : [item];
|
|
103
|
+
|
|
104
|
+
export const trycatch = <D>(callback: () => D): Result<D, Error> => {
|
|
105
|
+
try {
|
|
106
|
+
return [callback(), _null];
|
|
107
|
+
} catch (err) {
|
|
108
|
+
return [_null, _instanceof(err, Error) ? err : new Error(_JSON_stringify(err))];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export const uppercase = (str: string, start?: number, end?: number) => `${slice(str, 0, start)}${slice(str, start, end).toUpperCase()}${end ? slice(str, end) : ''}`
|
|
113
|
+
const _URL = URL;
|
|
114
|
+
export const toURL = (path: string | URL) => {
|
|
115
|
+
if (_instanceof(path, _URL)) return path;
|
|
116
|
+
if (startsWith(path, 'http')) return new _URL(path);
|
|
117
|
+
if (onclient()) return new _URL(startsWith(path, origin) ? path : origin+path);
|
|
118
|
+
else return new _URL('https://localhost' + path)
|
|
119
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { randomId, type RandomIdOptions } from "#lib/utils";
|
|
2
|
+
import type { Proto } from "@amateras/core";
|
|
3
|
+
|
|
4
|
+
export class UID {
|
|
5
|
+
static map = new Map<string, Set<string>>();
|
|
6
|
+
|
|
7
|
+
static generate(key: string, options?: RandomIdOptions): string {
|
|
8
|
+
const set = UID.map.get(key) ?? new Set();
|
|
9
|
+
const id = randomId(options);
|
|
10
|
+
if (set.has(id)) return UID.generate(key);
|
|
11
|
+
return id;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
static persistInProto(proto: Proto, key: string, options?: RandomIdOptions) {
|
|
15
|
+
const id = UID.generate(key, options);
|
|
16
|
+
proto.disposers.add(() => UID.map.get(key)?.delete(id))
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Amateras Widget
|
|
2
|
+
Widget 是组件化需要的重要模块,能够帮助开发者便利地编写组件代码。每个组件能够保存自己的数据仓库(Store),并且能将数据传达到指定的子组件中。
|
|
3
|
+
|
|
4
|
+
## 使用方式
|
|
5
|
+
使用组件函数 `$.widget` 定义组件原型构造器(Widget Constructor)。
|
|
6
|
+
```ts
|
|
7
|
+
import 'amateras';
|
|
8
|
+
import 'amateras/widget';
|
|
9
|
+
|
|
10
|
+
// 定义组件构造器
|
|
11
|
+
const App = $.widget((props: {name: string}) => ({
|
|
12
|
+
// 组建的模板函数
|
|
13
|
+
layout() {
|
|
14
|
+
$('h1', () => `Hello ${props.name}!`)
|
|
15
|
+
}
|
|
16
|
+
}))
|
|
17
|
+
|
|
18
|
+
// 创建组件
|
|
19
|
+
const $app = $(App, {name: 'Amateras'});
|
|
20
|
+
|
|
21
|
+
// 构建并渲染组件
|
|
22
|
+
$.render($app, () => document.body);
|
|
23
|
+
|
|
24
|
+
// 输出:<h1>Hello Amateras!</h1>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 文档
|
|
28
|
+
1. [组件基础](/docs/Widget.md)
|
|
29
|
+
2. [组件数据仓库](/docs/Widget.md)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@amateras/widget",
|
|
3
|
+
"peerDependencies": {
|
|
4
|
+
"@amateras/core": "workspace:*",
|
|
5
|
+
"@amateras/utils": "workspace:*"
|
|
6
|
+
},
|
|
7
|
+
"imports": {
|
|
8
|
+
"#structure/*": "./src/structure/*.ts",
|
|
9
|
+
"#lib/*": "./src/lib/*.ts"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": "./src/index.ts"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Proto } from "@amateras/core";
|
|
2
|
+
import { _Object_assign } from "@amateras/utils";
|
|
3
|
+
import { WidgetConstructor, type Widget } from "./structure/Widget";
|
|
4
|
+
|
|
5
|
+
export type WidgetChildrenLayout<$$ extends Constructor | null> = (proto: $$ extends Constructor ? InstanceType<$$> : undefined) => void;
|
|
6
|
+
export type WidgetConstructLayout<$$ extends Constructor | null, Store> = (
|
|
7
|
+
context: {
|
|
8
|
+
store: Store,
|
|
9
|
+
children: (
|
|
10
|
+
...args:
|
|
11
|
+
$$ extends Constructor
|
|
12
|
+
? [proto: InstanceType<$$>]
|
|
13
|
+
: []
|
|
14
|
+
) => void
|
|
15
|
+
}
|
|
16
|
+
) => void;
|
|
17
|
+
|
|
18
|
+
type WidgetInitLayoutStore<ParentStore, Store> =
|
|
19
|
+
ParentStore extends Record<string, any>
|
|
20
|
+
? Store extends Record<string, any>
|
|
21
|
+
? Prettify<ParentStore & Store>
|
|
22
|
+
: ParentStore
|
|
23
|
+
: Store extends Record<string, any>
|
|
24
|
+
? Store
|
|
25
|
+
: {}
|
|
26
|
+
|
|
27
|
+
export type WidgetInit<$$ extends Constructor | null = null, Store = any, Ancestors = Widget[], ParentStore = any> =
|
|
28
|
+
| {
|
|
29
|
+
ancestors?: Ancestors,
|
|
30
|
+
store?: Store,
|
|
31
|
+
$$?: $$,
|
|
32
|
+
layout: WidgetConstructLayout<$$, WidgetInitLayoutStore<ParentStore, Store>>
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type MergeAncestorStore<T extends any[]> =
|
|
36
|
+
MergeUnionType<
|
|
37
|
+
T extends Array<infer W>
|
|
38
|
+
? W extends Widget<any, any, infer Store>
|
|
39
|
+
? Store
|
|
40
|
+
: never
|
|
41
|
+
: never
|
|
42
|
+
>
|
|
43
|
+
|
|
44
|
+
type MergeUnionType<U> =
|
|
45
|
+
(
|
|
46
|
+
U extends any
|
|
47
|
+
? (k: U) => void
|
|
48
|
+
: never
|
|
49
|
+
) extends (k: infer I) => void
|
|
50
|
+
? I
|
|
51
|
+
: never;
|
|
52
|
+
|
|
53
|
+
type WidgetCraftArguments<$$ extends Constructor | null, Props> =
|
|
54
|
+
RequiredKeys<Props> extends never
|
|
55
|
+
? [children?: WidgetChildrenLayout<$$>] | [props?: $.Props<Props>, children?: WidgetChildrenLayout<$$>]
|
|
56
|
+
: [props: $.Props<Props>, children?: WidgetChildrenLayout<$$>]
|
|
57
|
+
|
|
58
|
+
declare global {
|
|
59
|
+
export function $<$$ extends Constructor | null, Props = never>(
|
|
60
|
+
widget: Widget<$$, Props>,
|
|
61
|
+
...args: WidgetCraftArguments<$$, Props>
|
|
62
|
+
): Proto;
|
|
63
|
+
|
|
64
|
+
export namespace $ {
|
|
65
|
+
export function widget<
|
|
66
|
+
Props extends $.Props,
|
|
67
|
+
Store,
|
|
68
|
+
Ancestors,
|
|
69
|
+
ParentStore extends MergeAncestorStore<Ancestors extends any[] ? Ancestors : []>,
|
|
70
|
+
$$ extends Constructor | null = null
|
|
71
|
+
>(init: (props: Props) => WidgetInit<$$, Store, Ancestors, ParentStore>): Widget<$$, Props, Store>;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
_Object_assign($, {
|
|
76
|
+
widget(arg1: any) {
|
|
77
|
+
let Widget = WidgetConstructor(arg1);
|
|
78
|
+
return Widget;
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
export * from "#structure/Widget";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { symbol_ProtoType } from "@amateras/core";
|
|
2
|
+
import { Proto } from "@amateras/core";
|
|
3
|
+
import { _Object_assign, forEach } from "@amateras/utils";
|
|
4
|
+
import type { WidgetChildrenLayout, WidgetInit } from "..";
|
|
5
|
+
|
|
6
|
+
export const WidgetConstructor = <$$ extends Constructor | null, Props, Store>
|
|
7
|
+
(init: (props: Props) => WidgetInit) => {
|
|
8
|
+
let stores = new WeakMap<Proto, Store>();
|
|
9
|
+
return class extends Proto {
|
|
10
|
+
declare static props: Props;
|
|
11
|
+
declare static store: Store;
|
|
12
|
+
static override [symbol_ProtoType] = 'Widget';
|
|
13
|
+
static stores = stores;
|
|
14
|
+
|
|
15
|
+
constructor(...args: Props extends unknown ? [] : [Props, WidgetChildrenLayout<$$>]) {
|
|
16
|
+
super(() => {
|
|
17
|
+
let props = args[0] ?? {};
|
|
18
|
+
let children = args[1];
|
|
19
|
+
let {store, layout, ancestors} = init(props as Props);
|
|
20
|
+
if (!store) store = {};
|
|
21
|
+
if (ancestors) forEach(ancestors, ancestor => {
|
|
22
|
+
let ancestorProto = this.findAbove(proto => proto.constructor === ancestor && proto);
|
|
23
|
+
if (ancestorProto) {
|
|
24
|
+
let ancestorStore = ancestor.stores.get(ancestorProto);
|
|
25
|
+
_Object_assign(store, ancestorStore);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
stores.set(this, store);
|
|
29
|
+
//@ts-ignore
|
|
30
|
+
layout({store, children: (proto) => children?.(proto)});
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface Widget<$$ extends Constructor | null = any, Props = any, Store = any> {
|
|
37
|
+
new(...args: Props extends unknown ? [] : [Props]): Proto;
|
|
38
|
+
props: Props;
|
|
39
|
+
store: Store;
|
|
40
|
+
stores: WeakMap<Proto, Store>
|
|
41
|
+
layout: ($$: $$) => void
|
|
42
|
+
}
|