amateras 0.1.1 → 0.3.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.
Files changed (68) hide show
  1. package/README.md +25 -8
  2. package/ext/css/src/index.ts +103 -49
  3. package/ext/css/src/lib/colorAssign.ts +6 -0
  4. package/ext/css/src/lib/colors/amber.ts +25 -0
  5. package/ext/css/src/lib/colors/blackwhite.ts +13 -0
  6. package/ext/css/src/lib/colors/blue.ts +25 -0
  7. package/ext/css/src/lib/colors/cyan.ts +25 -0
  8. package/ext/css/src/lib/colors/emerald.ts +25 -0
  9. package/ext/css/src/lib/colors/fuchsia.ts +25 -0
  10. package/ext/css/src/lib/colors/gray.ts +25 -0
  11. package/ext/css/src/lib/colors/green.ts +25 -0
  12. package/ext/css/src/lib/colors/indigo.ts +25 -0
  13. package/ext/css/src/lib/colors/lime.ts +25 -0
  14. package/ext/css/src/lib/colors/neutral.ts +25 -0
  15. package/ext/css/src/lib/colors/orange.ts +25 -0
  16. package/ext/css/src/lib/colors/pink.ts +25 -0
  17. package/ext/css/src/lib/colors/purple.ts +25 -0
  18. package/ext/css/src/lib/colors/red.ts +25 -0
  19. package/ext/css/src/lib/colors/rose.ts +25 -0
  20. package/ext/css/src/lib/colors/sky.ts +25 -0
  21. package/ext/css/src/lib/colors/slate.ts +25 -0
  22. package/ext/css/src/lib/colors/stone.ts +25 -0
  23. package/ext/css/src/lib/colors/teal.ts +25 -0
  24. package/ext/css/src/lib/colors/violet.ts +25 -0
  25. package/ext/css/src/lib/colors/yellow.ts +25 -0
  26. package/ext/css/src/lib/colors/zinc.ts +25 -0
  27. package/ext/css/src/lib/colors.ts +23 -0
  28. package/ext/css/src/structure/$CSSKeyframesRule.ts +2 -5
  29. package/ext/css/src/structure/$CSSMediaRule.ts +3 -23
  30. package/ext/css/src/structure/$CSSRule.ts +6 -18
  31. package/ext/css/src/structure/$CSSStyleRule.ts +10 -12
  32. package/ext/html/html.ts +24 -58
  33. package/ext/html/node/$Anchor.ts +49 -0
  34. package/ext/html/node/$Canvas.ts +16 -0
  35. package/ext/html/node/$Dialog.ts +16 -0
  36. package/ext/html/node/$Form.ts +16 -0
  37. package/ext/html/node/$Image.ts +72 -0
  38. package/ext/html/node/$Input.ts +169 -0
  39. package/ext/html/node/$Label.ts +16 -0
  40. package/ext/html/node/$Media.ts +16 -0
  41. package/ext/html/node/$OptGroup.ts +23 -0
  42. package/ext/html/node/$Option.ts +40 -0
  43. package/ext/html/node/$Select.ts +76 -0
  44. package/ext/html/node/$TextArea.ts +16 -0
  45. package/ext/router/README.md +81 -0
  46. package/ext/router/index.ts +66 -0
  47. package/ext/router/node/Page.ts +27 -0
  48. package/ext/router/node/Route.ts +53 -0
  49. package/ext/router/node/Router.ts +138 -0
  50. package/ext/router/node/RouterAnchor.ts +8 -0
  51. package/ext/ssr/env.ts +61 -0
  52. package/ext/ssr/index.ts +47 -0
  53. package/ext/ssr/package.json +10 -0
  54. package/package.json +8 -4
  55. package/src/core.ts +43 -30
  56. package/src/global.ts +6 -0
  57. package/src/lib/assign.ts +4 -3
  58. package/src/lib/assignHelper.ts +11 -13
  59. package/src/lib/native.ts +14 -3
  60. package/src/node/$Element.ts +204 -23
  61. package/src/node/$HTMLElement.ts +76 -0
  62. package/src/node/$Node.ts +145 -53
  63. package/src/node/node.ts +8 -6
  64. package/src/structure/Signal.ts +4 -4
  65. package/tsconfig.json +1 -1
  66. package/ext/css/src/structure/$CSSKeyframeRule.ts +0 -13
  67. package/ext/html/node/$HTMLElement.ts +0 -7
  68. package/ext/html/node/type.ts +0 -96
@@ -1,40 +1,41 @@
1
1
  import { Signal } from "#structure/Signal";
2
2
  import { $Node } from "#node/$Node";
3
- import { _Array_from, _instanceof, _Object_entries, _Object_fromEntries, isUndefined } from "#lib/native";
3
+ import { _Array_from, _document, _instanceof, _Object_assign, _Object_entries, _Object_fromEntries, isFunction, isString, isUndefined } from "#lib/native";
4
4
 
5
- export class $Element<Ele extends Element = Element> extends $Node {
6
- listeners = new Map<Function, (event: Event) => void>;
5
+ export class $Element<Ele extends Element = Element, EvMap = ElementEventMap> extends $Node {
7
6
  declare node: Ele
8
7
  constructor(resolver: Ele | string) {
9
- super(_instanceof(resolver, Element) ? resolver : document.createElement(resolver) as unknown as Ele)
8
+ super(_instanceof(resolver, Element) ? resolver : createNode(resolver) as unknown as Ele)
10
9
  //@ts-expect-error
11
10
  this.node.$ = this;
12
11
  }
13
12
 
14
13
  attr(): {[key: string]: string};
14
+ attr(key: string): string | null;
15
15
  attr(obj: {[key: string]: string | number | boolean | Signal<any>}): this;
16
- attr(obj?: {[key: string]: string | number | boolean | Signal<any>}) {
17
- if (!arguments.length) return _Object_fromEntries(_Array_from(this.node.attributes).map(attr => [attr.name, attr.value]));
18
- if (obj) for (let [key, value] of _Object_entries(obj)) {
19
- const set = (value: any) => isUndefined(value) && this.node.setAttribute(key, `${value}`)
16
+ attr(resolver?: {[key: string]: string | number | boolean | Signal<any>} | string) {
17
+ if (!arguments.length) return _Object_fromEntries(_Array_from(this.attributes).map(attr => [attr.name, attr.value]));
18
+ if (isString(resolver)) return this.getAttribute(resolver);
19
+ if (resolver) for (let [key, value] of _Object_entries(resolver)) {
20
+ const set = (value: any) => !isUndefined(value) && this.setAttribute(key, `${value}`)
20
21
  if (_instanceof(value, Signal)) value = value.subscribe(set).value();
21
22
  set(value);
22
23
  }
23
24
  return this;
24
25
  }
25
26
 
26
- class(...token: string[]) {
27
- this.node.classList = token.join(' ');
27
+ class(...token: (string | null | undefined)[]) {
28
+ this.classList(token.filter(isString).join(' '));
28
29
  return this;
29
30
  }
30
31
 
31
- addClass(...token: string[]) {
32
- this.node.classList.add(...token);
32
+ addClass(...token: (string | null | undefined)[]) {
33
+ this.classList().add(...token.filter(isString));
33
34
  return this;
34
35
  }
35
36
 
36
- removeClass(...token: string[]) {
37
- this.node.classList.remove(...token);
37
+ removeClass(...token: (string | null | undefined)[]) {
38
+ this.classList().remove(...token.filter(isString));
38
39
  return this;
39
40
  }
40
41
 
@@ -43,18 +44,198 @@ export class $Element<Ele extends Element = Element> extends $Node {
43
44
  return this;
44
45
  }
45
46
 
46
- on<K extends keyof HTMLElementEventMap>(type: K, listener: ($node: this, event: Event) => void, options?: boolean | AddEventListenerOptions) {
47
- const handler = (event: Event) => listener(this, event);
48
- this.listeners.set(listener, handler);
49
- this.node.addEventListener(type, handler, options);
47
+ on<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | AddEventListenerOptions) {
48
+ this.node.addEventListener(type as string, listener as any, options);
50
49
  return this;
51
50
  }
52
51
 
53
- off<K extends keyof HTMLElementEventMap>(type: K, listener: ($node: this, event: Event) => void, options?: boolean | EventListenerOptions) {
54
- const handler = this.listeners.get(listener);
55
- if (handler) this.node.removeEventListener(type, handler, options);
56
- this.listeners.delete(listener);
52
+ off<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | EventListenerOptions) {
53
+ this.node.removeEventListener(type as string, listener as any, options);
57
54
  return this;
58
55
  }
59
- once() {}
56
+
57
+ once<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | AddEventListenerOptions) {
58
+ const handler = (event: $Event<any>) => {
59
+ this.off(type, handler, options);
60
+ isFunction(listener) ? listener(event) : listener.handleEvent(event);
61
+ }
62
+ this.on(type, handler, options);
63
+ return this;
64
+ }
65
+
66
+ toString() {
67
+ return this.outerHTML();
68
+ }
69
+ }
70
+
71
+ export type EventMap = {[key: string]: Event}
72
+ export type $Event<E extends $Element, Ev = any> = Ev & {target: {$: E}};
73
+ export type $EventListener<E extends $Element, Ev> = (event: $Event<E, Ev>) => void;
74
+ export type $EventListenerObject<E extends $Element, Ev> = { handleEvent(object: $Event<E, Ev>): void; }
75
+
76
+ function createNode(nodeName: string) {
77
+ //@ts-expect-error
78
+ return !_document ? new Node(nodeName) as unknown as Node & ChildNode : _document.createElement(nodeName);
79
+ }
80
+
81
+ export interface $Element<Ele extends Element, EvMap> {
82
+ /** {@link Element.attributes} */
83
+ readonly attributes: NamedNodeMap;
84
+ /** {@link Element.clientHeight} */
85
+ readonly clientHeight: number;
86
+ /** {@link Element.clientLeft} */
87
+ readonly clientLeft: number;
88
+ /** {@link Element.clientTop} */
89
+ readonly clientTop: number;
90
+ /** {@link Element.clientWidth} */
91
+ readonly clientWidth: number;
92
+ /** {@link Element.currentCSSZoom} */
93
+ readonly currentCSSZoom: number;
94
+ /** {@link Element.localName} */
95
+ readonly localName: string;
96
+ /** {@link Element.namespaceURI} */
97
+ readonly namespaceURI: string | null;
98
+ /** {@link Element.prefix} */
99
+ readonly prefix: string | null;
100
+ /** {@link Element.ownerDocument} */
101
+ readonly ownerDocument: Document;
102
+ /** {@link Element.scrollHeight} */
103
+ readonly scrollHeight: number;
104
+ /** {@link Element.scrollWidth} */
105
+ readonly scrollWidth: number;
106
+ /** {@link Element.shadowRoot} */
107
+ readonly shadowRoot: ShadowRoot | null;
108
+ /** {@link Element.tagName} */
109
+ readonly tagName: string;
110
+
111
+ /** {@link Element.attachShadow} */
112
+ attachShadow(init: ShadowRootInit): ShadowRoot;
113
+ /** {@link Element.checkVisibility} */
114
+ checkVisibility(options?: CheckVisibilityOptions): boolean;
115
+ /** {@link Element.closest} */
116
+ closest<K extends keyof HTMLElementTagNameMap>(selector: K): HTMLElementTagNameMap[K] | null;
117
+ closest<K extends keyof SVGElementTagNameMap>(selector: K): SVGElementTagNameMap[K] | null;
118
+ closest<K extends keyof MathMLElementTagNameMap>(selector: K): MathMLElementTagNameMap[K] | null;
119
+ closest<E extends Element = Element>(selectors: string): E | null;
120
+ /** {@link Element.computedStyleMap} */
121
+ computedStyleMap(): StylePropertyMapReadOnly;
122
+ /** {@link Element.getAttribute} */
123
+ getAttribute(qualifiedName: string): string | null;
124
+ /** {@link Element.getAttributeNS} */
125
+ getAttributeNS(namespace: string | null, localName: string): string | null;
126
+ /** {@link Element.getAttributeNames} */
127
+ getAttributeNames(): string[];
128
+ /** {@link Element.getAttributeNode} */
129
+ getAttributeNode(qualifiedName: string): Attr | null;
130
+ /** {@link Element.getAttributeNodeNS} */
131
+ getAttributeNodeNS(namespace: string | null, localName: string): Attr | null;
132
+ /** {@link Element.getBoundingClientRect} */
133
+ getBoundingClientRect(): DOMRect;
134
+ /** {@link Element.getClientRects} */
135
+ getClientRects(): DOMRectList;
136
+ /** {@link Element.getElementsByClassName} */
137
+ getElementsByClassName(classNames: string): HTMLCollectionOf<Element>;
138
+ /** {@link Element.getElementsByTagName} */
139
+ getElementsByTagName<K extends keyof HTMLElementTagNameMap>(qualifiedName: K): HTMLCollectionOf<HTMLElementTagNameMap[K]>;
140
+ getElementsByTagName<K extends keyof SVGElementTagNameMap>(qualifiedName: K): HTMLCollectionOf<SVGElementTagNameMap[K]>;
141
+ getElementsByTagName<K extends keyof MathMLElementTagNameMap>(qualifiedName: K): HTMLCollectionOf<MathMLElementTagNameMap[K]>;
142
+ getElementsByTagName(qualifiedName: string): HTMLCollectionOf<Element>;
143
+ /** {@link Element.getElementsByTagNameNS} */
144
+ getElementsByTagNameNS(namespaceURI: "http://www.w3.org/1999/xhtml", localName: string): HTMLCollectionOf<HTMLElement>;
145
+ getElementsByTagNameNS(namespaceURI: "http://www.w3.org/2000/svg", localName: string): HTMLCollectionOf<SVGElement>;
146
+ getElementsByTagNameNS(namespaceURI: "http://www.w3.org/1998/Math/MathML", localName: string): HTMLCollectionOf<MathMLElement>;
147
+ getElementsByTagNameNS(namespace: string | null, localName: string): HTMLCollectionOf<Element>;
148
+ /** {@link Element.getHTML} */
149
+ getHTML(options?: GetHTMLOptions): string;
150
+ /** {@link Element.hasAttribute} */
151
+ hasAttribute(qualifiedName: string): boolean;
152
+ /** {@link Element.hasAttributeNS} */
153
+ hasAttributeNS(namespace: string | null, localName: string): boolean;
154
+ /** {@link Element.hasAttributes} */
155
+ hasAttributes(): boolean;
156
+ /** {@link Element.hasPointerCapture} */
157
+ hasPointerCapture(pointerId: number): boolean;
158
+ /** {@link Element.insertAdjacentElement} */
159
+ insertAdjacentElement(where: InsertPosition, element: Element): Element | null;
160
+ /** {@link Element.insertAdjacentHTML} */
161
+ insertAdjacentHTML(position: InsertPosition, string: string): this;
162
+ /** {@link Element.insertAdjacentText} */
163
+ insertAdjacentText(where: InsertPosition, data: string): this;
164
+ /** {@link Element.matches} */
165
+ matches(selectors: string): boolean;
166
+ /** {@link Element.releasePointerCapture} */
167
+ releasePointerCapture(pointerId: number): this;
168
+ /** {@link Element.removeAttribute} */
169
+ removeAttribute(qualifiedName: string): this;
170
+ /** {@link Element.removeAttributeNS} */
171
+ removeAttributeNS(namespace: string | null, localName: string): this;
172
+ /** {@link Element.removeAttributeNode} */
173
+ removeAttributeNode(attr: Attr): Attr;
174
+ /** {@link Element.requestFullscreen} */
175
+ requestFullscreen(options?: FullscreenOptions): Promise<this>;
176
+ /** {@link Element.requestPointerLock} */
177
+ requestPointerLock(options?: PointerLockOptions): Promise<this>;
178
+ /** {@link Element.scroll} */
179
+ scroll(options?: ScrollToOptions): this;
180
+ scroll(x: number, y: number): this;
181
+ /** {@link Element.scrollBy} */
182
+ scrollBy(options?: ScrollToOptions): this;
183
+ scrollBy(x: number, y: number): this;
184
+ /** {@link Element.scrollIntoView} */
185
+ scrollIntoView(arg?: boolean | ScrollIntoViewOptions): this;
186
+ /** {@link Element.scrollTo} */
187
+ scrollTo(options?: ScrollToOptions): this;
188
+ scrollTo(x: number, y: number): this;
189
+ /** {@link Element.setAttribute} */
190
+ setAttribute(qualifiedName: string, value: string): this;
191
+ /** {@link Element.setAttributeNS} */
192
+ setAttributeNS(namespace: string | null, qualifiedName: string, value: string): this;
193
+ /** {@link Element.setAttributeNode} */
194
+ setAttributeNode(attr: Attr): Attr | null;
195
+ /** {@link Element.setAttributeNodeNS} */
196
+ setAttributeNodeNS(attr: Attr): Attr | null;
197
+ /** {@link Element.setHTMLUnsafe} */
198
+ setHTMLUnsafe(html: string): this;
199
+ /** {@link Element.setPointerCapture} */
200
+ setPointerCapture(pointerId: number): this;
201
+ /** {@link Element.toggleAttribute} */
202
+ toggleAttribute(qualifiedName: string, force?: boolean): boolean;
203
+
204
+ /** {@link Element.classList} */
205
+ classList(): DOMTokenList;
206
+ classList(value: $Parameter<string>): this;
207
+ /** {@link Element.className} */
208
+ className(): string;
209
+ className(value: $Parameter<string>): this;
210
+ /** {@link Element.id} */
211
+ id(): string;
212
+ id(id: $Parameter<string>): this;
213
+ /** {@link Element.innerHTML} */
214
+ innerHTML(): string;
215
+ innerHTML(innerHTML: $Parameter<string>): this;
216
+ /** {@link Element.outerHTML} */
217
+ outerHTML(): string;
218
+ outerHTML(outerHTML: $Parameter<string>): this;
219
+ /** {@link Element.part} */
220
+ part(): DOMTokenList;
221
+ part(part: $Parameter<string>): this;
222
+ /** {@link Element.scrollLeft} */
223
+ scrollLeft(): number;
224
+ scrollLeft(scrollLeft: $Parameter<number>): this;
225
+ /** {@link Element.scrollTop} */
226
+ scrollTop(): number;
227
+ scrollTop(scrollTop: $Parameter<number>): this;
228
+ /** {@link Element.slot} */
229
+ slot(): string;
230
+ slot(slot: $Parameter<string>): this;
231
+
232
+
233
+ on(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | AddEventListenerOptions): this;
234
+ on<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | AddEventListenerOptions): this;
235
+
236
+ off(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | EventListenerOptions): this;
237
+ off<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | EventListenerOptions): this;
238
+
239
+ once(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | AddEventListenerOptions): this;
240
+ once<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | AddEventListenerOptions): this;
60
241
  }
@@ -0,0 +1,76 @@
1
+ import { $Element } from "#node/$Element";
2
+
3
+ export class $HTMLElement<Ele extends HTMLElement = HTMLElement, EvMap = HTMLElementEventMap> extends $Element<Ele, EvMap> {
4
+ constructor(resolver: string | Ele) {
5
+ super(resolver);
6
+ }
7
+ }
8
+
9
+ export interface $HTMLElement<Ele extends HTMLElement = HTMLElement, EvMap = HTMLElementEventMap> extends $Element<Ele, EvMap> {
10
+ /** {@link HTMLElement.accessKeyLabel} */
11
+ readonly accessKeyLabel: string;
12
+ /** {@link HTMLElement.offsetHeight} */
13
+ readonly offsetHeight: number;
14
+ /** {@link HTMLElement.offsetLeft} */
15
+ readonly offsetLeft: number;
16
+ /** {@link HTMLElement.offsetParent} */
17
+ readonly offsetParent: Element | null;
18
+ /** {@link HTMLElement.offsetTop} */
19
+ readonly offsetTop: number;
20
+ /** {@link HTMLElement.offsetWidth} */
21
+ readonly offsetWidth: number;
22
+
23
+ /** {@link HTMLElement.attachInternals} */
24
+ attachInternals(): ElementInternals;
25
+ /** {@link HTMLElement.click} */
26
+ click(): this;
27
+ /** {@link HTMLElement.hidePopover} */
28
+ hidePopover(): this;
29
+ /** {@link HTMLElement.showPopover} */
30
+ showPopover(): this;
31
+ /** {@link HTMLElement.togglePopover} */
32
+ togglePopover(options?: boolean): boolean;
33
+
34
+ /** {@link HTMLElement.accessKey} */
35
+ accessKey(): string;
36
+ accessKey(accessKey: $Parameter<string>): this;
37
+ /** {@link HTMLElement.autocapitalize} */
38
+ autocapitalize(): string;
39
+ autocapitalize(autocapitalize: $Parameter<string>): this;
40
+ /** {@link HTMLElement.dir} */
41
+ dir(): string;
42
+ dir(dir: $Parameter<string>): this;
43
+ /** {@link HTMLElement.draggable} */
44
+ draggable(): boolean;
45
+ draggable(draggable: $Parameter<boolean>): this;
46
+ /** {@link HTMLElement.hidden} */
47
+ hidden(): boolean;
48
+ hidden(hidden: $Parameter<boolean>): this;
49
+ /** {@link HTMLElement.inert} */
50
+ inert(): boolean;
51
+ inert(inert: $Parameter<boolean>): this;
52
+ /** {@link HTMLElement.innerText} */
53
+ innerText(): string;
54
+ innerText(innerText: $Parameter<string>): this;
55
+ /** {@link HTMLElement.lang} */
56
+ lang(): string;
57
+ lang(lang: $Parameter<string>): this;
58
+ /** {@link HTMLElement.outerText} */
59
+ outerText(): string;
60
+ outerText(outerText: $Parameter<string>): this;
61
+ /** {@link HTMLElement.popover} */
62
+ popover(): string | null;
63
+ popover(popover: $Parameter<string | null>): this;
64
+ /** {@link HTMLElement.spellcheck} */
65
+ spellcheck(): boolean;
66
+ spellcheck(spellcheck: $Parameter<boolean>): this;
67
+ /** {@link HTMLElement.title} */
68
+ title(): string;
69
+ title(title: $Parameter<string>): this;
70
+ /** {@link HTMLElement.translate} */
71
+ translate(): string;
72
+ translate(translate: $Parameter<boolean>): this;
73
+ /** {@link HTMLElement.writingSuggestions} */
74
+ writingSuggestions(): string;
75
+ writingSuggestions(writingSuggestions: $Parameter<string>): this;
76
+ }
package/src/node/$Node.ts CHANGED
@@ -1,81 +1,173 @@
1
- import { _Array_from, _instanceof, isFunction, isNull, isObject, isUndefined } from "#lib/native";
1
+ import { _Array_from, _document, _instanceof, _JSON_stringify, forEach, isFunction, isNull, isObject, isUndefined } from "#lib/native";
2
2
  import { Signal } from "#structure/Signal";
3
3
 
4
4
  export class $Node {
5
- node: Node;
6
- constructor(node: Node) {
5
+ node: Node & ChildNode;
6
+ constructor(node: Node & ChildNode) {
7
7
  this.node = node;
8
8
  //@ts-expect-error
9
9
  this.node.$ = this;
10
10
  }
11
11
 
12
12
  content(children: $NodeContentResolver<this>) {
13
- _Array_from(this.node.childNodes).forEach(node => node.remove());
13
+ forEach(_Array_from(this.childNodes), node => node.remove());
14
14
  return this.insert(children);
15
15
  }
16
16
 
17
17
  insert(resolver: $NodeContentResolver<this>, position = -1) {
18
- if (isFunction(resolver)) {
19
- const content = resolver(this);
20
- if (_instanceof(content, Promise)) content.then(content => $Node.insertChild(this.node, content, position))
21
- else $Node.insertChild(this.node, content, position);
22
- } else $Node.insertChild(this.node, resolver, position);
18
+ // insert node helper function for depend position
19
+ const appendChild = (children: OrArray<$Node | undefined | null>) => {
20
+ // get child node at position
21
+ const positionChild = _Array_from(this.childNodes).filter(node => node.nodeType !== node.TEXT_NODE).at(position);
22
+ forEach($.toArray(children), child => {
23
+ if (!child) return;
24
+ if (_instanceof(child, Array)) this.insert(child);
25
+ else if (!positionChild) this.appendChild(child.node);
26
+ else this.insertBefore(child.node, position < 0 ? positionChild.nextSibling : positionChild);
27
+ })
28
+ }
29
+ // process nodes
30
+ for (const child of $.toArray(resolver)) !isUndefined(child) && appendChild(processContent(this, child))
23
31
  return this;
24
32
  }
25
33
 
26
34
  await<T>(promise: Promise<T>, callback: ($node: this, result: T) => void): this {
27
- promise.then(result => callback(this, result));
28
- return this;
35
+ return promise.then(result => callback(this, result)), this;
29
36
  }
30
37
 
31
- replace($node: $NodeContentTypes | undefined | null) {
38
+ replace($node: $NodeContentResolver<$Node>) {
32
39
  if (!$node) return this;
33
- this.node.parentNode?.replaceChild($Node.processContent($node), this.node);
34
- return this;
40
+ this.replaceWith(
41
+ ...$.toArray(processContent(this, $node)).filter($node => $node).map($node => $node?.node) as Node[]
42
+ )
43
+ return this;
35
44
  }
36
45
 
37
- static insertChild(node: Node, children: OrArray<OrPromise<$NodeContentTypes>>, position = -1) {
38
- children = $.orArrayResolver(children);
39
- // get child node at position
40
- const positionChild = _Array_from(node.childNodes).filter(node => node.nodeType !== node.TEXT_NODE).at(position);
41
- // insert node helper function for depend position
42
- const append = (child: Node | undefined | null) => {
43
- if (!child) return;
44
- if (!positionChild) node.appendChild(child);
45
- else node.insertBefore(child, position < 0 ? positionChild.nextSibling : positionChild);
46
- }
47
- // process nodes
48
- for (const child of children) !isUndefined(child) && append($Node.processContent(child))
46
+ toString() {
47
+ return this.textContent();
49
48
  }
49
+ }
50
50
 
51
- static processContent(content: $NodeContentTypes): Node;
52
- static processContent(content: undefined | null): undefined | null;
53
- static processContent(content: OrPromise<undefined | null>): undefined | null;
54
- static processContent(content: OrPromise<$NodeContentTypes>): Node;
55
- static processContent(content: OrPromise<$NodeContentTypes | undefined | null>): Node | undefined | null
56
- static processContent(content: OrPromise<$NodeContentTypes | undefined | null>) {
57
- if (isUndefined(content)) return;
58
- if (isNull(content)) return content;
59
- // is $Element
60
- if (_instanceof(content, $Node)) return content.node;
61
- // is Promise
62
- if (_instanceof(content, Promise)) {
63
- const async = $('async').await(content, ($async, $child) => $async.replace($child));
64
- return async.node;
65
- }
66
- // is SignalFunction
67
- if (isFunction(content) && _instanceof((content as $.SignalFunction<any>).signal ,Signal)) {
68
- const text = new Text();
69
- const set = (value: any) => text.textContent = isObject(value) ? JSON.stringify(value) : value;
70
- (content as $.SignalFunction<any>).signal.subscribe(set);
71
- set((content as $.SignalFunction<any>)());
72
- return text;
51
+ function processContent<T extends $Node>($node: T, content: $NodeContentResolver<any>): OrArray<$Node | undefined | null> {
52
+ if (isUndefined(content)) return;
53
+ if (isNull(content)) return content;
54
+ // is $Element
55
+ if (_instanceof(content, $Node)) return content;
56
+ // is Promise
57
+ if (_instanceof(content, Promise)) return $('async').await(content, ($async, $child) => $async.replace($child as any));
58
+ // is SignalFunction or ContentHandler
59
+ if (isFunction(content)) {
60
+ const signal = (content as any).signal;
61
+ if (_instanceof(signal, Signal)) {
62
+ const resolver = (content as $.SignalFunction<any>)();
63
+ if (_instanceof(resolver, $Node)) {
64
+ // handler signal $Node result
65
+ let node = resolver;
66
+ const set = (value: any) => {
67
+ node.replace(value);
68
+ node = value;
69
+ }
70
+ signal.subscribe(set);
71
+ return resolver;
72
+ } else {
73
+ // handler signal other type result
74
+ const $text = _document ? new $Text() : $('signal').attr({ type: typeof signal.value() });
75
+ const set = (value: any) => $text.textContent(isObject(value) ? _JSON_stringify(value) : value);
76
+ if (_instanceof($text, $Text)) $text.signals.add(signal);
77
+ signal.subscribe(set);
78
+ set(resolver);
79
+ return $text;
80
+ }
81
+ } else {
82
+ const _content = content($node) as $NodeContentResolver<$Node>;
83
+ if (_instanceof(_content, Promise)) return processContent($node, _content as any);
84
+ else return $.toArray(_content).map(content => processContent($node, content) as $Node);
73
85
  }
74
- // is string | number | boolean
75
- return new Text(`${content}`);
76
86
  }
87
+ // is nested array
88
+ if (_instanceof(content, Array)) return content.map(c => processContent($node, c) as $Node)
89
+ // is string | number | boolean
90
+ return new $Text(`${content}`);
77
91
  }
78
92
 
79
- export type $NodeContentTypes = $Node | string | number | boolean | $.SignalFunction<any>;
80
- export type $NodeContentHandler<T extends $Node> = ($node: T) => OrPromise<OrArray<$NodeContentTypes>>;
81
- export type $NodeContentResolver<T extends $Node> = $NodeContentHandler<T> | OrArray<OrPromise<$NodeContentTypes>>
93
+ export class $Text extends $Node {
94
+ signals = new Set<Signal<any>>();
95
+ constructor(textContent?: string) {
96
+ super(new Text(textContent));
97
+ }
98
+ }
99
+
100
+ export type $NodeContentHandler<T extends $Node> = ($node: T) => OrPromise<$NodeContentResolver<T>>;
101
+ export type $NodeContentTypes = $Node | string | number | boolean | $.SignalFunction<any> | null | undefined;
102
+ export type $NodeContentResolver<T extends $Node> = OrPromise<$NodeContentTypes | $NodeContentHandler<T> | $NodeContentResolver<T>[]>;
103
+
104
+ export interface $Node {
105
+ /** {@link Node.baseURI} */
106
+ readonly baseURI: string;
107
+ /** {@link Node.childNodes} */
108
+ readonly childNodes: NodeListOf<ChildNode>;
109
+ /** {@link Node.firstChild} */
110
+ readonly firstChild: ChildNode | null;
111
+ /** {@link Node.isConnected} */
112
+ readonly isConnected: boolean;
113
+ /** {@link Node.lastChild} */
114
+ readonly lastChild: ChildNode | null;
115
+ /** {@link Node.nextSibling} */
116
+ readonly nextSibling: ChildNode | null;
117
+ /** {@link Node.nodeName} */
118
+ readonly nodeName: string;
119
+ /** {@link Node.nodeType} */
120
+ readonly nodeType: number;
121
+ /** {@link Node.ownerDocument} */
122
+ readonly ownerDocument: Document | null;
123
+ /** {@link Node.parentElement} */
124
+ readonly parentElement?: HTMLElement | null;
125
+ /** {@link Node.parentNode} */
126
+ readonly parentNode?: ParentNode | null;
127
+ /** {@link Node.previousSibling} */
128
+ readonly previousSibling?: ChildNode | null;
129
+
130
+ /** {@link Node.appendChild} */
131
+ appendChild<T extends Node>(node: T): T;
132
+ /** {@link Node.cloneNode} */
133
+ cloneNode(subtree?: boolean): Node;
134
+ /** {@link Node.compareDocumentPosition} */
135
+ compareDocumentPosition(other: Node): number;
136
+ /** {@link Node.getRootNode} */
137
+ getRootNode(options?: GetRootNodeOptions): Node;
138
+ /** {@link Node.hasChildNodes} */
139
+ hasChildNodes(): boolean;
140
+ /** {@link Node.insertBefore} */
141
+ insertBefore<T extends Node>(node: T, child: Node | null): T;
142
+ /** {@link Node.isDefaultNamespace} */
143
+ isDefaultNamespace(namespace: string | null): boolean;
144
+ /** {@link Node.isEqualNode} */
145
+ isEqualNode(otherNode: Node | null): boolean;
146
+ /** {@link Node.isSameNode} */
147
+ isSameNode(otherNode: Node | null): boolean;
148
+ /** {@link Node.lookupNamespaceURI} */
149
+ lookupNamespaceURI(prefix: string | null): string | null;
150
+ /** {@link Node.lookupPrefix} */
151
+ lookupPrefix(namespace: string | null): string | null;
152
+ /** {@link Node.normalize} */
153
+ normalize(): this;
154
+ /** {@link Node.removeChild} */
155
+ removeChild<T extends Node>(child: T): T;
156
+ /** {@link Node.replaceChild} */
157
+ replaceChild<T extends Node>(node: Node, child: T): T;
158
+ /** {@link Node.replaceChild} */
159
+ after(...nodes: (Node | string)[]): this;
160
+ /** {@link Node.replaceChild} */
161
+ before(...nodes: (Node | string)[]): this;
162
+ /** {@link Node.replaceChild} */
163
+ remove(): this;
164
+ /** {@link Node.replaceChild} */
165
+ replaceWith(...nodes: (Node | string)[]): this;
166
+
167
+ /** {@link Node.nodeValue} */
168
+ nodeValue(nodeValue: $Parameter<string | null>): this;
169
+ nodeValue(): string | null;
170
+ /** {@link Node.textContent} */
171
+ textContent(textContent: $Parameter<string | null>): this;
172
+ textContent(): string | null;
173
+ }
package/src/node/node.ts CHANGED
@@ -1,11 +1,13 @@
1
+ import { $HTMLElement } from '#node/$HTMLElement';
1
2
  import { assignHelper } from '#lib/assignHelper';
2
3
  import { $Element } from '#node/$Element';
3
- import { $Node } from './$Node';
4
+ import { $Node, $Text } from './$Node';
4
5
 
5
- export * from './$Element';
6
6
  export * from './$Node';
7
+ export * from './$Element';
8
+ export * from './$HTMLElement';
7
9
 
8
- assignHelper([
9
- [Node, $Node],
10
- [Element, $Element],
11
- ])
10
+ assignHelper(Node, $Node);
11
+ assignHelper(Text, $Text);
12
+ assignHelper(Element, $Element);
13
+ assignHelper(HTMLElement, $HTMLElement);
@@ -1,4 +1,4 @@
1
- import { isUndefined } from "#lib/native";
1
+ import { _instanceof, forEach, isUndefined } from "#lib/native";
2
2
 
3
3
  export class Signal<T> {
4
4
  #value: T;
@@ -13,10 +13,10 @@ export class Signal<T> {
13
13
  value(callback: (oldValue: T) => T): this;
14
14
  value(resolver?: T | ((oldValue: T) => T)) {
15
15
  if (!arguments.length) {
16
- Signal.listeners.forEach(fn => fn(this));
16
+ forEach(Signal.listeners, fn => fn(this));
17
17
  return this.#value;
18
18
  }
19
- if (resolver instanceof Function) this.value(resolver(this.#value));
19
+ if (_instanceof(resolver, Function)) this.value(resolver(this.#value));
20
20
  else if (!isUndefined(resolver)) {
21
21
  this.#value = resolver;
22
22
  this.emit();
@@ -25,7 +25,7 @@ export class Signal<T> {
25
25
  }
26
26
 
27
27
  emit() {
28
- this.subscribers.forEach(subs => subs(this.#value))
28
+ forEach(this.subscribers, subs => subs(this.#value))
29
29
  return this;
30
30
  }
31
31
 
package/tsconfig.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  // Environment setup & latest features
4
- "lib": ["ESNext", "DOM"],
4
+ "lib": ["ESNext", "DOM", "DOM.Iterable"],
5
5
  "target": "ESNext",
6
6
  "module": "ESNext",
7
7
  "moduleDetection": "force",
@@ -1,13 +0,0 @@
1
- import { $CSSStyleRule } from "#structure/$CSSStyleRule";
2
-
3
- export class $CSSKeyframeRule extends $CSSStyleRule {
4
- keyframe: string
5
- constructor(keyframe: string) {
6
- super();
7
- this.keyframe = keyframe;
8
- }
9
-
10
- get css(): string {
11
- return `${this.keyframe} { ${Array.from(this.declarations).map(([_, dec]) => `${dec}`).join(' ')} }`
12
- }
13
- }
@@ -1,7 +0,0 @@
1
- import { $Element } from "#node/$Element";
2
-
3
- export class $HTMLElement<Ele extends HTMLElement = HTMLElement> extends $Element<Ele> {
4
- constructor(resolver: string | Ele) {
5
- super(resolver);
6
- }
7
- }