amateras 0.3.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.
- package/README.md +6 -4
- package/ext/css/README.md +19 -0
- package/ext/css/src/index.ts +347 -331
- package/ext/css/src/lib/colorAssign.ts +1 -1
- package/ext/css/src/structure/$CSSContainerRule.ts +13 -0
- package/ext/css/src/structure/$CSSRule.ts +1 -1
- package/ext/css/src/structure/$CSSStyleRule.ts +0 -7
- package/ext/css/src/structure/$CSSVariable.ts +3 -3
- package/ext/html/html.ts +1 -13
- package/ext/i18n/README.md +53 -0
- package/ext/i18n/package.json +10 -0
- package/ext/i18n/src/index.ts +54 -0
- package/ext/i18n/src/node/I18nText.ts +35 -0
- package/ext/i18n/src/structure/I18n.ts +40 -0
- package/ext/i18n/src/structure/I18nDictionary.ts +31 -0
- package/ext/markdown/index.ts +123 -0
- package/ext/router/index.ts +8 -1
- package/ext/router/node/Page.ts +1 -0
- package/ext/router/node/Route.ts +2 -1
- package/ext/router/node/Router.ts +33 -22
- package/ext/ssr/index.ts +4 -2
- package/ext/ui/lib/VirtualScroll.ts +24 -0
- package/ext/ui/node/Accordian.ts +97 -0
- package/ext/ui/node/Tabs.ts +114 -0
- package/ext/ui/node/Toast.ts +16 -0
- package/ext/ui/node/Waterfall.ts +73 -0
- package/ext/ui/package.json +11 -0
- package/package.json +4 -7
- package/src/core.ts +21 -8
- package/src/lib/assign.ts +8 -9
- package/src/lib/assignHelper.ts +1 -1
- package/src/lib/chain.ts +3 -0
- package/src/lib/debounce.ts +7 -0
- package/src/lib/env.ts +2 -0
- package/src/lib/native.ts +22 -35
- package/src/lib/randomId.ts +1 -1
- package/src/lib/sleep.ts +1 -1
- package/src/node/$Element.ts +182 -20
- package/src/node/$HTMLElement.ts +24 -0
- package/src/node/$Node.ts +75 -52
- package/src/node/$Virtual.ts +58 -0
- package/src/{node/node.ts → node.ts} +2 -5
package/src/node/$Element.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Signal } from "#structure/Signal";
|
|
2
2
|
import { $Node } from "#node/$Node";
|
|
3
|
-
import { _Array_from,
|
|
3
|
+
import { _Array_from, _instanceof, _Object_assign, _Object_entries, _Object_fromEntries, isNull, isString, isUndefined } from "#lib/native";
|
|
4
|
+
import { _document } from "#lib/env";
|
|
4
5
|
|
|
5
6
|
export class $Element<Ele extends Element = Element, EvMap = ElementEventMap> extends $Node {
|
|
6
7
|
declare node: Ele
|
|
@@ -12,12 +13,12 @@ export class $Element<Ele extends Element = Element, EvMap = ElementEventMap> ex
|
|
|
12
13
|
|
|
13
14
|
attr(): {[key: string]: string};
|
|
14
15
|
attr(key: string): string | null;
|
|
15
|
-
attr(obj: {[key: string]: string | number | boolean | Signal<any>}): this;
|
|
16
|
-
attr(resolver?: {[key: string]: string | number | boolean | Signal<any>} | string) {
|
|
16
|
+
attr(obj: {[key: string]: string | number | boolean | Signal<any> | null}): this;
|
|
17
|
+
attr(resolver?: {[key: string]: string | number | boolean | Signal<any> | null} | string) {
|
|
17
18
|
if (!arguments.length) return _Object_fromEntries(_Array_from(this.attributes).map(attr => [attr.name, attr.value]));
|
|
18
19
|
if (isString(resolver)) return this.getAttribute(resolver);
|
|
19
20
|
if (resolver) for (let [key, value] of _Object_entries(resolver)) {
|
|
20
|
-
const set = (value: any) => !isUndefined(value) && this.setAttribute(key, `${value}`)
|
|
21
|
+
const set = (value: any) => !isUndefined(value) && isNull(value) ? this.removeAttribute(key) : this.setAttribute(key, `${value}`)
|
|
21
22
|
if (_instanceof(value, Signal)) value = value.subscribe(set).value();
|
|
22
23
|
set(value);
|
|
23
24
|
}
|
|
@@ -39,28 +40,18 @@ export class $Element<Ele extends Element = Element, EvMap = ElementEventMap> ex
|
|
|
39
40
|
return this;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
use(callback: ($ele: this) => void) {
|
|
43
|
-
callback(this);
|
|
44
|
-
return this;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
43
|
on<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | AddEventListenerOptions) {
|
|
48
|
-
this.
|
|
44
|
+
this.addEventListener(type as string, listener as any, options);
|
|
49
45
|
return this;
|
|
50
46
|
}
|
|
51
47
|
|
|
52
48
|
off<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | EventListenerOptions) {
|
|
53
|
-
this.
|
|
49
|
+
this.removeEventListener(type as string, listener as any, options);
|
|
54
50
|
return this;
|
|
55
51
|
}
|
|
56
52
|
|
|
57
53
|
once<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | AddEventListenerOptions) {
|
|
58
|
-
|
|
59
|
-
this.off(type, handler, options);
|
|
60
|
-
isFunction(listener) ? listener(event) : listener.handleEvent(event);
|
|
61
|
-
}
|
|
62
|
-
this.on(type, handler, options);
|
|
63
|
-
return this;
|
|
54
|
+
return this.on(type, listener, {once: true})
|
|
64
55
|
}
|
|
65
56
|
|
|
66
57
|
toString() {
|
|
@@ -68,14 +59,15 @@ export class $Element<Ele extends Element = Element, EvMap = ElementEventMap> ex
|
|
|
68
59
|
}
|
|
69
60
|
}
|
|
70
61
|
|
|
71
|
-
export type
|
|
72
|
-
export type $Event<E extends $Element, Ev = any> = Ev & {target: {$: E}};
|
|
62
|
+
export type $Event<E extends $Element, Ev = any> = Ev & {currentTarget: {$: E}};
|
|
73
63
|
export type $EventListener<E extends $Element, Ev> = (event: $Event<E, Ev>) => void;
|
|
74
64
|
export type $EventListenerObject<E extends $Element, Ev> = { handleEvent(object: $Event<E, Ev>): void; }
|
|
75
65
|
|
|
76
66
|
function createNode(nodeName: string) {
|
|
67
|
+
return !_document
|
|
77
68
|
//@ts-expect-error
|
|
78
|
-
|
|
69
|
+
? new Node(nodeName) as unknown as Node & ChildNode
|
|
70
|
+
: _document.createElement(nodeName);
|
|
79
71
|
}
|
|
80
72
|
|
|
81
73
|
export interface $Element<Ele extends Element, EvMap> {
|
|
@@ -107,6 +99,20 @@ export interface $Element<Ele extends Element, EvMap> {
|
|
|
107
99
|
readonly shadowRoot: ShadowRoot | null;
|
|
108
100
|
/** {@link Element.tagName} */
|
|
109
101
|
readonly tagName: string;
|
|
102
|
+
/** {@link Element.nextElementSibling} */
|
|
103
|
+
readonly nextElementSibling: Element | null;
|
|
104
|
+
/** {@link Element.previousElementSibling} */
|
|
105
|
+
readonly previousElementSibling: Element | null;
|
|
106
|
+
/** {@link Element.childElementCount} */
|
|
107
|
+
readonly childElementCount: number;
|
|
108
|
+
/** {@link Element.children} */
|
|
109
|
+
readonly children: HTMLCollection;
|
|
110
|
+
/** {@link Element.firstElementChild} */
|
|
111
|
+
readonly firstElementChild: Element | null;
|
|
112
|
+
/** {@link Element.lastElementChild} */
|
|
113
|
+
readonly lastElementChild: Element | null;
|
|
114
|
+
/** {@link Element.assignedSlot} */
|
|
115
|
+
readonly assignedSlot: HTMLSlotElement | null;
|
|
110
116
|
|
|
111
117
|
/** {@link Element.attachShadow} */
|
|
112
118
|
attachShadow(init: ShadowRootInit): ShadowRoot;
|
|
@@ -200,6 +206,24 @@ export interface $Element<Ele extends Element, EvMap> {
|
|
|
200
206
|
setPointerCapture(pointerId: number): this;
|
|
201
207
|
/** {@link Element.toggleAttribute} */
|
|
202
208
|
toggleAttribute(qualifiedName: string, force?: boolean): boolean;
|
|
209
|
+
/** {@link Element.animate} */
|
|
210
|
+
animate(keyframes: Keyframe[] | PropertyIndexedKeyframes | null, options?: number | KeyframeAnimationOptions): Animation;
|
|
211
|
+
/** {@link Element.getAnimations} */
|
|
212
|
+
getAnimations(options?: GetAnimationsOptions): Animation[];
|
|
213
|
+
/** {@link Element.append} */
|
|
214
|
+
append(...nodes: (Node | string)[]): this;
|
|
215
|
+
/** {@link Element.prepend} */
|
|
216
|
+
prepend(...nodes: (Node | string)[]): this;
|
|
217
|
+
/** {@link Element.querySelector} */
|
|
218
|
+
querySelector<K extends keyof HTMLElementTagNameMap>(selectors: K): HTMLElementTagNameMap[K] | null;
|
|
219
|
+
querySelector<K extends keyof SVGElementTagNameMap>(selectors: K): SVGElementTagNameMap[K] | null;
|
|
220
|
+
querySelector<K extends keyof MathMLElementTagNameMap>(selectors: K): MathMLElementTagNameMap[K] | null;
|
|
221
|
+
/** {@link Element.querySelectorAll} */
|
|
222
|
+
querySelectorAll<K extends keyof HTMLElementTagNameMap>(selectors: K): NodeListOf<HTMLElementTagNameMap[K]>;
|
|
223
|
+
querySelectorAll<K extends keyof SVGElementTagNameMap>(selectors: K): NodeListOf<SVGElementTagNameMap[K]>;
|
|
224
|
+
querySelectorAll<K extends keyof MathMLElementTagNameMap>(selectors: K): NodeListOf<MathMLElementTagNameMap[K]>;
|
|
225
|
+
/** {@link Element.replaceChildren} */
|
|
226
|
+
replaceChildren(...nodes: (Node | string)[]): this;
|
|
203
227
|
|
|
204
228
|
/** {@link Element.classList} */
|
|
205
229
|
classList(): DOMTokenList;
|
|
@@ -228,6 +252,144 @@ export interface $Element<Ele extends Element, EvMap> {
|
|
|
228
252
|
/** {@link Element.slot} */
|
|
229
253
|
slot(): string;
|
|
230
254
|
slot(slot: $Parameter<string>): this;
|
|
255
|
+
|
|
256
|
+
// ARIAMixin
|
|
257
|
+
/** {@link ARIAMixin.ariaAtomic} */
|
|
258
|
+
ariaAtomic(): string | null;
|
|
259
|
+
ariaAtomic(ariaAtomic: $Parameter<string | null>): this;
|
|
260
|
+
/** {@link ARIAMixin.ariaAutoComplete} */
|
|
261
|
+
ariaAutoComplete(): string | null;
|
|
262
|
+
ariaAutoComplete(ariaAutoComplete: $Parameter<string | null>): this;
|
|
263
|
+
/** {@link ARIAMixin.ariaBrailleLabel} */
|
|
264
|
+
ariaBrailleLabel(): string | null;
|
|
265
|
+
ariaBrailleLabel(ariaBrailleLabel: $Parameter<string | null>): this;
|
|
266
|
+
/** {@link ARIAMixin.ariaBrailleRoleDescription} */
|
|
267
|
+
ariaBrailleRoleDescription(): string | null;
|
|
268
|
+
ariaBrailleRoleDescription(ariaBrailleRoleDescription: $Parameter<string | null>): this;
|
|
269
|
+
/** {@link ARIAMixin.ariaBusy} */
|
|
270
|
+
ariaBusy(): string | null;
|
|
271
|
+
ariaBusy(ariaBusy: $Parameter<string | null>): this;
|
|
272
|
+
/** {@link ARIAMixin.ariaChecked} */
|
|
273
|
+
ariaChecked(): string | null;
|
|
274
|
+
ariaChecked(ariaChecked: $Parameter<string | null>): this;
|
|
275
|
+
/** {@link ARIAMixin.ariaColCount} */
|
|
276
|
+
ariaColCount(): string | null;
|
|
277
|
+
ariaColCount(ariaColCount: $Parameter<string | null>): this;
|
|
278
|
+
/** {@link ARIAMixin.ariaColIndex} */
|
|
279
|
+
ariaColIndex(): string | null;
|
|
280
|
+
ariaColIndex(ariaColIndex: $Parameter<string | null>): this;
|
|
281
|
+
/** {@link ARIAMixin.ariaColIndexText} */
|
|
282
|
+
ariaColIndexText(): string | null;
|
|
283
|
+
ariaColIndexText(ariaColIndexText: $Parameter<string | null>): this;
|
|
284
|
+
/** {@link ARIAMixin.ariaColSpan} */
|
|
285
|
+
ariaColSpan(): string | null;
|
|
286
|
+
ariaColSpan(ariaColSpan: $Parameter<string | null>): this;
|
|
287
|
+
/** {@link ARIAMixin.ariaCurrent} */
|
|
288
|
+
ariaCurrent(): string | null;
|
|
289
|
+
ariaCurrent(ariaCurrent: $Parameter<string | null>): this;
|
|
290
|
+
/** {@link ARIAMixin.ariaDescription} */
|
|
291
|
+
ariaDescription(): string | null;
|
|
292
|
+
ariaDescription(ariaDescription: $Parameter<string | null>): this;
|
|
293
|
+
/** {@link ARIAMixin.ariaDisabled} */
|
|
294
|
+
ariaDisabled(): string | null;
|
|
295
|
+
ariaDisabled(ariaDisabled: $Parameter<string | null>): this;
|
|
296
|
+
/** {@link ARIAMixin.ariaExpanded} */
|
|
297
|
+
ariaExpanded(): string | null;
|
|
298
|
+
ariaExpanded(ariaExpanded: $Parameter<string | null>): this;
|
|
299
|
+
/** {@link ARIAMixin.ariaHasPopup} */
|
|
300
|
+
ariaHasPopup(): string | null;
|
|
301
|
+
ariaHasPopup(ariaHasPopup: $Parameter<string | null>): this;
|
|
302
|
+
/** {@link ARIAMixin.ariaHidden} */
|
|
303
|
+
ariaHidden(): string | null;
|
|
304
|
+
ariaHidden(ariaHidden: $Parameter<string | null>): this;
|
|
305
|
+
/** {@link ARIAMixin.ariaInvalid} */
|
|
306
|
+
ariaInvalid(): string | null;
|
|
307
|
+
ariaInvalid(ariaInvalid: $Parameter<string | null>): this;
|
|
308
|
+
/** {@link ARIAMixin.ariaKeyShortcuts} */
|
|
309
|
+
ariaKeyShortcuts(): string | null;
|
|
310
|
+
ariaKeyShortcuts(ariaKeyShortcuts: $Parameter<string | null>): this;
|
|
311
|
+
/** {@link ARIAMixin.ariaLabel} */
|
|
312
|
+
ariaLabel(): string | null;
|
|
313
|
+
ariaLabel(ariaLabel: $Parameter<string | null>): this;
|
|
314
|
+
/** {@link ARIAMixin.ariaLevel} */
|
|
315
|
+
ariaLevel(): string | null;
|
|
316
|
+
ariaLevel(ariaLevel: $Parameter<string | null>): this;
|
|
317
|
+
/** {@link ARIAMixin.ariaLive} */
|
|
318
|
+
ariaLive(): string | null;
|
|
319
|
+
ariaLive(ariaLive: $Parameter<string | null>): this;
|
|
320
|
+
/** {@link ARIAMixin.ariaModal} */
|
|
321
|
+
ariaModal(): string | null;
|
|
322
|
+
ariaModal(ariaModal: $Parameter<string | null>): this;
|
|
323
|
+
/** {@link ARIAMixin.ariaMultiLine} */
|
|
324
|
+
ariaMultiLine(): string | null;
|
|
325
|
+
ariaMultiLine(ariaMultiLine: $Parameter<string | null>): this;
|
|
326
|
+
/** {@link ARIAMixin.ariaMultiSelectable} */
|
|
327
|
+
ariaMultiSelectable(): string | null;
|
|
328
|
+
ariaMultiSelectable(ariaMultiSelectable: $Parameter<string | null>): this;
|
|
329
|
+
/** {@link ARIAMixin.ariaOrientation} */
|
|
330
|
+
ariaOrientation(): string | null;
|
|
331
|
+
ariaOrientation(ariaOrientation: $Parameter<string | null>): this;
|
|
332
|
+
/** {@link ARIAMixin.ariaPlaceholder} */
|
|
333
|
+
ariaPlaceholder(): string | null;
|
|
334
|
+
ariaPlaceholder(ariaPlaceholder: $Parameter<string | null>): this;
|
|
335
|
+
/** {@link ARIAMixin.ariaPosInSet} */
|
|
336
|
+
ariaPosInSet(): string | null;
|
|
337
|
+
ariaPosInSet(ariaPosInSet: $Parameter<string | null>): this;
|
|
338
|
+
/** {@link ARIAMixin.ariaPressed} */
|
|
339
|
+
ariaPressed(): string | null;
|
|
340
|
+
ariaPressed(ariaPressed: $Parameter<string | null>): this;
|
|
341
|
+
/** {@link ARIAMixin.ariaReadOnly} */
|
|
342
|
+
ariaReadOnly(): string | null;
|
|
343
|
+
ariaReadOnly(ariaReadOnly: $Parameter<string | null>): this;
|
|
344
|
+
/** {@link ARIAMixin.ariaRelevant} */
|
|
345
|
+
ariaRelevant(): string | null;
|
|
346
|
+
ariaRelevant(ariaRelevant: $Parameter<string | null>): this;
|
|
347
|
+
/** {@link ARIAMixin.ariaRequired} */
|
|
348
|
+
ariaRequired(): string | null;
|
|
349
|
+
ariaRequired(ariaRequired: $Parameter<string | null>): this;
|
|
350
|
+
/** {@link ARIAMixin.ariaRoleDescription} */
|
|
351
|
+
ariaRoleDescription(): string | null;
|
|
352
|
+
ariaRoleDescription(ariaRoleDescription: $Parameter<string | null>): this;
|
|
353
|
+
/** {@link ARIAMixin.ariaRowCount} */
|
|
354
|
+
ariaRowCount(): string | null;
|
|
355
|
+
ariaRowCount(ariaRowCount: $Parameter<string | null>): this;
|
|
356
|
+
/** {@link ARIAMixin.ariaRowIndex} */
|
|
357
|
+
ariaRowIndex(): string | null;
|
|
358
|
+
ariaRowIndex(ariaRowIndex: $Parameter<string | null>): this;
|
|
359
|
+
/** {@link ARIAMixin.ariaRowIndexText} */
|
|
360
|
+
ariaRowIndexText(): string | null;
|
|
361
|
+
ariaRowIndexText(ariaRowIndexText: $Parameter<string | null>): this;
|
|
362
|
+
/** {@link ARIAMixin.ariaRowSpan} */
|
|
363
|
+
ariaRowSpan(): string | null;
|
|
364
|
+
ariaRowSpan(ariaRowSpan: $Parameter<string | null>): this;
|
|
365
|
+
/** {@link ARIAMixin.ariaSelected} */
|
|
366
|
+
ariaSelected(): string | null;
|
|
367
|
+
ariaSelected(ariaSelected: $Parameter<string | null>): this;
|
|
368
|
+
/** {@link ARIAMixin.ariaSetSize} */
|
|
369
|
+
ariaSetSize(): string | null;
|
|
370
|
+
ariaSetSize(ariaSetSize: $Parameter<string | null>): this;
|
|
371
|
+
/** {@link ARIAMixin.ariaSort} */
|
|
372
|
+
ariaSort(): string | null;
|
|
373
|
+
ariaSort(ariaSort: $Parameter<string | null>): this;
|
|
374
|
+
/** {@link ARIAMixin.ariaValueMax} */
|
|
375
|
+
ariaValueMax(): string | null;
|
|
376
|
+
ariaValueMax(ariaValueMax: $Parameter<string | null>): this;
|
|
377
|
+
/** {@link ARIAMixin.ariaValueMin} */
|
|
378
|
+
ariaValueMin(): string | null;
|
|
379
|
+
ariaValueMin(ariaValueMin: $Parameter<string | null>): this;
|
|
380
|
+
/** {@link ARIAMixin.ariaValueNow} */
|
|
381
|
+
ariaValueNow(): string | null;
|
|
382
|
+
ariaValueNow(ariaValueNow: $Parameter<string | null>): this;
|
|
383
|
+
/** {@link ARIAMixin.ariaValueText} */
|
|
384
|
+
ariaValueText(): string | null;
|
|
385
|
+
ariaValueText(ariaValueText: $Parameter<string | null>): this;
|
|
386
|
+
/** {@link ARIAMixin.role} */
|
|
387
|
+
role(): string | null;
|
|
388
|
+
role(role: $Parameter<string | null>): this;
|
|
389
|
+
addEventListener<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | AddEventListenerOptions): void;
|
|
390
|
+
addEventListener(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | AddEventListenerOptions): void;
|
|
391
|
+
removeEventListener<K extends keyof EvMap, Ev extends EvMap[K]>(type: K, listener: $EventListener<this, Ev> | $EventListenerObject<this, Ev>, options?: boolean | EventListenerOptions): void;
|
|
392
|
+
removeEventListener(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | EventListenerOptions): void;
|
|
231
393
|
|
|
232
394
|
|
|
233
395
|
on(type: string, listener: $EventListener<this, Event> | $EventListenerObject<this, Event>, options?: boolean | AddEventListenerOptions): this;
|
package/src/node/$HTMLElement.ts
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
|
+
import { _Object_entries, forEach } from "#lib/native";
|
|
1
2
|
import { $Element } from "#node/$Element";
|
|
2
3
|
|
|
3
4
|
export class $HTMLElement<Ele extends HTMLElement = HTMLElement, EvMap = HTMLElementEventMap> extends $Element<Ele, EvMap> {
|
|
4
5
|
constructor(resolver: string | Ele) {
|
|
5
6
|
super(resolver);
|
|
6
7
|
}
|
|
8
|
+
|
|
9
|
+
style(): CSSStyleDeclaration;
|
|
10
|
+
style(style: Partial<CSSStyleDeclarationOptions> | undefined): this
|
|
11
|
+
style(style?: Partial<CSSStyleDeclarationOptions> | undefined) {
|
|
12
|
+
let _style = this.node.style
|
|
13
|
+
if (!arguments.length) return _style
|
|
14
|
+
if (!style) return this;
|
|
15
|
+
forEach(_Object_entries(style), ([key, value]) => _style[key as any] = value ?? '')
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
7
18
|
}
|
|
8
19
|
|
|
20
|
+
type CSSStyleDeclarationOptions = Omit<CSSStyleDeclaration, 'parentRule' | 'length' | 'getPropertyPriority' | 'getPropertyValue' | 'item' | 'removeProperty' | 'setProperty'>;
|
|
21
|
+
|
|
9
22
|
export interface $HTMLElement<Ele extends HTMLElement = HTMLElement, EvMap = HTMLElementEventMap> extends $Element<Ele, EvMap> {
|
|
10
23
|
/** {@link HTMLElement.accessKeyLabel} */
|
|
11
24
|
readonly accessKeyLabel: string;
|
|
@@ -19,6 +32,8 @@ export interface $HTMLElement<Ele extends HTMLElement = HTMLElement, EvMap = HTM
|
|
|
19
32
|
readonly offsetTop: number;
|
|
20
33
|
/** {@link HTMLElement.offsetWidth} */
|
|
21
34
|
readonly offsetWidth: number;
|
|
35
|
+
/** {@link HTMLElement.isContentEditable} */
|
|
36
|
+
readonly isContentEditable: boolean;
|
|
22
37
|
|
|
23
38
|
/** {@link HTMLElement.attachInternals} */
|
|
24
39
|
attachInternals(): ElementInternals;
|
|
@@ -73,4 +88,13 @@ export interface $HTMLElement<Ele extends HTMLElement = HTMLElement, EvMap = HTM
|
|
|
73
88
|
/** {@link HTMLElement.writingSuggestions} */
|
|
74
89
|
writingSuggestions(): string;
|
|
75
90
|
writingSuggestions(writingSuggestions: $Parameter<string>): this;
|
|
91
|
+
/** {@link HTMLElement.contentEditable} */
|
|
92
|
+
contentEditable(): string;
|
|
93
|
+
contentEditable(contentEditable: $Parameter<string>): this;
|
|
94
|
+
/** {@link HTMLElement.enterKeyHint} */
|
|
95
|
+
enterKeyHint(): string;
|
|
96
|
+
enterKeyHint(enterKeyHint: $Parameter<string>): this;
|
|
97
|
+
/** {@link HTMLElement.inputMode} */
|
|
98
|
+
inputMode(): string;
|
|
99
|
+
inputMode(inputMode: $Parameter<string>): this;
|
|
76
100
|
}
|
package/src/node/$Node.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
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,84 +11,100 @@ export class $Node {
|
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
content(children: $NodeContentResolver<this>) {
|
|
14
|
+
if (isUndefined(children)) return this;
|
|
13
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.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
20
|
// process nodes
|
|
30
|
-
|
|
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:
|
|
35
|
-
return promise.then(result => callback(this, result)), 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;
|
|
36
28
|
}
|
|
37
29
|
|
|
38
30
|
replace($node: $NodeContentResolver<$Node>) {
|
|
39
31
|
if (!$node) return this;
|
|
40
32
|
this.replaceWith(
|
|
41
|
-
...$.toArray(
|
|
33
|
+
...$.toArray($Node.process(this, $node)).filter($node => $node).map($node => $node?.node) as Node[]
|
|
42
34
|
)
|
|
43
35
|
return this;
|
|
44
36
|
}
|
|
45
37
|
|
|
38
|
+
inDOM() {
|
|
39
|
+
return _document.contains(this.node);
|
|
40
|
+
}
|
|
41
|
+
|
|
46
42
|
toString() {
|
|
47
43
|
return this.textContent();
|
|
48
44
|
}
|
|
49
|
-
}
|
|
50
45
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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;
|
|
57
|
+
}
|
|
58
|
+
|
|
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];
|
|
69
85
|
}
|
|
70
|
-
signal.subscribe(set);
|
|
71
|
-
return resolver;
|
|
72
86
|
} else {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (_instanceof($text, $Text)) $text.signals.add(signal);
|
|
77
|
-
signal.subscribe(set);
|
|
78
|
-
set(resolver);
|
|
79
|
-
return $text;
|
|
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();
|
|
80
90
|
}
|
|
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);
|
|
85
91
|
}
|
|
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);
|
|
86
107
|
}
|
|
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}`);
|
|
91
108
|
}
|
|
92
109
|
|
|
93
110
|
export class $Text extends $Node {
|
|
@@ -163,6 +180,12 @@ export interface $Node {
|
|
|
163
180
|
remove(): this;
|
|
164
181
|
/** {@link Node.replaceChild} */
|
|
165
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;
|
|
166
189
|
|
|
167
190
|
/** {@link Node.nodeValue} */
|
|
168
191
|
nodeValue(nodeValue: $Parameter<string | null>): this;
|
|
@@ -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,12 +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 '
|
|
5
|
-
|
|
6
|
-
export * from './$Node';
|
|
7
|
-
export * from './$Element';
|
|
8
|
-
export * from './$HTMLElement';
|
|
4
|
+
import { $Node, $Text } from '#node/$Node';
|
|
9
5
|
|
|
6
|
+
assignHelper(EventTarget, $Node);
|
|
10
7
|
assignHelper(Node, $Node);
|
|
11
8
|
assignHelper(Text, $Text);
|
|
12
9
|
assignHelper(Element, $Element);
|