amateras 0.4.2 → 0.6.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 +24 -25
- package/ext/html/node/$Anchor.ts +3 -3
- package/ext/html/node/$Canvas.ts +2 -2
- package/ext/html/node/$Dialog.ts +2 -2
- package/ext/html/node/$Form.ts +2 -2
- package/ext/html/node/$Image.ts +2 -2
- package/ext/html/node/$Input.ts +28 -4
- package/ext/html/node/$Label.ts +12 -3
- package/ext/html/node/$Media.ts +2 -2
- package/ext/html/node/$OptGroup.ts +2 -2
- package/ext/html/node/$Option.ts +2 -2
- package/ext/html/node/$Select.ts +2 -2
- package/ext/html/node/$TextArea.ts +2 -2
- package/ext/i18n/README.md +20 -0
- package/ext/i18n/src/index.ts +106 -12
- package/ext/i18n/src/structure/I18n.ts +12 -8
- package/ext/i18n/src/structure/I18nDictionary.ts +2 -2
- package/ext/i18n/src/structure/I18nTranslation.ts +35 -0
- package/ext/idb/README.md +127 -0
- package/ext/idb/package.json +13 -0
- package/ext/idb/src/core.ts +6 -0
- package/ext/idb/src/index.ts +17 -0
- package/ext/idb/src/lib/$IDBRequest.ts +8 -0
- package/ext/idb/src/structure/$IDB.ts +63 -0
- package/ext/idb/src/structure/$IDBCursor.ts +34 -0
- package/ext/idb/src/structure/$IDBIndex.ts +48 -0
- package/ext/idb/src/structure/$IDBStore.ts +103 -0
- package/ext/idb/src/structure/$IDBStoreBase.ts +30 -0
- package/ext/idb/src/structure/$IDBTransaction.ts +38 -0
- package/ext/idb/src/structure/builder/$IDBBuilder.ts +230 -0
- package/ext/idb/src/structure/builder/$IDBStoreBuilder.ts +100 -0
- package/ext/markdown/README.md +53 -0
- package/ext/markdown/package.json +15 -0
- package/ext/markdown/src/index.ts +3 -0
- package/ext/markdown/src/lib/type.ts +26 -0
- package/ext/markdown/src/lib/util.ts +21 -0
- package/ext/markdown/src/structure/Markdown.ts +54 -0
- package/ext/markdown/src/structure/MarkdownLexer.ts +111 -0
- package/ext/markdown/src/structure/MarkdownParser.ts +33 -0
- package/ext/markdown/src/syntax/alert.ts +46 -0
- package/ext/markdown/src/syntax/blockquote.ts +35 -0
- package/ext/markdown/src/syntax/bold.ts +11 -0
- package/ext/markdown/src/syntax/code.ts +11 -0
- package/ext/markdown/src/syntax/codeblock.ts +44 -0
- package/ext/markdown/src/syntax/heading.ts +14 -0
- package/ext/markdown/src/syntax/horizontalRule.ts +11 -0
- package/ext/markdown/src/syntax/image.ts +23 -0
- package/ext/markdown/src/syntax/italic.ts +11 -0
- package/ext/markdown/src/syntax/link.ts +46 -0
- package/ext/markdown/src/syntax/list.ts +121 -0
- package/ext/markdown/src/syntax/table.ts +67 -0
- package/ext/markdown/src/syntax/text.ts +19 -0
- package/ext/router/README.md +111 -17
- package/ext/router/package.json +10 -0
- package/ext/router/src/index.ts +69 -0
- package/ext/router/src/node/Page.ts +34 -0
- package/ext/router/src/node/Router.ts +191 -0
- package/ext/router/src/node/RouterAnchor.ts +24 -0
- package/ext/router/src/structure/PageBuilder.ts +24 -0
- package/ext/router/src/structure/Route.ts +105 -0
- package/ext/signal/README.md +93 -0
- package/ext/signal/package.json +9 -0
- package/ext/signal/src/index.ts +128 -0
- package/{src → ext/signal/src}/structure/Signal.ts +7 -11
- package/ext/ssr/index.ts +4 -4
- package/ext/ui/lib/VirtualScroll.ts +25 -0
- package/ext/ui/node/Accordian.ts +97 -0
- package/ext/ui/node/Form.ts +53 -0
- package/ext/ui/node/Grid.ts +0 -0
- package/ext/ui/node/Table.ts +43 -0
- package/ext/ui/node/Tabs.ts +114 -0
- package/ext/ui/node/Toast.ts +16 -0
- package/ext/ui/node/Waterfall.ts +72 -0
- package/ext/ui/package.json +11 -0
- package/package.json +9 -3
- package/src/core.ts +31 -59
- package/src/global.ts +12 -2
- package/src/index.ts +1 -2
- package/src/lib/assignProperties.ts +57 -0
- package/src/lib/native.ts +33 -11
- package/src/lib/sleep.ts +3 -1
- package/src/lib/toArray.ts +9 -0
- package/src/lib/trycatch.ts +17 -0
- package/src/lib/uppercase.ts +3 -0
- package/src/node/$Element.ts +7 -53
- package/src/node/$EventTarget.ts +45 -0
- package/src/node/$Node.ts +63 -55
- package/src/node/$Virtual.ts +65 -0
- package/src/node.ts +7 -6
- package/ext/i18n/src/node/I18nText.ts +0 -35
- package/ext/router/index.ts +0 -73
- package/ext/router/node/Page.ts +0 -27
- package/ext/router/node/Route.ts +0 -54
- package/ext/router/node/Router.ts +0 -149
- package/ext/router/node/RouterAnchor.ts +0 -8
- package/src/lib/assign.ts +0 -38
- package/src/lib/assignHelper.ts +0 -18
package/src/global.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { $Element } from '#node/$Element';
|
|
2
2
|
import type { $Node } from '#node/$Node';
|
|
3
3
|
import * as core from '#core';
|
|
4
|
-
import type {
|
|
4
|
+
import type { $EventTarget } from '#node/$EventTarget';
|
|
5
5
|
|
|
6
6
|
declare global {
|
|
7
7
|
export import $ = core.$;
|
|
@@ -11,7 +11,14 @@ declare global {
|
|
|
11
11
|
type OrPromise<T> = T | Promise<T>;
|
|
12
12
|
type OrNullish<T> = T | Nullish;
|
|
13
13
|
type Constructor<T> = { new (...args: any[]): T }
|
|
14
|
-
type
|
|
14
|
+
type Mutable<T> = {
|
|
15
|
+
-readonly [P in keyof T]: T[P];
|
|
16
|
+
}
|
|
17
|
+
type AsyncFunction<T> = () => Promise<T>;
|
|
18
|
+
type $Parameter<T> = T | undefined | $.$NodeParameterExtends<T>
|
|
19
|
+
type Ok<D> = [data: D, err: null];
|
|
20
|
+
type Err<E> = [data: null, err: E]
|
|
21
|
+
type Result<D, E> = Ok<D> | Err<E>
|
|
15
22
|
type Repeat<T, N extends number, Acc extends T[] = []> =
|
|
16
23
|
Acc['length'] extends N
|
|
17
24
|
? Acc
|
|
@@ -22,6 +29,9 @@ declare global {
|
|
|
22
29
|
interface Node {
|
|
23
30
|
readonly $: $Node
|
|
24
31
|
}
|
|
32
|
+
interface EventTarget {
|
|
33
|
+
readonly $: $EventTarget
|
|
34
|
+
}
|
|
25
35
|
interface Element {
|
|
26
36
|
readonly $: $Element
|
|
27
37
|
}
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { $EventTarget } from "#node/$EventTarget";
|
|
2
|
+
import { $Node } from "#node/$Node";
|
|
3
|
+
import { _instanceof, _null, _Object_defineProperty, _Object_entries, _Object_getOwnPropertyDescriptors, forEach, isUndefined } from "./native";
|
|
4
|
+
|
|
5
|
+
const assigner = (target: any, {set, get, fn}: {
|
|
6
|
+
set?: string[],
|
|
7
|
+
get?: string[],
|
|
8
|
+
fn?: string[]
|
|
9
|
+
}) => {
|
|
10
|
+
const [GET, SET, FN] = ['get', 'set', 'fn'] as const;
|
|
11
|
+
const filterAndMap = (type: 'get' | 'set' | 'fn', arr: string[] | undefined) => arr?.map(prop => [type, prop]) ?? []
|
|
12
|
+
const list = [...filterAndMap(GET, get), ...filterAndMap(SET, set), ...filterAndMap(FN, fn)] as [string, string][];
|
|
13
|
+
forEach(list, ([type, prop]) =>
|
|
14
|
+
_Object_defineProperty(target.prototype, prop, {
|
|
15
|
+
...(type === GET ? {
|
|
16
|
+
get() { return this.node[prop as any] }
|
|
17
|
+
} : {
|
|
18
|
+
writable: true,
|
|
19
|
+
...(type === SET ? {
|
|
20
|
+
// set
|
|
21
|
+
value(this, args: any) {
|
|
22
|
+
if (!arguments.length) return this.node[prop];
|
|
23
|
+
let set = (value: any) => !isUndefined(value) && (this.node[prop] = value);
|
|
24
|
+
for (const setter of $Node.setters) {
|
|
25
|
+
const result = setter(args, set);
|
|
26
|
+
if (!isUndefined(result)) return set(result), this;
|
|
27
|
+
}
|
|
28
|
+
set(args)
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
} : {
|
|
32
|
+
// fn
|
|
33
|
+
value(this, ...args : any[]) {
|
|
34
|
+
let result = this.node[prop](...args.map(value => _instanceof(value, $Node) ? value.node : value ?? _null))
|
|
35
|
+
return isUndefined(result) ? this : result;
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
}),
|
|
39
|
+
|
|
40
|
+
})
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const assignProperties = (object: Constructor<EventTarget>, target: Constructor<$EventTarget>, tagname?: string) => {
|
|
45
|
+
const [set, get, fn] = [[], [], []] as [string[], string[], string[]]
|
|
46
|
+
// assign native object properties to target
|
|
47
|
+
forEach(_Object_entries(_Object_getOwnPropertyDescriptors(object.prototype)), ([prop, value]) => {
|
|
48
|
+
if (!(prop in target.prototype)) {
|
|
49
|
+
if (value.get && !value.set) get.push(prop);
|
|
50
|
+
else if (value.value) fn.push(prop);
|
|
51
|
+
else if (value.get && value.set) set.push(prop);
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
assigner(target, {set, get, fn})
|
|
55
|
+
// register tagname
|
|
56
|
+
if (tagname) $.assign([tagname, target])
|
|
57
|
+
}
|
package/src/lib/native.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Value
|
|
2
2
|
export const _null = null;
|
|
3
|
+
export const _undefined = undefined;
|
|
3
4
|
// Object
|
|
4
5
|
export const _Object_fromEntries = Object.fromEntries;
|
|
5
6
|
export const _Object_entries = Object.entries;
|
|
@@ -9,27 +10,48 @@ export const _Object_defineProperty = Object.defineProperty;
|
|
|
9
10
|
export const _Object_getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors;
|
|
10
11
|
// Array
|
|
11
12
|
export const _Array_from = Array.from;
|
|
12
|
-
|
|
13
|
+
interface forEach {
|
|
14
|
+
<T>(arr: Array<T>, fn: (value: T, index: number, array: Array<T>) => Promise<void>): Promise<void>;
|
|
15
|
+
<T>(arr: Array<T>, fn: (value: T, index: number, array: Array<T>) => void): void;
|
|
16
|
+
<T>(set: Set<T>, fn: (value: T, index: number, set: Set<T>) => Promise<void>): void;
|
|
17
|
+
<T>(set: Set<T>, fn: (value: T, index: number, set: Set<T>) => void): void;
|
|
18
|
+
<K, V>(map: Map<K, V>, fn: (value: [K, V], index: number, map: Map<K, V>) => Promise<void>): void;
|
|
19
|
+
<K, V>(map: Map<K, V>, fn: (value: [K, V], index: number, map: Map<K, V>) => void): void;
|
|
20
|
+
<N extends Node>(set: NodeListOf<N>, fn: (value: N, index: number, parent: NodeListOf<N>) => Promise<void>): void;
|
|
21
|
+
<N extends Node>(set: NodeListOf<N>, fn: (value: N, index: number, parent: NodeListOf<N>) => void): void;
|
|
22
|
+
}
|
|
23
|
+
export const forEach: forEach = async (arr: any, fn: any) => {
|
|
24
|
+
let i = 0;
|
|
25
|
+
let isAsync = isAsyncFunction(fn);
|
|
26
|
+
let handle = async () => { for (let item of arr) { isAsync ? await fn(item, i, arr) : fn(item, i, arr); i++; } }
|
|
27
|
+
return isAsync ? new _Promise<void>(resolve => handle().then(resolve)) : handle();
|
|
28
|
+
};
|
|
29
|
+
// export const forEach: forEach = (arr: any, fn: any) => arr.forEach(fn);
|
|
13
30
|
// type check
|
|
14
31
|
export const _typeof = (target: any, type: 'string' | 'number' | 'object' | 'boolean' | 'function' | 'bigint' | 'symbol' | 'undefined') => typeof target === type;
|
|
15
32
|
export const equal = <T, V extends T>(target: T, ...args: V[]): target is V => !!args.find(a => a === target);
|
|
16
33
|
export const isString = (target: any): target is string => _typeof(target, 'string');
|
|
17
|
-
export const
|
|
18
|
-
export const
|
|
19
|
-
export const
|
|
34
|
+
export const isBoolean = (target: any): target is boolean => _typeof(target, 'boolean');
|
|
35
|
+
export const isNumber = (target: any): target is number => _typeof(target, 'number');
|
|
36
|
+
export const isObject = (target: any): target is object => _typeof(target, 'object');
|
|
37
|
+
export const isFunction = (target: any): target is Function => _typeof(target, 'function');
|
|
38
|
+
export const isAsyncFunction = (target: any): target is AsyncFunction<Awaited<ReturnType<typeof target>>> => _instanceof(target, (async () => 0).constructor as any)
|
|
20
39
|
export const isUndefined = (target: any): target is undefined => target === undefined;
|
|
21
40
|
export const isNull = (target: any): target is null => target === _null;
|
|
41
|
+
export const isArray = Array.isArray;
|
|
22
42
|
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);
|
|
23
43
|
// JSON
|
|
24
44
|
export const _JSON_stringify = JSON.stringify;
|
|
25
45
|
export const _JSON_parse = JSON.parse;
|
|
26
46
|
// String
|
|
27
47
|
export const startsWith = (target: string, ...str: string[]) => !!str.find(s => target.startsWith(s));
|
|
48
|
+
// String & Array
|
|
49
|
+
interface slice {
|
|
50
|
+
(target: string, start?: number, end?: number): string;
|
|
51
|
+
<T>(target: Array<T>, start?: number, end?: number): T[];
|
|
52
|
+
}
|
|
53
|
+
export const slice: slice = (target: any, start?: number, end?: number) => target.slice(start, end);
|
|
28
54
|
// Function
|
|
29
|
-
export const _bind = (target:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
<T>(set: Set<T>, fn: (value: T, index: number, set: Set<T>) => any, thisArgs?: any): void;
|
|
33
|
-
<K, V>(set: Map<K, V>, fn: (value: V, key: K, index: number, map: Map<K, V>) => any, thisArgs?: any): void;
|
|
34
|
-
<N extends Node>(set: NodeListOf<N>, fn: (value: N, index: number, parent: NodeListOf<N>) => any, thisArgs?: any): void;
|
|
35
|
-
}
|
|
55
|
+
export const _bind = <T extends Function>(target: T, obj: Object): T => target.bind(obj);
|
|
56
|
+
// Promise
|
|
57
|
+
export const _Promise = Promise;
|
package/src/lib/sleep.ts
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { _instanceof, _Object_assign } from "./native";
|
|
2
|
+
|
|
3
|
+
export const toArray = <T>(item: OrArray<T>): T[] => _instanceof(item, Array) ? item : [item];
|
|
4
|
+
|
|
5
|
+
declare module '#core' {
|
|
6
|
+
export namespace $ {
|
|
7
|
+
export function toArray<T>(item: OrArray<T>): T[];
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { _instanceof, _JSON_stringify, _null, _Object_assign } from "./native";
|
|
2
|
+
|
|
3
|
+
export const trycatch = <D>(callback: () => D): Result<D, Error> => {
|
|
4
|
+
try {
|
|
5
|
+
return [callback(), _null];
|
|
6
|
+
} catch (err) {
|
|
7
|
+
return [_null, _instanceof(err, Error) ? err : new Error(_JSON_stringify(err))];
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
_Object_assign($, {trycatch})
|
|
12
|
+
|
|
13
|
+
declare module '#core' {
|
|
14
|
+
export namespace $ {
|
|
15
|
+
export function trycatch <D>(callback: () => D): Result<D, Error>
|
|
16
|
+
}
|
|
17
|
+
}
|
package/src/node/$Element.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { Signal } from "#structure/Signal";
|
|
2
|
-
import { $Node } from "#node/$Node";
|
|
3
1
|
import { _Array_from, _instanceof, _Object_assign, _Object_entries, _Object_fromEntries, isNull, isString, isUndefined } from "#lib/native";
|
|
4
2
|
import { _document } from "#lib/env";
|
|
3
|
+
import { $Node } from "./$Node";
|
|
5
4
|
|
|
6
|
-
export class $Element<Ele extends Element = Element, EvMap = ElementEventMap> extends $Node {
|
|
5
|
+
export class $Element<Ele extends Element = Element, EvMap = ElementEventMap> extends $Node<EvMap> {
|
|
7
6
|
declare node: Ele
|
|
8
7
|
constructor(resolver: Ele | string) {
|
|
9
8
|
super(_instanceof(resolver, Element) ? resolver : createNode(resolver) as unknown as Ele)
|
|
@@ -13,14 +12,13 @@ export class $Element<Ele extends Element = Element, EvMap = ElementEventMap> ex
|
|
|
13
12
|
|
|
14
13
|
attr(): {[key: string]: string};
|
|
15
14
|
attr(key: string): string | null;
|
|
16
|
-
attr(obj: {[key: string]: string | number | boolean |
|
|
17
|
-
attr(resolver?: {[key: string]: string | number | boolean |
|
|
15
|
+
attr(obj: {[key: string]: string | number | boolean | null | undefined}): this;
|
|
16
|
+
attr(resolver?: {[key: string]: string | number | boolean | null | undefined} | string) {
|
|
18
17
|
if (!arguments.length) return _Object_fromEntries(_Array_from(this.attributes).map(attr => [attr.name, attr.value]));
|
|
19
18
|
if (isString(resolver)) return this.getAttribute(resolver);
|
|
20
19
|
if (resolver) for (let [key, value] of _Object_entries(resolver)) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
set(value);
|
|
20
|
+
if (!isUndefined(value) && isNull(value)) this.removeAttribute(key);
|
|
21
|
+
else this.setAttribute(key, `${value}`);
|
|
24
22
|
}
|
|
25
23
|
return this;
|
|
26
24
|
}
|
|
@@ -39,27 +37,11 @@ export class $Element<Ele extends Element = Element, EvMap = ElementEventMap> ex
|
|
|
39
37
|
return this;
|
|
40
38
|
}
|
|
41
39
|
|
|
42
|
-
on<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | AddEventListenerOptions) {
|
|
43
|
-
return this.addEventListener(type as string, listener as any, options);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
off<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | EventListenerOptions) {
|
|
47
|
-
return this.removeEventListener(type as string, listener as any, options);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
once<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | AddEventListenerOptions) {
|
|
51
|
-
return this.on(type, listener, {once: true})
|
|
52
|
-
}
|
|
53
|
-
|
|
54
40
|
toString() {
|
|
55
41
|
return this.outerHTML();
|
|
56
42
|
}
|
|
57
43
|
}
|
|
58
44
|
|
|
59
|
-
export type $Event<E extends $Element, Ev = any> = Ev & {currentTarget: {$: E}};
|
|
60
|
-
export type $EventListener<E extends $Element, Ev> = (event: $Event<E, Ev>) => void;
|
|
61
|
-
export type $EventListenerObject<E extends $Element, Ev> = { handleEvent(object: $Event<E, Ev>): void; }
|
|
62
|
-
|
|
63
45
|
function createNode(nodeName: string) {
|
|
64
46
|
return !_document
|
|
65
47
|
//@ts-expect-error
|
|
@@ -67,7 +49,7 @@ function createNode(nodeName: string) {
|
|
|
67
49
|
: _document.createElement(nodeName);
|
|
68
50
|
}
|
|
69
51
|
|
|
70
|
-
export interface $Element<Ele extends Element, EvMap> {
|
|
52
|
+
export interface $Element<Ele extends Element, EvMap = ElementEventMap> {
|
|
71
53
|
/** {@link Element.attributes} */
|
|
72
54
|
readonly attributes: NamedNodeMap;
|
|
73
55
|
/** {@link Element.clientHeight} */
|
|
@@ -207,20 +189,6 @@ export interface $Element<Ele extends Element, EvMap> {
|
|
|
207
189
|
animate(keyframes: Keyframe[] | PropertyIndexedKeyframes | null, options?: number | KeyframeAnimationOptions): Animation;
|
|
208
190
|
/** {@link Element.getAnimations} */
|
|
209
191
|
getAnimations(options?: GetAnimationsOptions): Animation[];
|
|
210
|
-
/** {@link Element.append} */
|
|
211
|
-
append(...nodes: (Node | string)[]): this;
|
|
212
|
-
/** {@link Element.prepend} */
|
|
213
|
-
prepend(...nodes: (Node | string)[]): this;
|
|
214
|
-
/** {@link Element.querySelector} */
|
|
215
|
-
querySelector<K extends keyof HTMLElementTagNameMap>(selectors: K): HTMLElementTagNameMap[K] | null;
|
|
216
|
-
querySelector<K extends keyof SVGElementTagNameMap>(selectors: K): SVGElementTagNameMap[K] | null;
|
|
217
|
-
querySelector<K extends keyof MathMLElementTagNameMap>(selectors: K): MathMLElementTagNameMap[K] | null;
|
|
218
|
-
/** {@link Element.querySelectorAll} */
|
|
219
|
-
querySelectorAll<K extends keyof HTMLElementTagNameMap>(selectors: K): NodeListOf<HTMLElementTagNameMap[K]>;
|
|
220
|
-
querySelectorAll<K extends keyof SVGElementTagNameMap>(selectors: K): NodeListOf<SVGElementTagNameMap[K]>;
|
|
221
|
-
querySelectorAll<K extends keyof MathMLElementTagNameMap>(selectors: K): NodeListOf<MathMLElementTagNameMap[K]>;
|
|
222
|
-
/** {@link Element.replaceChildren} */
|
|
223
|
-
replaceChildren(...nodes: (Node | string)[]): this;
|
|
224
192
|
|
|
225
193
|
/** {@link Element.classList} */
|
|
226
194
|
classList(): DOMTokenList;
|
|
@@ -383,18 +351,4 @@ export interface $Element<Ele extends Element, EvMap> {
|
|
|
383
351
|
/** {@link ARIAMixin.role} */
|
|
384
352
|
role(): string | null;
|
|
385
353
|
role(role: $Parameter<string | null>): this;
|
|
386
|
-
addEventListener<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | AddEventListenerOptions): this;
|
|
387
|
-
addEventListener(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | AddEventListenerOptions): this;
|
|
388
|
-
removeEventListener<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | EventListenerOptions): this;
|
|
389
|
-
removeEventListener(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | EventListenerOptions): this;
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
on(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | AddEventListenerOptions): this;
|
|
393
|
-
on<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | AddEventListenerOptions): this;
|
|
394
|
-
|
|
395
|
-
off(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | EventListenerOptions): this;
|
|
396
|
-
off<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | EventListenerOptions): this;
|
|
397
|
-
|
|
398
|
-
once(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | AddEventListenerOptions): this;
|
|
399
|
-
once<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | AddEventListenerOptions): this;
|
|
400
354
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { isBoolean } from "#lib/native";
|
|
2
|
+
|
|
3
|
+
export class $EventTarget<EvMap = {}> {
|
|
4
|
+
node: EventTarget;
|
|
5
|
+
constructor(node: EventTarget) {
|
|
6
|
+
this.node = node;
|
|
7
|
+
if (node !== window) (node as Mutable<EventTarget>).$ = this;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
on(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | AddEventListenerOptions): this {
|
|
11
|
+
return this.addEventListener(type, listener, options);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
off(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | EventListenerOptions): this {
|
|
15
|
+
return this.removeEventListener(type, listener, options);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
once(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | AddEventListenerOptions): this {
|
|
19
|
+
return this.on(type, listener, { once: true, ...(isBoolean(options) ? {capture: options} : options ?? {}) })
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type $Event<E extends $EventTarget, Ev = any> = Ev & {currentTarget: {$: E}};
|
|
24
|
+
export type $EventListener<E extends $EventTarget, Ev> = (event: $Event<E, Ev>) => void;
|
|
25
|
+
export type $EventListenerObject<E extends $EventTarget, Ev> = { handleEvent(object: $Event<E, Ev>): void; }
|
|
26
|
+
|
|
27
|
+
export interface $EventTarget<EvMap = {}> {
|
|
28
|
+
/** {@link EventTarget.addEventListener} */
|
|
29
|
+
addEventListener<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | AddEventListenerOptions): this;
|
|
30
|
+
addEventListener(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | AddEventListenerOptions): this;
|
|
31
|
+
/** {@link EventTarget.removeEventListener} */
|
|
32
|
+
removeEventListener<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | EventListenerOptions): this;
|
|
33
|
+
removeEventListener(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | EventListenerOptions): this;
|
|
34
|
+
/** {@link EventTarget.dispatchEvent} */
|
|
35
|
+
dispatchEvent(event: Event): boolean;
|
|
36
|
+
|
|
37
|
+
on<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | AddEventListenerOptions): this;
|
|
38
|
+
on(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | AddEventListenerOptions): this;
|
|
39
|
+
|
|
40
|
+
off<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | EventListenerOptions): this;
|
|
41
|
+
off(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | EventListenerOptions): this;
|
|
42
|
+
|
|
43
|
+
once<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | AddEventListenerOptions): this;
|
|
44
|
+
once(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | AddEventListenerOptions): this;
|
|
45
|
+
}
|
package/src/node/$Node.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { chain } from "#lib/chain";
|
|
2
2
|
import { _document } from "#lib/env";
|
|
3
|
-
import { _Array_from, _instanceof, _JSON_stringify, _null, forEach, isFunction, isNull,
|
|
4
|
-
import {
|
|
3
|
+
import { _Array_from, _instanceof, _JSON_stringify, _null, _Promise, forEach, isFunction, isNull, isUndefined } from "#lib/native";
|
|
4
|
+
import { toArray } from "#lib/toArray";
|
|
5
|
+
import { $EventTarget } from "./$EventTarget";
|
|
5
6
|
|
|
6
|
-
export class $Node {
|
|
7
|
-
node: Node & ChildNode;
|
|
7
|
+
export class $Node<EvMap = {}> extends $EventTarget<EvMap> {
|
|
8
|
+
declare node: Node & ChildNode & ParentNode;
|
|
9
|
+
static processors = new Set<$NodeContentProcessor>();
|
|
10
|
+
static setters = new Set<$NodeSetterHandler>();
|
|
8
11
|
constructor(node: Node & ChildNode) {
|
|
9
|
-
|
|
10
|
-
//@ts-expect-error
|
|
11
|
-
this.node.$ = this;
|
|
12
|
+
super(node);
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
content(children: $NodeContentResolver<this>) {
|
|
@@ -20,7 +21,10 @@ export class $Node {
|
|
|
20
21
|
|
|
21
22
|
insert(resolver: $NodeContentResolver<this>, position = -1) {
|
|
22
23
|
// process nodes
|
|
23
|
-
forEach(
|
|
24
|
+
forEach(toArray(resolver), resolve_child => forEach($Node.process(this, resolve_child), $node => {
|
|
25
|
+
$Node.append(this, $node, position);
|
|
26
|
+
if (position >= 0) position++;
|
|
27
|
+
}));
|
|
24
28
|
return this;
|
|
25
29
|
}
|
|
26
30
|
|
|
@@ -33,7 +37,7 @@ export class $Node {
|
|
|
33
37
|
replace($node: $NodeContentResolver<$Node>) {
|
|
34
38
|
if ($node)
|
|
35
39
|
this.replaceWith(
|
|
36
|
-
|
|
40
|
+
...toArray($Node.process(this, $node)).filter($node => $node).map($node => $node?.node) as Node[]
|
|
37
41
|
)
|
|
38
42
|
return this;
|
|
39
43
|
}
|
|
@@ -58,37 +62,18 @@ export class $Node {
|
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
static process<T extends $Node>($node: T, content: $NodeContentResolver<any>): Array<$Node | undefined | null> {
|
|
65
|
+
for (const processor of this.processors) {
|
|
66
|
+
const result = processor($node, content);
|
|
67
|
+
if (result) return result;
|
|
68
|
+
}
|
|
61
69
|
if (isUndefined(content) || isNull(content) || _instanceof(content, $Node)) return [content];
|
|
62
70
|
// is Promise
|
|
63
|
-
if (_instanceof(content,
|
|
71
|
+
if (_instanceof(content, _Promise)) return [$('async').await(content, ($async, $child) => $async.replace($child as any))];
|
|
64
72
|
// is SignalFunction or ContentHandler
|
|
65
73
|
if (isFunction(content)) {
|
|
66
|
-
const
|
|
67
|
-
if (_instanceof(
|
|
68
|
-
|
|
69
|
-
if (_instanceof(resolver, $Node)) {
|
|
70
|
-
// handler signal $Node result
|
|
71
|
-
let node = resolver;
|
|
72
|
-
const set = (value: any) => {
|
|
73
|
-
node.replace(value);
|
|
74
|
-
node = value;
|
|
75
|
-
}
|
|
76
|
-
signal.subscribe(set);
|
|
77
|
-
return [resolver];
|
|
78
|
-
} else {
|
|
79
|
-
// handler signal other type result
|
|
80
|
-
const $text = _document ? new $Text() : $('signal').attr({ type: typeof signal.value() });
|
|
81
|
-
const set = (value: any) => $text.textContent(isObject(value) ? _JSON_stringify(value) : value);
|
|
82
|
-
if (_instanceof($text, $Text)) $text.signals.add(signal);
|
|
83
|
-
signal.subscribe(set);
|
|
84
|
-
set(resolver);
|
|
85
|
-
return [$text];
|
|
86
|
-
}
|
|
87
|
-
} else {
|
|
88
|
-
const _content = content($node) as $NodeContentResolver<$Node>;
|
|
89
|
-
if (_instanceof(_content, Promise)) return this.process($node, _content as any);
|
|
90
|
-
else return $.toArray(_content).map(content => this.process($node, content)).flat();
|
|
91
|
-
}
|
|
74
|
+
const _content = content($node) as $NodeContentResolver<$Node>;
|
|
75
|
+
if (_instanceof(_content, _Promise)) return this.process($node, _content as any);
|
|
76
|
+
else return toArray(_content).map(content => this.process($node, content)).flat();
|
|
92
77
|
}
|
|
93
78
|
// is nested array
|
|
94
79
|
if (_instanceof(content, Array)) return content.map(c => this.process($node, c)).flat();
|
|
@@ -109,17 +94,18 @@ export class $Node {
|
|
|
109
94
|
}
|
|
110
95
|
|
|
111
96
|
export class $Text extends $Node {
|
|
112
|
-
signals = new Set<Signal<any>>();
|
|
113
97
|
constructor(textContent?: string) {
|
|
114
98
|
super(new Text(textContent));
|
|
115
99
|
}
|
|
116
100
|
}
|
|
117
101
|
|
|
102
|
+
export type $NodeSetterHandler = (value: any, set: (value: any) => void) => any;
|
|
103
|
+
export type $NodeContentProcessor = <N extends $Node>($node: N, content: $NodeContentResolver<N>) => Array<$Node | undefined | null> | void | undefined;
|
|
118
104
|
export type $NodeContentHandler<T extends $Node> = ($node: T) => OrPromise<$NodeContentResolver<T>>;
|
|
119
|
-
export type $NodeContentTypes = $Node | string | number | boolean |
|
|
105
|
+
export type $NodeContentTypes = $Node | string | number | boolean | $.$NodeContentTypeExtends | null | undefined;
|
|
120
106
|
export type $NodeContentResolver<T extends $Node> = OrPromise<$NodeContentTypes | $NodeContentHandler<T> | $NodeContentResolver<T>[]>;
|
|
121
107
|
|
|
122
|
-
export interface $Node {
|
|
108
|
+
export interface $Node<EvMap = {}> extends $EventTarget<EvMap> {
|
|
123
109
|
/** {@link Node.baseURI} */
|
|
124
110
|
readonly baseURI: string;
|
|
125
111
|
/** {@link Node.childNodes} */
|
|
@@ -144,13 +130,21 @@ export interface $Node {
|
|
|
144
130
|
readonly parentNode?: ParentNode | null;
|
|
145
131
|
/** {@link Node.previousSibling} */
|
|
146
132
|
readonly previousSibling?: ChildNode | null;
|
|
133
|
+
/** {@link ParentNode.childElementCount} */
|
|
134
|
+
readonly childElementCount: number;
|
|
135
|
+
/** {@link ParentNode.children} */
|
|
136
|
+
readonly children: HTMLCollection;
|
|
137
|
+
/** {@link ParentNode.firstElementChild} */
|
|
138
|
+
readonly firstElementChild: Element | null;
|
|
139
|
+
/** {@link ParentNode.lastElementChild} */
|
|
140
|
+
readonly lastElementChild: Element | null;
|
|
147
141
|
|
|
148
142
|
/** {@link Node.appendChild} */
|
|
149
143
|
appendChild<T extends Node>(node: T): T;
|
|
150
144
|
/** {@link Node.cloneNode} */
|
|
151
145
|
cloneNode(subtree?: boolean): Node;
|
|
152
146
|
/** {@link Node.compareDocumentPosition} */
|
|
153
|
-
compareDocumentPosition(other: Node): number;
|
|
147
|
+
compareDocumentPosition(other: $EventTarget | Node): number;
|
|
154
148
|
/** {@link Node.getRootNode} */
|
|
155
149
|
getRootNode(options?: GetRootNodeOptions): Node;
|
|
156
150
|
/** {@link Node.hasChildNodes} */
|
|
@@ -160,9 +154,9 @@ export interface $Node {
|
|
|
160
154
|
/** {@link Node.isDefaultNamespace} */
|
|
161
155
|
isDefaultNamespace(namespace: string | null): boolean;
|
|
162
156
|
/** {@link Node.isEqualNode} */
|
|
163
|
-
isEqualNode(otherNode: Node | null): boolean;
|
|
157
|
+
isEqualNode(otherNode: $EventTarget | Node | null): boolean;
|
|
164
158
|
/** {@link Node.isSameNode} */
|
|
165
|
-
isSameNode(otherNode: Node | null): boolean;
|
|
159
|
+
isSameNode(otherNode: $EventTarget | Node | null): boolean;
|
|
166
160
|
/** {@link Node.lookupNamespaceURI} */
|
|
167
161
|
lookupNamespaceURI(prefix: string | null): string | null;
|
|
168
162
|
/** {@link Node.lookupPrefix} */
|
|
@@ -173,20 +167,34 @@ export interface $Node {
|
|
|
173
167
|
removeChild<T extends Node>(child: T): T;
|
|
174
168
|
/** {@link Node.replaceChild} */
|
|
175
169
|
replaceChild<T extends Node>(node: Node, child: T): T;
|
|
176
|
-
/** {@link Node.
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
170
|
+
/** {@link Node.contains} */
|
|
171
|
+
contains(other: $EventTarget | Node | null | undefined): boolean;
|
|
172
|
+
|
|
173
|
+
/** {@link ChildNode.after} */
|
|
174
|
+
after(...nodes: ($EventTarget | Node | string)[]): this;
|
|
175
|
+
/** {@link ChildNode.before} */
|
|
176
|
+
before(...nodes: ($EventTarget | Node | string)[]): this;
|
|
177
|
+
/** {@link ChildNode.remove} */
|
|
181
178
|
remove(): this;
|
|
182
|
-
/** {@link
|
|
183
|
-
replaceWith(...nodes: (Node | string)[]): this;
|
|
184
|
-
/** {@link
|
|
185
|
-
|
|
186
|
-
/** {@link
|
|
187
|
-
|
|
188
|
-
/** {@link
|
|
189
|
-
|
|
179
|
+
/** {@link ChildNode.replaceWith} */
|
|
180
|
+
replaceWith(...nodes: ($EventTarget | Node | string)[]): this;
|
|
181
|
+
/** {@link ParentNode.append} */
|
|
182
|
+
append(...nodes: ($EventTarget | Node | string)[]): this;
|
|
183
|
+
/** {@link ParentNode.prepend} */
|
|
184
|
+
prepend(...nodes: ($EventTarget | Node | string)[]): this;
|
|
185
|
+
/** {@link ParentNode.querySelector} */
|
|
186
|
+
querySelector<K extends keyof HTMLElementTagNameMap>(selectors: K): HTMLElementTagNameMap[K] | null;
|
|
187
|
+
querySelector<K extends keyof SVGElementTagNameMap>(selectors: K): SVGElementTagNameMap[K] | null;
|
|
188
|
+
querySelector<K extends keyof MathMLElementTagNameMap>(selectors: K): MathMLElementTagNameMap[K] | null;
|
|
189
|
+
querySelector<E extends Element = Element>(selectors: string): E | null;
|
|
190
|
+
/** {@link ParentNode.querySelectorAll} */
|
|
191
|
+
querySelectorAll<K extends keyof HTMLElementTagNameMap>(selectors: K): NodeListOf<HTMLElementTagNameMap[K]>;
|
|
192
|
+
querySelectorAll<K extends keyof SVGElementTagNameMap>(selectors: K): NodeListOf<SVGElementTagNameMap[K]>;
|
|
193
|
+
querySelectorAll<K extends keyof MathMLElementTagNameMap>(selectors: K): NodeListOf<MathMLElementTagNameMap[K]>;
|
|
194
|
+
querySelectorAll<K extends keyof HTMLElementDeprecatedTagNameMap>(selectors: K): NodeListOf<HTMLElementDeprecatedTagNameMap[K]>;
|
|
195
|
+
querySelectorAll<E extends Element = Element>(selectors: string): NodeListOf<E>;
|
|
196
|
+
/** {@link ParentNode.replaceChildren} */
|
|
197
|
+
replaceChildren(...nodes: ($EventTarget | Node | string)[]): this;
|
|
190
198
|
|
|
191
199
|
/** {@link Node.nodeValue} */
|
|
192
200
|
nodeValue(nodeValue: $Parameter<string | null>): this;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { chain } from "#lib/chain";
|
|
2
|
+
import { forEach, _Array_from, _instanceof, _null } from "#lib/native";
|
|
3
|
+
import { toArray } from "#lib/toArray";
|
|
4
|
+
import { $HTMLElement } from "#node/$HTMLElement";
|
|
5
|
+
import { $Node, type $NodeContentResolver } from "#node/$Node";
|
|
6
|
+
|
|
7
|
+
export class $Virtual<Ele extends HTMLElement = HTMLElement, EvMap = HTMLElementEventMap> extends $HTMLElement<Ele, EvMap> {
|
|
8
|
+
nodes = new Set<$Node>();
|
|
9
|
+
hiddenNodes = new Set<$Node>();
|
|
10
|
+
constructor(resolver: string | Ele) {
|
|
11
|
+
super(resolver);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
content(children: $NodeContentResolver<this>) {
|
|
15
|
+
return chain(this, _null, _null, children, children => {
|
|
16
|
+
this.nodes.clear();
|
|
17
|
+
forEach(this.childNodes, node => node.remove());
|
|
18
|
+
this.insert(children);
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
insert(resolver: $NodeContentResolver<this>, position = -1) {
|
|
23
|
+
// process nodes
|
|
24
|
+
forEach(toArray(resolver), resolve_child => {
|
|
25
|
+
forEach($Node.process(this, resolve_child), $node => {
|
|
26
|
+
$Virtual.append(this, $node, position)
|
|
27
|
+
if (position >= 0) position++;
|
|
28
|
+
})
|
|
29
|
+
});
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
hide($node?: $Node | null) {
|
|
34
|
+
if ($node && this.nodes.has($node)) this.hiddenNodes.add($node);
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
show($node?: $Node | null) {
|
|
39
|
+
if ($node) this.hiddenNodes.delete($node);
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
render() {
|
|
44
|
+
// remove hidden node
|
|
45
|
+
forEach(this.childNodes, node => this.hiddenNodes.has($(node)) && node.remove());
|
|
46
|
+
// add visible node with position
|
|
47
|
+
forEach(this.nodes, ($node, i) => {
|
|
48
|
+
if (
|
|
49
|
+
!this.hiddenNodes.has($node) // node is not hidden
|
|
50
|
+
&& !$node.inDOM() // node is not in dom tree
|
|
51
|
+
&& $(this.childNodes).at(i) !== $node // node not matched at position
|
|
52
|
+
) $Node.append(this, $node, i);
|
|
53
|
+
})
|
|
54
|
+
return this;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static append($node: $Virtual, child: $Node | undefined | null, position: number) {
|
|
58
|
+
if (child) {
|
|
59
|
+
const childList = _Array_from($node.nodes);
|
|
60
|
+
if (!childList.at(position)) childList.push(child);
|
|
61
|
+
else childList.splice(position >= 0 ? position : childList.length + 1 + position, 0, child);
|
|
62
|
+
$node.nodes = new Set(childList);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
package/src/node.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { $HTMLElement } from '#node/$HTMLElement';
|
|
2
|
-
import {
|
|
2
|
+
import { assignProperties } from '#lib/assignProperties';
|
|
3
3
|
import { $Element } from '#node/$Element';
|
|
4
4
|
import { $Node, $Text } from '#node/$Node';
|
|
5
|
+
import { $EventTarget } from '#node/$EventTarget';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
assignProperties(EventTarget, $EventTarget);
|
|
8
|
+
assignProperties(Node, $Node);
|
|
9
|
+
assignProperties(Text, $Text);
|
|
10
|
+
assignProperties(Element, $Element);
|
|
11
|
+
assignProperties(HTMLElement, $HTMLElement);
|