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
|
@@ -4,6 +4,8 @@ import './global';
|
|
|
4
4
|
import { ElementProto } from './structure/ElementProto';
|
|
5
5
|
import { Proto } from './structure/Proto';
|
|
6
6
|
import { TextProto } from './structure/TextProto';
|
|
7
|
+
import type { ProxyProto } from '#structure/ProxyProto';
|
|
8
|
+
import type { NodeProto } from '#structure/NodeProto';
|
|
7
9
|
|
|
8
10
|
function createProto(insert: boolean, ...args: any) {
|
|
9
11
|
const prevProtoParent = Proto.proto;
|
|
@@ -37,9 +39,12 @@ function createProto(insert: boolean, ...args: any) {
|
|
|
37
39
|
|
|
38
40
|
// Function Handler
|
|
39
41
|
if (isFunction(arg1)) {
|
|
40
|
-
let args
|
|
42
|
+
let args = arg2 ? [arg2, arg3] : [arg3];
|
|
43
|
+
if (_instanceof(arg1.prototype, ElementProto)) {
|
|
44
|
+
args = isFunction(arg2) ? [{}, arg2] : [arg2, arg3];
|
|
45
|
+
}
|
|
46
|
+
// Constructor Handler
|
|
41
47
|
let target = new arg1(...args);
|
|
42
|
-
// Widget Handler
|
|
43
48
|
if (_instanceof(target, Proto)) {
|
|
44
49
|
addProtoToParent(target);
|
|
45
50
|
return target;
|
|
@@ -81,42 +86,96 @@ type ElementProtoArguments<C extends Constructor> =
|
|
|
81
86
|
? [layout?: ConstructorParameters<C>[1]] | [props: ConstructorParameters<C>[0], layout?: ConstructorParameters<C>[1]]
|
|
82
87
|
: [props: ConstructorParameters<C>[0], layout?: ConstructorParameters<C>[1]]
|
|
83
88
|
|
|
84
|
-
export function $<
|
|
85
|
-
export function
|
|
86
|
-
export function $(proto: Proto): Proto;
|
|
87
|
-
export function $(args: any[]): Proto[];
|
|
88
|
-
export function $<T extends keyof HTMLElementTagNameMap>(tagname: T, layout?: $.Layout<ElementProto<HTMLElementTagNameMap[T]>>): ElementProto;
|
|
89
|
-
export function $<T extends string>(tagname: T, layout?: $.Layout<ElementProto>): ElementProto;
|
|
90
|
-
export function $<T extends keyof HTMLElementTagNameMap>(tagname: T, attr: $.Props, layout?: $.Layout<ElementProto<HTMLElementTagNameMap[T]>>): ElementProto;
|
|
91
|
-
export function $<T extends string>(tagname: T, attr: $.Props, layout?: $.Layout<ElementProto>): ElementProto;
|
|
89
|
+
export function $<K extends $.Overload[keyof $.Overload][0][0], T extends $.OverloadResolver<[K]>>(arg1: K, ...args: T[1]): T[0];
|
|
90
|
+
export function $<K extends $.Overload[keyof $.Overload][0][0], L extends $.Overload[keyof $.Overload][0][1], T extends $.OverloadResolver<[K, L]>>(arg1: K, arg2: L, ...args: T[1]): T[0];
|
|
92
91
|
export function $(...args: any): any {
|
|
93
92
|
return createProto(true, ...args);
|
|
94
93
|
}
|
|
95
94
|
|
|
96
95
|
interface Craft {
|
|
97
|
-
<
|
|
98
|
-
(
|
|
99
|
-
(proto: Proto): Proto;
|
|
100
|
-
(args: any[]): Proto[];
|
|
101
|
-
<T extends keyof HTMLElementTagNameMap>(tagname: T, layout?: $.Layout<ElementProto<HTMLElementTagNameMap[T]>>): ElementProto;
|
|
102
|
-
<T extends string>(tagname: T, layout?: $.Layout<ElementProto>): ElementProto;
|
|
103
|
-
<T extends keyof HTMLElementTagNameMap>(tagname: T, attr: $.Props, layout?: $.Layout<ElementProto<HTMLElementTagNameMap[T]>>): ElementProto;
|
|
104
|
-
<T extends string>(tagname: T, attr: $.Props, layout?: $.Layout<ElementProto>): ElementProto;
|
|
96
|
+
<K extends $.Overload[keyof $.Overload][0][0], T extends $.OverloadResolver<[K]>>(arg1: K, ...args: T[1]): T[0];
|
|
97
|
+
<K extends $.Overload[keyof $.Overload][0][0], L extends $.Overload[keyof $.Overload][0][1], T extends $.OverloadResolver<[K, L]>>(arg1: K, arg2: L, ...args: T[1]): T[0];
|
|
105
98
|
}
|
|
106
99
|
|
|
107
100
|
export namespace $ {
|
|
108
101
|
/** Layout 是一个 Proto 模板函数,所有在此函数中运行 $ 函数所创建的 Proto 都会被加入到运行 Layout 的 Proto 中。 */
|
|
109
102
|
export type Layout<E extends Proto = any> = (proto: E) => void;
|
|
110
103
|
/** Props 是组件函数的参数,集合了该组件的自定义属性,以及组件 Layout 函数和元素属性的传递。 */
|
|
111
|
-
export type Props<T = {}> = { [key: string]: any } & T & Partial<AttrMap
|
|
104
|
+
export type Props<T = {}, H = HTMLElement> = { [key: string]: any } & T & Partial<AttrMap<H>>;
|
|
112
105
|
|
|
113
106
|
export type CraftMiddleware = (...args: any[]) => any;
|
|
114
107
|
export type TextMiddleware = (value: any) => Proto | undefined;
|
|
115
108
|
export type AttrMiddleware = (name: string, value: any, proto: ElementProto) => any;
|
|
109
|
+
|
|
110
|
+
export interface Overload<I extends any[] = any> {
|
|
111
|
+
proto: [
|
|
112
|
+
input: [Proto],
|
|
113
|
+
output: I[0] extends Constructor<infer P> ? P : I[0],
|
|
114
|
+
args: []
|
|
115
|
+
]
|
|
116
|
+
template: [
|
|
117
|
+
input: [TemplateStringsArray],
|
|
118
|
+
output: Proto[],
|
|
119
|
+
args: any[]
|
|
120
|
+
]
|
|
121
|
+
arr: [
|
|
122
|
+
input: [any[]],
|
|
123
|
+
output: Proto[],
|
|
124
|
+
args: []
|
|
125
|
+
]
|
|
126
|
+
elementConstructor: [
|
|
127
|
+
input: [Constructor],
|
|
128
|
+
output: I[0] extends Constructor<infer E>
|
|
129
|
+
? E extends ElementProto<any>
|
|
130
|
+
? InstanceType<I[0]>
|
|
131
|
+
: never
|
|
132
|
+
: never,
|
|
133
|
+
args: I[0] extends Constructor<infer E>
|
|
134
|
+
? E extends ElementProto<any>
|
|
135
|
+
? ElementProtoArguments<I[0]>
|
|
136
|
+
: never
|
|
137
|
+
: never,
|
|
138
|
+
],
|
|
139
|
+
proxyConstructor: [
|
|
140
|
+
input: [Constructor],
|
|
141
|
+
output: I[0] extends Constructor<infer P> ? P : I[0],
|
|
142
|
+
args: I[0] extends Constructor<infer E>
|
|
143
|
+
? E extends ProxyProto
|
|
144
|
+
? ConstructorParameters<I[0]>
|
|
145
|
+
: never
|
|
146
|
+
: never
|
|
147
|
+
]
|
|
148
|
+
string: [
|
|
149
|
+
input: [string] | [keyof HTMLElementTagNameMap],
|
|
150
|
+
output: I[0] extends keyof HTMLElementTagNameMap ? ElementProto<HTMLElementTagNameMap[I[0]]> : ElementProto,
|
|
151
|
+
args: [
|
|
152
|
+
props?: I[0] extends keyof HTMLElementTagNameMap ? $.Props<{}, HTMLElementTagNameMap[I[0]]> : $.Props,
|
|
153
|
+
layout?:
|
|
154
|
+
| $.Layout<I[0] extends keyof HTMLElementTagNameMap ? ElementProto<HTMLElementTagNameMap[I[0]]> : ElementProto>]
|
|
155
|
+
| [layout?: $.Layout<I[0] extends keyof HTMLElementTagNameMap ? ElementProto<HTMLElementTagNameMap[I[0]]> : ElementProto>
|
|
156
|
+
]
|
|
157
|
+
]
|
|
158
|
+
}
|
|
116
159
|
|
|
117
|
-
export
|
|
160
|
+
export type OverloadResolver<K extends any[]> = {
|
|
161
|
+
[I in keyof Overload<K>]: Overload<K>[I] extends [infer Input, infer Output, infer Args]
|
|
162
|
+
? K extends Input
|
|
163
|
+
? [Output, Args]
|
|
164
|
+
: never
|
|
165
|
+
: never
|
|
166
|
+
}[keyof Overload<K>];
|
|
167
|
+
|
|
168
|
+
export interface AttrMap<T> extends ElementProtoOnEventMap<T> {}
|
|
169
|
+
|
|
170
|
+
type ElementProtoOnEventMap<T> = {
|
|
171
|
+
[key in keyof HTMLElementEventMap as string extends string ? `on${key}` : never]: string | ((event: HTMLElementEventMap[key] & { currentTarget: T }) => void)
|
|
172
|
+
}
|
|
118
173
|
|
|
119
|
-
export interface ProtoEventMap {
|
|
174
|
+
export interface ProtoEventMap<P extends Proto> {
|
|
175
|
+
dispose: [];
|
|
176
|
+
builded: [];
|
|
177
|
+
dom: [node: P extends NodeProto ? Exclude<P['node'], null> : Node]
|
|
178
|
+
}
|
|
120
179
|
|
|
121
180
|
export const process = {
|
|
122
181
|
craft: new Set<CraftMiddleware>(),
|
|
@@ -126,15 +185,11 @@ export namespace $ {
|
|
|
126
185
|
|
|
127
186
|
export const craft: Craft = (...args: any) => createProto(false, ...args);
|
|
128
187
|
|
|
129
|
-
export const
|
|
130
|
-
Proto.proto?.ondispose(disposer);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export const render = (proto: Proto, query: string) => {
|
|
188
|
+
export const render = (proto: Proto | Constructor<Proto>, query: string) => {
|
|
134
189
|
// Disable render on server side
|
|
135
190
|
if (onserver()) return;
|
|
136
|
-
|
|
137
|
-
let nodes = $(proto).build().toDOM()
|
|
191
|
+
|
|
192
|
+
let nodes = $(proto as Proto).build().toDOM()
|
|
138
193
|
document.querySelector(query)?.replaceChildren(...nodes);
|
|
139
194
|
// if (!hmr(element, proto)) {
|
|
140
195
|
// let nodes = proto.build().toDOM()
|
|
@@ -180,9 +235,9 @@ export namespace $ {
|
|
|
180
235
|
return cases.get(condition)?.() ?? cases.get(symbol_default)?.();
|
|
181
236
|
}
|
|
182
237
|
|
|
183
|
-
export const
|
|
184
|
-
|
|
185
|
-
|
|
238
|
+
export const tuple = <T extends any[]>(...args: T) => args;
|
|
239
|
+
|
|
240
|
+
export const async = <T>(fn: (parent: Proto | null) => Promise<T>): Promise<T> => Proto.proto?.global.asyncTask(fn(Proto.proto)) ?? fn(Proto.proto);
|
|
186
241
|
|
|
187
242
|
export const stylesheet = onclient() ? new CSSStyleSheet() : _null;
|
|
188
243
|
export const styleMap = new Map<Constructor<ElementProto>, Set<string>>();
|
|
@@ -58,10 +58,10 @@ function diff(parentElement: HTMLElement, newProto: Proto, oldProto?: Proto, pre
|
|
|
58
58
|
if (!_instanceof(oldProto, NodeProto) || !_instanceof(newProto, NodeProto)) return;
|
|
59
59
|
newProto.node = oldProto.node;
|
|
60
60
|
oldProto.dispose();
|
|
61
|
-
if (newProto.modifiers) forEach(newProto.modifiers, mod => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
})
|
|
61
|
+
// if (newProto.modifiers) forEach(newProto.modifiers, mod => {
|
|
62
|
+
// if (!newProto.node) throw 'diff:transferNode:newProto.node==null'
|
|
63
|
+
// mod(newProto.node)
|
|
64
|
+
// })
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
if (!oldProto) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _Array_from, _null, _Object_assign, _Object_entries, forEach, isNull, isUndefined, map } from "@amateras/utils";
|
|
1
|
+
import { _Array_from, _null, _Object_assign, _Object_entries, forEach, isFunction, isNull, isUndefined, map } from "@amateras/utils";
|
|
2
2
|
import { NodeProto } from "./NodeProto";
|
|
3
3
|
|
|
4
4
|
const SELF_CLOSING_TAGNAMES = ['img', 'hr', 'br', 'input', 'link', 'meta'];
|
|
@@ -9,7 +9,7 @@ export class ElementProto<H extends HTMLElement = HTMLElement> extends NodeProto
|
|
|
9
9
|
declare layout: $.Layout | null;
|
|
10
10
|
#innerHTML = '';
|
|
11
11
|
private __props__: $.Props | null
|
|
12
|
-
constructor(tagname: string, props: $.Props | null, layout?: $.Layout | null) {
|
|
12
|
+
constructor(tagname: string, props: $.Props<any, any> | null, layout?: $.Layout | null) {
|
|
13
13
|
super(() => layout?.(this));
|
|
14
14
|
this.tagname = tagname;
|
|
15
15
|
this.__props__ = props;
|
|
@@ -32,6 +32,13 @@ export class ElementProto<H extends HTMLElement = HTMLElement> extends NodeProto
|
|
|
32
32
|
props({ ...props }: $.Props) {
|
|
33
33
|
let {class: className, ...propsFiltered} = props;
|
|
34
34
|
if (className) this.addClass(...className.split(' '));
|
|
35
|
+
// handle event listener in props
|
|
36
|
+
forEach(_Object_entries(propsFiltered), ([name, value]) => {
|
|
37
|
+
if (name.startsWith('on') && isFunction(value)) {
|
|
38
|
+
this.on(name.replace('on', ''), value);
|
|
39
|
+
delete propsFiltered[name];
|
|
40
|
+
}
|
|
41
|
+
})
|
|
35
42
|
this.attrProcess(propsFiltered);
|
|
36
43
|
}
|
|
37
44
|
|
|
@@ -40,19 +47,19 @@ export class ElementProto<H extends HTMLElement = HTMLElement> extends NodeProto
|
|
|
40
47
|
on(type: string, listener: (event: Event & { currentTarget: H }) => void, options?: boolean | AddEventListenerOptions) {
|
|
41
48
|
let setListener = (node: Node) => {
|
|
42
49
|
node.addEventListener(type, listener as any, options)
|
|
43
|
-
this.
|
|
50
|
+
this.listen('dispose', () => this.node?.removeEventListener(type, listener as any))
|
|
44
51
|
}
|
|
45
52
|
if (this.node) setListener(this.node);
|
|
46
|
-
else this.
|
|
53
|
+
else this.listen('dom', setListener);
|
|
47
54
|
}
|
|
48
55
|
|
|
49
56
|
override toString(): string {
|
|
50
|
-
return this.parseHTML()
|
|
57
|
+
return this.parseHTML();
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
parseHTML(options?: { children?: string, attr?: string }) {
|
|
54
61
|
let tagname = this.tagname;
|
|
55
|
-
let childrenHTML = options?.children ?? (this.#innerHTML || map(this.protos, proto => `${proto}`).join(''));
|
|
62
|
+
let childrenHTML = options?.children ?? (this.#innerHTML || map(this.protos, proto => proto.visible ? `${proto}` : '').join(''));
|
|
56
63
|
let attr = options?.attr ?? map(_Object_entries(this.#attr), ([key, value]) => value.length ? `${key}="${value}"` : key).join(' ');
|
|
57
64
|
let attrText = attr.length ? ' ' + attr : '';
|
|
58
65
|
if (SELF_CLOSING_TAGNAMES.includes(tagname)) return `<${tagname}${attrText} />`;
|
|
@@ -60,16 +67,31 @@ export class ElementProto<H extends HTMLElement = HTMLElement> extends NodeProto
|
|
|
60
67
|
}
|
|
61
68
|
|
|
62
69
|
override toDOM(children = true): H[] {
|
|
63
|
-
|
|
64
|
-
let element = document.createElement(this.tagname) as H;
|
|
70
|
+
let element = this.node ?? document.createElement(this.tagname) as H;
|
|
65
71
|
this.node = element;
|
|
66
|
-
if (this.#innerHTML) this.node.innerHTML = this.#innerHTML;
|
|
67
|
-
else if (children)
|
|
72
|
+
if (this.#innerHTML && this.node.innerHTML !== this.#innerHTML) this.node.innerHTML = this.#innerHTML;
|
|
73
|
+
else if (children) this.DOMProcess();
|
|
68
74
|
forEach(_Object_entries(this.#attr), ([key, value]) => element.setAttribute(key, value));
|
|
69
|
-
|
|
75
|
+
this.dispatch('dom', [this.node])
|
|
70
76
|
return [element];
|
|
71
77
|
}
|
|
72
78
|
|
|
79
|
+
private DOMProcess() {
|
|
80
|
+
let thisNode = this.node;
|
|
81
|
+
if (thisNode) {
|
|
82
|
+
let nodes = map(_Array_from(this.protos).filter(proto => proto.visible), proto => proto.toDOM()).flat();
|
|
83
|
+
let nextNode: Node | null = _null;
|
|
84
|
+
forEach(nodes, (node, i) => {
|
|
85
|
+
let currentNode = thisNode.childNodes[i];
|
|
86
|
+
if (currentNode !== node) {
|
|
87
|
+
if (!nodes.includes(currentNode as any)) nextNode = currentNode ?? _null;
|
|
88
|
+
else nextNode = thisNode.childNodes[i + 1] ?? _null;
|
|
89
|
+
thisNode.insertBefore(node, nextNode);
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
73
95
|
private attrProcess(attrObj: $.Props) {
|
|
74
96
|
forEach(_Object_entries(attrObj), ([key, value]) => {
|
|
75
97
|
for (let process of $.process.attr) {
|
|
@@ -1,26 +1,35 @@
|
|
|
1
1
|
import { _null, _Object_assign, forEach } from "@amateras/utils";
|
|
2
|
-
import
|
|
2
|
+
import { Proto } from "./Proto";
|
|
3
|
+
|
|
4
|
+
export type GlobalStateInitial = (global: GlobalState) => object | void;
|
|
3
5
|
|
|
4
6
|
export class GlobalState {
|
|
5
7
|
static disposers = new Set<(global: GlobalState) => void>()
|
|
6
8
|
promises = new Set<Promise<any>>();
|
|
7
9
|
root: Proto;
|
|
10
|
+
static initials = new Set<GlobalStateInitial>();
|
|
8
11
|
constructor(root: Proto) {
|
|
12
|
+
forEach(GlobalState.initials, initial => {
|
|
13
|
+
const obj = initial(this);
|
|
14
|
+
if (obj) _Object_assign(this, obj);
|
|
15
|
+
})
|
|
9
16
|
this.root = root;
|
|
10
|
-
root.
|
|
17
|
+
root.listen('dispose', () => this.dispose());
|
|
11
18
|
}
|
|
19
|
+
|
|
12
20
|
dispose() {
|
|
13
21
|
this.promises.clear();
|
|
14
22
|
this.root = _null as any;
|
|
15
23
|
forEach(GlobalState.disposers, disposer => disposer(this));
|
|
16
24
|
}
|
|
17
25
|
|
|
18
|
-
static assign(
|
|
19
|
-
|
|
26
|
+
static assign(initial: GlobalStateInitial) {
|
|
27
|
+
this.initials.add(initial);
|
|
20
28
|
}
|
|
21
29
|
|
|
22
30
|
asyncTask(promise: Promise<any>) {
|
|
23
31
|
this.promises.add(promise);
|
|
24
32
|
promise.finally(() => this.promises.delete(promise));
|
|
33
|
+
return promise;
|
|
25
34
|
}
|
|
26
35
|
}
|
|
@@ -4,20 +4,18 @@ import { onclient } from "#env";
|
|
|
4
4
|
|
|
5
5
|
export class NodeProto<N extends Node & ChildNode = Node & ChildNode> extends Proto {
|
|
6
6
|
node: null | N = _null;
|
|
7
|
-
modifiers: null | ((node: N) => void)[] = _null
|
|
8
7
|
constructor(layout?: $.Layout) {
|
|
9
8
|
super(layout);
|
|
10
9
|
}
|
|
11
10
|
|
|
11
|
+
/**@deprecated - use `Proto.listen` on 'dom' event instead */
|
|
12
12
|
ondom(callback: (node: N) => void) {
|
|
13
|
-
this.
|
|
14
|
-
this.modifiers.push(callback);
|
|
13
|
+
this.listen('dom', callback as any)
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
override dispose(): void {
|
|
18
17
|
super.dispose();
|
|
19
18
|
this.node = _null;
|
|
20
|
-
this.modifiers = _null
|
|
21
19
|
}
|
|
22
20
|
|
|
23
21
|
inDOM() {
|
|
@@ -8,8 +8,6 @@ export abstract class Proto {
|
|
|
8
8
|
static proto: Proto | null = _null;
|
|
9
9
|
static [symbol_ProtoType] = 'Proto';
|
|
10
10
|
static [symbol_Statement] = false;
|
|
11
|
-
static disposer: ((proto: Proto) => void)[] = []
|
|
12
|
-
private disposers: Function[] | null = _null;
|
|
13
11
|
layout: $.Layout | null;
|
|
14
12
|
readonly parent: Proto | null = _null;
|
|
15
13
|
global: GlobalState = Proto.proto?.global ?? new GlobalState(this);
|
|
@@ -17,7 +15,8 @@ export abstract class Proto {
|
|
|
17
15
|
firstProto: Proto | null = _null;
|
|
18
16
|
lastProto: Proto | null = _null;
|
|
19
17
|
builded = false;
|
|
20
|
-
|
|
18
|
+
visible = true;
|
|
19
|
+
listeners: { [key: string]: Set<(...args: any[]) => void> } | null = _null;
|
|
21
20
|
/**
|
|
22
21
|
* @virtual This property is phantom types, declare the return type of {@link Proto.children}
|
|
23
22
|
* @deprecated
|
|
@@ -28,20 +27,18 @@ export abstract class Proto {
|
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
dispose() {
|
|
31
|
-
|
|
32
|
-
forEach(this.disposers, disposer => disposer());
|
|
30
|
+
this.dispatch('dispose', [this])
|
|
33
31
|
forEach(this.protos, proto => proto.dispose());
|
|
34
32
|
this.global = _null as any;
|
|
35
33
|
this.sibling = _null;
|
|
36
34
|
this.firstProto = _null;
|
|
37
35
|
this.lastProto = _null;
|
|
38
|
-
this.disposers = _null;
|
|
39
36
|
(this as Mutable<this>).parent = _null;
|
|
40
37
|
this.layout = _null;
|
|
41
38
|
}
|
|
42
39
|
|
|
43
40
|
get children(): this['__child__'][] {
|
|
44
|
-
return map(this.protos, proto => {
|
|
41
|
+
return map(Array.from(this.protos).filter(proto => proto.visible), proto => {
|
|
45
42
|
//@ts-ignore
|
|
46
43
|
if (proto.constructor[symbol_Statement])
|
|
47
44
|
return proto.children
|
|
@@ -105,6 +102,10 @@ export abstract class Proto {
|
|
|
105
102
|
proto.global = this.global;
|
|
106
103
|
}
|
|
107
104
|
|
|
105
|
+
remove() {
|
|
106
|
+
this.parent?.removeProtos(this);
|
|
107
|
+
}
|
|
108
|
+
|
|
108
109
|
removeProtos(...protos: Proto[]) {
|
|
109
110
|
let protoSet = this.protos;
|
|
110
111
|
forEach(protos, proto => {
|
|
@@ -116,11 +117,12 @@ export abstract class Proto {
|
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
private processProtos(...protos: Proto[]) {
|
|
119
|
-
let prevProto: null | Proto =
|
|
120
|
+
let prevProto: null | Proto = _null;
|
|
120
121
|
if (protos.length)
|
|
121
122
|
forEach(protos, (proto, i) => {
|
|
122
123
|
if (i === 0) this.firstProto = proto;
|
|
123
124
|
if (prevProto) prevProto.sibling = proto;
|
|
125
|
+
proto.sibling = _null;
|
|
124
126
|
prevProto = proto;
|
|
125
127
|
(proto as Mutable<Proto>).parent = this;
|
|
126
128
|
})
|
|
@@ -129,28 +131,30 @@ export abstract class Proto {
|
|
|
129
131
|
this.lastProto = prevProto;
|
|
130
132
|
}
|
|
131
133
|
|
|
132
|
-
build(cascading = true): this {
|
|
133
|
-
this.clear(true);
|
|
134
|
+
build(cascading = true, clear = true): this {
|
|
135
|
+
if (clear) this.clear(true);
|
|
134
136
|
$.context(Proto, this, () => this.layout?.(this));
|
|
135
137
|
this.builded = true;
|
|
136
138
|
if (cascading) forEach(this.protos, proto => {
|
|
137
139
|
proto.build()
|
|
138
140
|
});
|
|
139
|
-
this.dispatch('builded', this);
|
|
141
|
+
this.dispatch('builded', [this]);
|
|
140
142
|
return this
|
|
141
143
|
}
|
|
142
144
|
|
|
143
145
|
toString(): string {
|
|
144
|
-
return map(this.protos, proto => `${proto}`).join('')
|
|
146
|
+
return map(_Array_from(this.protos).filter(proto => proto.visible), proto => `${proto}`).join('')
|
|
145
147
|
}
|
|
146
148
|
|
|
147
149
|
toDOM(children = true): Node[] {
|
|
148
|
-
return children ? map(this.protos, proto => proto.toDOM(children)).flat() : [];
|
|
150
|
+
return children ? map(_Array_from(this.protos).filter(proto => proto.visible), proto => proto.toDOM(children)).flat() : [];
|
|
149
151
|
}
|
|
150
152
|
|
|
153
|
+
/**
|
|
154
|
+
* @deprecated use Proto.listen('dispose') instead
|
|
155
|
+
*/
|
|
151
156
|
ondispose(disposer: () => void) {
|
|
152
|
-
this.
|
|
153
|
-
this.disposers.push(disposer);
|
|
157
|
+
this.listen('dispose', disposer);
|
|
154
158
|
}
|
|
155
159
|
|
|
156
160
|
removeNode() {
|
|
@@ -169,10 +173,10 @@ export abstract class Proto {
|
|
|
169
173
|
return _null;
|
|
170
174
|
}
|
|
171
175
|
|
|
172
|
-
findBelow(filter: (proto: Proto) => boolean | void):
|
|
176
|
+
findBelow<T extends Proto>(filter: (proto: Proto) => boolean | void): T | null {
|
|
173
177
|
for (let proto of this.protos) {
|
|
174
|
-
if (filter(proto)) return proto;
|
|
175
|
-
let nested = proto.findBelow(filter);
|
|
178
|
+
if (filter(proto)) return proto as T;
|
|
179
|
+
let nested = proto.findBelow<T>(filter);
|
|
176
180
|
if (nested) return nested;
|
|
177
181
|
}
|
|
178
182
|
return _null;
|
|
@@ -196,14 +200,24 @@ export abstract class Proto {
|
|
|
196
200
|
get text(): string {
|
|
197
201
|
return this.children.map(proto => proto.text).join('')
|
|
198
202
|
}
|
|
199
|
-
|
|
200
|
-
dispatch(type:
|
|
201
|
-
|
|
203
|
+
|
|
204
|
+
dispatch<K extends keyof $.ProtoEventMap<this>>(type: K, args: $.ProtoEventMap<this>[K], options?: {bubbles?: boolean}): boolean
|
|
205
|
+
dispatch(type: string, args: any[], options?: {bubbles?: boolean}): boolean
|
|
206
|
+
dispatch(type: string, args: any[], options?: {bubbles?: boolean}): boolean {
|
|
202
207
|
let handlerSet = this.listeners?.[type];
|
|
203
|
-
|
|
208
|
+
let preventDefault = false;
|
|
209
|
+
if (options?.bubbles) {
|
|
210
|
+
let prevent = this.parent?.dispatch(type, args, options);
|
|
211
|
+
if (!preventDefault) preventDefault = prevent ?? false;
|
|
212
|
+
}
|
|
213
|
+
forEach(handlerSet, handle => {
|
|
214
|
+
let prevent = handle(...args) ?? false;
|
|
215
|
+
if (!preventDefault) preventDefault = prevent;
|
|
216
|
+
});
|
|
217
|
+
return preventDefault;
|
|
204
218
|
}
|
|
205
219
|
|
|
206
|
-
listen<K extends keyof $.ProtoEventMap
|
|
220
|
+
listen<K extends keyof $.ProtoEventMap<this>>(type: K, handle: (...args: $.ProtoEventMap<this>[K]) => void): void;
|
|
207
221
|
listen(type: string, handle: (src: Proto) => void): void;
|
|
208
222
|
listen(type: string, handle: (...args: any) => void) {
|
|
209
223
|
let listeners = this.listeners ?? {};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { forEach } from "@amateras/utils";
|
|
2
1
|
import { NodeProto } from "./NodeProto";
|
|
3
2
|
|
|
4
3
|
export class TextProto extends NodeProto<Text> {
|
|
@@ -25,7 +24,7 @@ export class TextProto extends NodeProto<Text> {
|
|
|
25
24
|
if (this.node) return [this.node];
|
|
26
25
|
let node = new Text(this.#content);
|
|
27
26
|
this.node = node;
|
|
28
|
-
|
|
27
|
+
this.dispatch('dom', [this.node])
|
|
29
28
|
return [node];
|
|
30
29
|
}
|
|
31
30
|
|
package/packages/css/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# amateras/css
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Import
|
|
4
4
|
```ts
|
|
5
5
|
import 'amateras';
|
|
6
6
|
import 'amateras/css';
|
|
@@ -21,23 +21,27 @@ const style = $.css({
|
|
|
21
21
|
}
|
|
22
22
|
})
|
|
23
23
|
|
|
24
|
-
$(
|
|
25
|
-
$('p'
|
|
26
|
-
|
|
24
|
+
$('div', { css: style }, $$ => {
|
|
25
|
+
$('p', $$ => $`Change the size of window to see the color changes.`)
|
|
26
|
+
})
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
## Define Style in
|
|
29
|
+
## Define Style in Layout
|
|
30
|
+
There are two way to define CSS rule of proto.
|
|
30
31
|
```ts
|
|
31
|
-
$(
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
$('div', $$ => {
|
|
33
|
+
$$.css({
|
|
34
|
+
padding: '1rem 2rem'
|
|
35
|
+
})
|
|
36
|
+
$('h1', { css: { color: 'red' } }, $$ => $`This is a title with red color!`)
|
|
37
|
+
})
|
|
34
38
|
```
|
|
35
39
|
|
|
36
40
|
## Define Variables
|
|
37
41
|
|
|
38
42
|
### Single Variable
|
|
39
43
|
```ts
|
|
40
|
-
const largeText = $.css.
|
|
44
|
+
const largeText = $.css.variable('1.2rem');
|
|
41
45
|
|
|
42
46
|
$.css({
|
|
43
47
|
fontSize: largeText
|
|
@@ -46,7 +50,9 @@ $.css({
|
|
|
46
50
|
|
|
47
51
|
### Variable Group
|
|
48
52
|
```ts
|
|
49
|
-
|
|
53
|
+
import 'amateras/css/variable';
|
|
54
|
+
|
|
55
|
+
const text = $.css.variable({
|
|
50
56
|
small: '0.8rem',
|
|
51
57
|
medium: '1rem',
|
|
52
58
|
large: '1.2rem'
|
|
@@ -59,6 +65,8 @@ $.css({
|
|
|
59
65
|
|
|
60
66
|
## Define Keyframes
|
|
61
67
|
```ts
|
|
68
|
+
import 'amateras/css/keyframes';
|
|
69
|
+
|
|
62
70
|
const keyframes = $.css.keyframes({
|
|
63
71
|
fadeIn: {
|
|
64
72
|
'0%': { opacity: 0 },
|
|
@@ -101,11 +109,6 @@ $.CSS({
|
|
|
101
109
|
}
|
|
102
110
|
},
|
|
103
111
|
})
|
|
104
|
-
|
|
105
|
-
$(document.body).content([
|
|
106
|
-
$('h1').class('title').content('A red color title.')
|
|
107
|
-
])
|
|
108
|
-
|
|
109
112
|
```
|
|
110
113
|
|
|
111
114
|
### CSS Colors Preset
|
|
@@ -26,9 +26,8 @@ declare global {
|
|
|
26
26
|
|
|
27
27
|
export type CSSPropertyMap = {
|
|
28
28
|
[key: string]:
|
|
29
|
-
[$.CSSPropertySyntax, string | number, boolean]
|
|
30
|
-
| [
|
|
31
|
-
| ['*']
|
|
29
|
+
[syntax: $.CSSPropertySyntax, initialValue?: string | number, inherits?: boolean]
|
|
30
|
+
| [syntax: '*']
|
|
32
31
|
}
|
|
33
32
|
}
|
|
34
33
|
}
|
|
@@ -85,6 +85,7 @@ export interface $CSSDeclarationMap {
|
|
|
85
85
|
content: string;
|
|
86
86
|
counterIncrement: string;
|
|
87
87
|
counterReset: string;
|
|
88
|
+
container: string;
|
|
88
89
|
containerName: string;
|
|
89
90
|
containerType: 'inline-size' | 'size' | 'normal' | 'scroll-state';
|
|
90
91
|
cursor: 'auto' | 'default' | 'none' | 'context-menu' | 'help' | 'pointer' | 'progress' | 'wait' | 'cell' | 'crosshair' | 'text' | 'vertical-text' | 'alias' | 'copy' | 'move' | 'no-drop' | 'not-allowed' | 'e-resize' | 'n-resize' | 'ne-resize' | 'nw-resize' | 's-resize' | 'se-resize' | 'sw-resize' | 'w-resize' | 'ew-resize' | 'ns-resize' | 'nesw-resize' | 'nwse-resize' | 'col-resize' | 'row-resize' | 'all-scroll' | 'zoom-in' | 'zoom-out' | 'grab' | 'grabbing';
|
|
@@ -234,6 +235,9 @@ export interface $CSSDeclarationMap {
|
|
|
234
235
|
scrollMarginInline: string;
|
|
235
236
|
scrollMarginInlineStart: string;
|
|
236
237
|
scrollMarginInlineEnd: string;
|
|
238
|
+
scrollbarWidth: 'thin' | 'none' | 'auto'
|
|
239
|
+
scrollbarGutter: OptionalStrings<['stable', 'both-edges']>
|
|
240
|
+
scrollbarColor: 'auto';
|
|
237
241
|
shapeRendering: 'auto' | 'optimizeSpeed' | 'crispEdges' | 'geometricPrecision';
|
|
238
242
|
stopColor: string;
|
|
239
243
|
stopOpacity: string;
|
|
@@ -270,6 +274,7 @@ export interface $CSSDeclarationMap {
|
|
|
270
274
|
textTransform: 'none' | 'capitalize' | 'uppercase' | 'lowercase';
|
|
271
275
|
textUnderlineOffset: string;
|
|
272
276
|
textUnderlinePosition: 'auto' | 'under' | 'left' | 'right';
|
|
277
|
+
textWrap: 'auto' | 'wrap' | 'nowrap' | 'balance' | 'pretty' | 'stable'
|
|
273
278
|
top: string;
|
|
274
279
|
touchAction: 'auto' | 'none' | 'pan-x' | 'pan-y' | 'manipulation';
|
|
275
280
|
transform: string;
|