amateras 0.2.0 → 0.4.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 (78) hide show
  1. package/README.md +25 -7
  2. package/ext/css/README.md +19 -0
  3. package/ext/css/src/index.ts +395 -322
  4. package/ext/css/src/lib/colorAssign.ts +6 -0
  5. package/ext/css/src/lib/colors/amber.ts +25 -0
  6. package/ext/css/src/lib/colors/blackwhite.ts +13 -0
  7. package/ext/css/src/lib/colors/blue.ts +25 -0
  8. package/ext/css/src/lib/colors/cyan.ts +25 -0
  9. package/ext/css/src/lib/colors/emerald.ts +25 -0
  10. package/ext/css/src/lib/colors/fuchsia.ts +25 -0
  11. package/ext/css/src/lib/colors/gray.ts +25 -0
  12. package/ext/css/src/lib/colors/green.ts +25 -0
  13. package/ext/css/src/lib/colors/indigo.ts +25 -0
  14. package/ext/css/src/lib/colors/lime.ts +25 -0
  15. package/ext/css/src/lib/colors/neutral.ts +25 -0
  16. package/ext/css/src/lib/colors/orange.ts +25 -0
  17. package/ext/css/src/lib/colors/pink.ts +25 -0
  18. package/ext/css/src/lib/colors/purple.ts +25 -0
  19. package/ext/css/src/lib/colors/red.ts +25 -0
  20. package/ext/css/src/lib/colors/rose.ts +25 -0
  21. package/ext/css/src/lib/colors/sky.ts +25 -0
  22. package/ext/css/src/lib/colors/slate.ts +25 -0
  23. package/ext/css/src/lib/colors/stone.ts +25 -0
  24. package/ext/css/src/lib/colors/teal.ts +25 -0
  25. package/ext/css/src/lib/colors/violet.ts +25 -0
  26. package/ext/css/src/lib/colors/yellow.ts +25 -0
  27. package/ext/css/src/lib/colors/zinc.ts +25 -0
  28. package/ext/css/src/lib/colors.ts +23 -0
  29. package/ext/css/src/structure/$CSSContainerRule.ts +13 -0
  30. package/ext/css/src/structure/$CSSKeyframesRule.ts +1 -5
  31. package/ext/css/src/structure/$CSSMediaRule.ts +3 -23
  32. package/ext/css/src/structure/$CSSRule.ts +6 -18
  33. package/ext/css/src/structure/$CSSStyleRule.ts +5 -14
  34. package/ext/css/src/structure/$CSSVariable.ts +3 -3
  35. package/ext/html/html.ts +1 -13
  36. package/ext/html/node/$Anchor.ts +31 -1
  37. package/ext/html/node/$Image.ts +54 -1
  38. package/ext/html/node/$Input.ts +154 -1
  39. package/ext/html/node/$OptGroup.ts +8 -1
  40. package/ext/html/node/$Option.ts +25 -1
  41. package/ext/html/node/$Select.ts +61 -1
  42. package/ext/i18n/README.md +53 -0
  43. package/ext/i18n/package.json +10 -0
  44. package/ext/i18n/src/index.ts +54 -0
  45. package/ext/i18n/src/node/I18nText.ts +35 -0
  46. package/ext/i18n/src/structure/I18n.ts +40 -0
  47. package/ext/i18n/src/structure/I18nDictionary.ts +31 -0
  48. package/ext/markdown/index.ts +123 -0
  49. package/ext/router/index.ts +13 -4
  50. package/ext/router/node/Page.ts +1 -0
  51. package/ext/router/node/Route.ts +4 -3
  52. package/ext/router/node/Router.ts +62 -17
  53. package/ext/router/node/RouterAnchor.ts +1 -1
  54. package/ext/ssr/index.ts +7 -5
  55. package/ext/ui/lib/VirtualScroll.ts +24 -0
  56. package/ext/ui/node/Accordian.ts +97 -0
  57. package/ext/ui/node/Tabs.ts +114 -0
  58. package/ext/ui/node/Toast.ts +16 -0
  59. package/ext/ui/node/Waterfall.ts +73 -0
  60. package/ext/ui/package.json +11 -0
  61. package/package.json +6 -7
  62. package/src/core.ts +36 -19
  63. package/src/global.ts +4 -0
  64. package/src/lib/assign.ts +12 -12
  65. package/src/lib/assignHelper.ts +2 -2
  66. package/src/lib/chain.ts +3 -0
  67. package/src/lib/debounce.ts +7 -0
  68. package/src/lib/env.ts +2 -0
  69. package/src/lib/native.ts +22 -24
  70. package/src/lib/randomId.ts +1 -1
  71. package/src/lib/sleep.ts +1 -1
  72. package/src/node/$Element.ts +301 -35
  73. package/src/node/$HTMLElement.ts +94 -1
  74. package/src/node/$Node.ts +148 -54
  75. package/src/node/$Virtual.ts +58 -0
  76. package/src/{node/node.ts → node.ts} +2 -4
  77. package/src/structure/Signal.ts +3 -3
  78. package/ext/css/src/structure/$CSSKeyframeRule.ts +0 -14
package/src/node/$Node.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { _Array_from, _instanceof, isFunction, isNull, isObject, isUndefined } from "#lib/native";
1
+ import { _document } from "#lib/env";
2
+ import { _Array_from, _instanceof, _JSON_stringify, forEach, isFunction, isNull, isObject, isUndefined } from "#lib/native";
2
3
  import { Signal } from "#structure/Signal";
3
4
 
4
5
  export class $Node {
@@ -10,74 +11,100 @@ export class $Node {
10
11
  }
11
12
 
12
13
  content(children: $NodeContentResolver<this>) {
13
- _Array_from(this.node.childNodes).forEach(node => node.remove());
14
+ if (isUndefined(children)) return this;
15
+ forEach(_Array_from(this.childNodes), node => node.remove());
14
16
  return this.insert(children);
15
17
  }
16
18
 
17
19
  insert(resolver: $NodeContentResolver<this>, position = -1) {
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.node.childNodes).filter(node => node.nodeType !== node.TEXT_NODE).at(position);
22
- $.orArrayResolver(children).forEach(child => {
23
- if (!child) return;
24
- if (_instanceof(child, Array)) this.insert(child);
25
- else if (!positionChild) this.node.appendChild(child.node);
26
- else this.insertBefore(child.node, position < 0 ? positionChild.nextSibling : positionChild);
27
- })
28
- }
29
20
  // process nodes
30
- for (const child of $.orArrayResolver(resolver)) !isUndefined(child) && appendChild(processContent(this, child))
21
+ forEach($.toArray(resolver), resolve_child => forEach($Node.process(this, resolve_child), $node => $Node.append(this, $node, position)));
31
22
  return this;
32
23
  }
33
24
 
34
- await<T>(promise: Promise<T>, callback: ($node: this, result: T) => void): this {
35
- return promise.then(result => callback(this, result)), this;
36
- }
37
-
38
- remove() {
39
- return this.node.remove(), this
25
+ await<T>(promise: OrPromise<T>, callback: ($node: this, result: T) => void): this {
26
+ if (_instanceof(promise, Promise)) return promise.then(result => callback(this, result)), this;
27
+ else return callback(this, promise), this;
40
28
  }
41
29
 
42
30
  replace($node: $NodeContentResolver<$Node>) {
43
- if (!$node) return this.remove();
44
- const index = _Array_from(this.parentNode!.childNodes).indexOf(this.node) + 1;
45
- const parentNode = this.parentNode;
46
- this.remove();
47
- parentNode?.$.insert($node, index)
31
+ if (!$node) return this;
32
+ this.replaceWith(
33
+ ...$.toArray($Node.process(this, $node)).filter($node => $node).map($node => $node?.node) as Node[]
34
+ )
48
35
  return this;
49
36
  }
50
37
 
38
+ inDOM() {
39
+ return _document.contains(this.node);
40
+ }
41
+
51
42
  toString() {
52
- return this.node.textContent;
43
+ return this.textContent();
44
+ }
45
+
46
+ mounted($parent: $Node) {
47
+ return this;
48
+ }
49
+
50
+ use<F extends ($ele: this, ...args: any) => void>(callback: F, ...args: F extends ($ele: this, ...args: infer P) => void ? P : never) {
51
+ callback(this, ...args);
52
+ return this;
53
+ }
54
+
55
+ is<T extends (abstract new (...args: any[]) => $Node)>(instance: T): InstanceType<T> | null {
56
+ return _instanceof(this, instance) ? this : null;
53
57
  }
54
- }
55
58
 
56
- function processContent<T extends $Node>($node: T, content: OrPromise<$NodeContentTypes | $NodeContentHandler<T>>): OrArray<$Node | undefined | null> {
57
- if (isUndefined(content)) return;
58
- if (isNull(content)) return content;
59
- // is $Element
60
- if (_instanceof(content, $Node)) return content;
61
- // is Promise
62
- if (_instanceof(content, Promise)) return $('async').await(content, ($async, $child) => $async.replace($child as any));
63
- // is SignalFunction or ContentHandler
64
- if (isFunction(content)) {
65
- if (_instanceof((content as $.SignalFunction<any>).signal, Signal)) {
66
- const signalFn = content as $.SignalFunction<any>;
67
- const $text = document ? new $Text() : $('signal').attr({ type: typeof signalFn.signal.value() });
68
- const set = (value: any) => $text.textContent(isObject(value) ? JSON.stringify(value) : value);
69
- if (_instanceof($text, $Text)) $text.signals.add(signalFn.signal);
70
- signalFn.signal.subscribe(set);
71
- set(signalFn());
72
- return $text;
73
- } else {
74
- const _content = content($node) as $NodeContentResolver<$Node>;
75
- if (_instanceof(_content, Promise)) return processContent($node, _content as any);
76
- else return $.orArrayResolver(_content).map(content => processContent($node, content) as $Node);
59
+ static process<T extends $Node>($node: T, content: $NodeContentResolver<any>): Array<$Node | undefined | null> {
60
+ if (isUndefined(content) || isNull(content) || _instanceof(content, $Node)) return [content];
61
+ // is Promise
62
+ if (_instanceof(content, Promise)) return [$('async').await(content, ($async, $child) => $async.replace($child as any))];
63
+ // is SignalFunction or ContentHandler
64
+ if (isFunction(content)) {
65
+ const signal = (content as any).signal;
66
+ if (_instanceof(signal, Signal)) {
67
+ const resolver = (content as $.SignalFunction<any>)();
68
+ if (_instanceof(resolver, $Node)) {
69
+ // handler signal $Node result
70
+ let node = resolver;
71
+ const set = (value: any) => {
72
+ node.replace(value);
73
+ node = value;
74
+ }
75
+ signal.subscribe(set);
76
+ return [resolver];
77
+ } else {
78
+ // handler signal other type result
79
+ const $text = _document ? new $Text() : $('signal').attr({ type: typeof signal.value() });
80
+ const set = (value: any) => $text.textContent(isObject(value) ? _JSON_stringify(value) : value);
81
+ if (_instanceof($text, $Text)) $text.signals.add(signal);
82
+ signal.subscribe(set);
83
+ set(resolver);
84
+ return [$text];
85
+ }
86
+ } else {
87
+ const _content = content($node) as $NodeContentResolver<$Node>;
88
+ if (_instanceof(_content, Promise)) return this.process($node, _content as any);
89
+ else return $.toArray(_content).map(content => this.process($node, content)).flat();
90
+ }
77
91
  }
78
- }
79
- // is string | number | boolean
80
- return new $Text(`${content}`);
92
+ // is nested array
93
+ if (_instanceof(content, Array)) return content.map(c => this.process($node, c)).flat();
94
+ // is string | number | boolean
95
+ return [new $Text(`${content}`)];
96
+ }
97
+
98
+ /** */
99
+ static append($node: $Node, child: $Node | undefined | null, position: number) {
100
+ // insert each child, child may be an array
101
+ if (!child) return;
102
+ // get child node at position
103
+ let positionChild = _Array_from($node.childNodes).at(position);
104
+ if (!positionChild) $node.appendChild(child.node);
105
+ else $node.insertBefore(child.node, position < 0 ? positionChild.nextSibling : positionChild);
106
+ child.mounted($node);
107
+ }
81
108
  }
82
109
 
83
110
  export class $Text extends $Node {
@@ -89,14 +116,81 @@ export class $Text extends $Node {
89
116
 
90
117
  export type $NodeContentHandler<T extends $Node> = ($node: T) => OrPromise<$NodeContentResolver<T>>;
91
118
  export type $NodeContentTypes = $Node | string | number | boolean | $.SignalFunction<any> | null | undefined;
92
- export type $NodeContentResolver<T extends $Node> = OrArray<OrPromise<$NodeContentTypes | $NodeContentHandler<T>>>;
119
+ export type $NodeContentResolver<T extends $Node> = OrPromise<$NodeContentTypes | $NodeContentHandler<T> | $NodeContentResolver<T>[]>;
93
120
 
94
121
  export interface $Node {
95
- readonly parentNode?: Node;
122
+ /** {@link Node.baseURI} */
123
+ readonly baseURI: string;
124
+ /** {@link Node.childNodes} */
96
125
  readonly childNodes: NodeListOf<ChildNode>;
126
+ /** {@link Node.firstChild} */
127
+ readonly firstChild: ChildNode | null;
128
+ /** {@link Node.isConnected} */
129
+ readonly isConnected: boolean;
130
+ /** {@link Node.lastChild} */
131
+ readonly lastChild: ChildNode | null;
132
+ /** {@link Node.nextSibling} */
133
+ readonly nextSibling: ChildNode | null;
134
+ /** {@link Node.nodeName} */
135
+ readonly nodeName: string;
136
+ /** {@link Node.nodeType} */
137
+ readonly nodeType: number;
138
+ /** {@link Node.ownerDocument} */
139
+ readonly ownerDocument: Document | null;
140
+ /** {@link Node.parentElement} */
141
+ readonly parentElement?: HTMLElement | null;
142
+ /** {@link Node.parentNode} */
143
+ readonly parentNode?: ParentNode | null;
144
+ /** {@link Node.previousSibling} */
145
+ readonly previousSibling?: ChildNode | null;
146
+
147
+ /** {@link Node.appendChild} */
97
148
  appendChild<T extends Node>(node: T): T;
149
+ /** {@link Node.cloneNode} */
150
+ cloneNode(subtree?: boolean): Node;
151
+ /** {@link Node.compareDocumentPosition} */
152
+ compareDocumentPosition(other: Node): number;
153
+ /** {@link Node.getRootNode} */
154
+ getRootNode(options?: GetRootNodeOptions): Node;
155
+ /** {@link Node.hasChildNodes} */
156
+ hasChildNodes(): boolean;
157
+ /** {@link Node.insertBefore} */
98
158
  insertBefore<T extends Node>(node: T, child: Node | null): T;
159
+ /** {@link Node.isDefaultNamespace} */
160
+ isDefaultNamespace(namespace: string | null): boolean;
161
+ /** {@link Node.isEqualNode} */
162
+ isEqualNode(otherNode: Node | null): boolean;
163
+ /** {@link Node.isSameNode} */
164
+ isSameNode(otherNode: Node | null): boolean;
165
+ /** {@link Node.lookupNamespaceURI} */
166
+ lookupNamespaceURI(prefix: string | null): string | null;
167
+ /** {@link Node.lookupPrefix} */
168
+ lookupPrefix(namespace: string | null): string | null;
169
+ /** {@link Node.normalize} */
170
+ normalize(): this;
171
+ /** {@link Node.removeChild} */
172
+ removeChild<T extends Node>(child: T): T;
173
+ /** {@link Node.replaceChild} */
174
+ replaceChild<T extends Node>(node: Node, child: T): T;
175
+ /** {@link Node.replaceChild} */
176
+ after(...nodes: (Node | string)[]): this;
177
+ /** {@link Node.replaceChild} */
178
+ before(...nodes: (Node | string)[]): this;
179
+ /** {@link Node.replaceChild} */
180
+ remove(): this;
181
+ /** {@link Node.replaceChild} */
182
+ replaceWith(...nodes: (Node | string)[]): this;
183
+ /** {@link EventTarget.addEventListener} */
184
+ addEventListener(type: string, callback: EventListenerOrEventListenerObject | null, options?: AddEventListenerOptions | boolean): void;
185
+ /** {@link EventTarget.removeEventListener} */
186
+ removeEventListener(type: string, callback: EventListenerOrEventListenerObject | null, options?: EventListenerOptions | boolean): void;
187
+ /** {@link EventTarget.dispatchEvent} */
188
+ dispatchEvent(event: Event): boolean;
99
189
 
100
- textContent(content: string | null): this;
190
+ /** {@link Node.nodeValue} */
191
+ nodeValue(nodeValue: $Parameter<string | null>): this;
192
+ nodeValue(): string | null;
193
+ /** {@link Node.textContent} */
194
+ textContent(textContent: $Parameter<string | null>): this;
101
195
  textContent(): string | null;
102
196
  }
@@ -0,0 +1,58 @@
1
+ import { forEach, _Array_from, isUndefined, _instanceof } from "#lib/native";
2
+ import { $HTMLElement } from "#node/$HTMLElement";
3
+ import { $Node, type $NodeContentResolver } from "#node/$Node";
4
+
5
+ export class $Virtual<Ele extends HTMLElement = HTMLElement, EvMap = HTMLElementEventMap> extends $HTMLElement<Ele, EvMap> {
6
+ nodes = new Set<$Node>;
7
+ hiddenNodes = new Set<$Node>;
8
+ constructor(resolver: string | Ele) {
9
+ super(resolver);
10
+ }
11
+
12
+ content(children: $NodeContentResolver<this>) {
13
+ this.nodes.clear();
14
+ forEach(_Array_from(this.childNodes), node => node.remove());
15
+ return this.insert(children);
16
+ }
17
+
18
+ insert(resolver: $NodeContentResolver<this>, position = -1) {
19
+ // process nodes
20
+ forEach($.toArray(resolver), resolve_child => {
21
+ forEach($Node.process(this, resolve_child), $node => $Virtual.append(this, $node, position))
22
+ });
23
+ this.render();
24
+ return this;
25
+ }
26
+
27
+ hide($node?: $Node | null) {
28
+ if (!$node || !this.nodes.has($node)) return this;
29
+ this.hiddenNodes.add($node);
30
+ return this;
31
+ }
32
+
33
+ show($node?: $Node | null) {
34
+ if (!$node) return this;
35
+ this.hiddenNodes.delete($node);
36
+ return this;
37
+ }
38
+
39
+ render() {
40
+ // remove hidden node
41
+ forEach(_Array_from(this.childNodes), node => this.hiddenNodes.has($(node)) && node.remove());
42
+ // add visible node with position
43
+ forEach(_Array_from(this.nodes), ($node, i) => {
44
+ if (this.hiddenNodes.has($node)) return;
45
+ if (_Array_from(this.childNodes).at(i) !== $node.node) $Node.append(this, $node, i);
46
+ })
47
+ return this;
48
+ }
49
+
50
+ static append($node: $Virtual, child: $Node | undefined | null, position: number) {
51
+ if (!child) return;
52
+ const childList = _Array_from($node.nodes);
53
+ let $positionChild = childList.at(position);
54
+ if (!$positionChild) childList.push(child);
55
+ else childList.splice(position >= 0 ? position : childList.length + 1 + position, 0, child);
56
+ $node.nodes = new Set(childList);
57
+ }
58
+ }
@@ -1,11 +1,9 @@
1
1
  import { $HTMLElement } from '#node/$HTMLElement';
2
2
  import { assignHelper } from '#lib/assignHelper';
3
3
  import { $Element } from '#node/$Element';
4
- import { $Node, $Text } from './$Node';
5
-
6
- export * from './$Element';
7
- export * from './$Node';
4
+ import { $Node, $Text } from '#node/$Node';
8
5
 
6
+ assignHelper(EventTarget, $Node);
9
7
  assignHelper(Node, $Node);
10
8
  assignHelper(Text, $Text);
11
9
  assignHelper(Element, $Element);
@@ -1,4 +1,4 @@
1
- import { _instanceof, 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,7 +13,7 @@ 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
19
  if (_instanceof(resolver, Function)) this.value(resolver(this.#value));
@@ -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
 
@@ -1,14 +0,0 @@
1
- import { $CSSStyleRule } from "#structure/$CSSStyleRule";
2
- import { _Array_from } from "../../../../src/lib/native";
3
-
4
- export class $CSSKeyframeRule extends $CSSStyleRule {
5
- keyframe: string
6
- constructor(keyframe: string) {
7
- super();
8
- this.keyframe = keyframe;
9
- }
10
-
11
- get css(): string {
12
- return `${this.keyframe} { ${_Array_from(this.declarations).map(([_, dec]) => `${dec}`).join(' ')} }`
13
- }
14
- }