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.
- package/README.md +25 -7
- package/ext/css/README.md +19 -0
- package/ext/css/src/index.ts +395 -322
- package/ext/css/src/lib/colorAssign.ts +6 -0
- package/ext/css/src/lib/colors/amber.ts +25 -0
- package/ext/css/src/lib/colors/blackwhite.ts +13 -0
- package/ext/css/src/lib/colors/blue.ts +25 -0
- package/ext/css/src/lib/colors/cyan.ts +25 -0
- package/ext/css/src/lib/colors/emerald.ts +25 -0
- package/ext/css/src/lib/colors/fuchsia.ts +25 -0
- package/ext/css/src/lib/colors/gray.ts +25 -0
- package/ext/css/src/lib/colors/green.ts +25 -0
- package/ext/css/src/lib/colors/indigo.ts +25 -0
- package/ext/css/src/lib/colors/lime.ts +25 -0
- package/ext/css/src/lib/colors/neutral.ts +25 -0
- package/ext/css/src/lib/colors/orange.ts +25 -0
- package/ext/css/src/lib/colors/pink.ts +25 -0
- package/ext/css/src/lib/colors/purple.ts +25 -0
- package/ext/css/src/lib/colors/red.ts +25 -0
- package/ext/css/src/lib/colors/rose.ts +25 -0
- package/ext/css/src/lib/colors/sky.ts +25 -0
- package/ext/css/src/lib/colors/slate.ts +25 -0
- package/ext/css/src/lib/colors/stone.ts +25 -0
- package/ext/css/src/lib/colors/teal.ts +25 -0
- package/ext/css/src/lib/colors/violet.ts +25 -0
- package/ext/css/src/lib/colors/yellow.ts +25 -0
- package/ext/css/src/lib/colors/zinc.ts +25 -0
- package/ext/css/src/lib/colors.ts +23 -0
- package/ext/css/src/structure/$CSSContainerRule.ts +13 -0
- package/ext/css/src/structure/$CSSKeyframesRule.ts +1 -5
- package/ext/css/src/structure/$CSSMediaRule.ts +3 -23
- package/ext/css/src/structure/$CSSRule.ts +6 -18
- package/ext/css/src/structure/$CSSStyleRule.ts +5 -14
- package/ext/css/src/structure/$CSSVariable.ts +3 -3
- package/ext/html/html.ts +1 -13
- package/ext/html/node/$Anchor.ts +31 -1
- package/ext/html/node/$Image.ts +54 -1
- package/ext/html/node/$Input.ts +154 -1
- package/ext/html/node/$OptGroup.ts +8 -1
- package/ext/html/node/$Option.ts +25 -1
- package/ext/html/node/$Select.ts +61 -1
- 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 +13 -4
- package/ext/router/node/Page.ts +1 -0
- package/ext/router/node/Route.ts +4 -3
- package/ext/router/node/Router.ts +62 -17
- package/ext/router/node/RouterAnchor.ts +1 -1
- package/ext/ssr/index.ts +7 -5
- 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 +6 -7
- package/src/core.ts +36 -19
- package/src/global.ts +4 -0
- package/src/lib/assign.ts +12 -12
- package/src/lib/assignHelper.ts +2 -2
- 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 -24
- package/src/lib/randomId.ts +1 -1
- package/src/lib/sleep.ts +1 -1
- package/src/node/$Element.ts +301 -35
- package/src/node/$HTMLElement.ts +94 -1
- package/src/node/$Node.ts +148 -54
- package/src/node/$Virtual.ts +58 -0
- package/src/{node/node.ts → node.ts} +2 -4
- package/src/structure/Signal.ts +3 -3
- package/ext/css/src/structure/$CSSKeyframeRule.ts +0 -14
|
@@ -1,30 +1,10 @@
|
|
|
1
1
|
import { _Array_from, _instanceof } from "amateras/lib/native";
|
|
2
2
|
import { $CSSRule } from "#structure/$CSSRule";
|
|
3
|
-
import { $CSSStyleRule } from "./$CSSStyleRule";
|
|
4
3
|
|
|
5
4
|
export class $CSSMediaRule extends $CSSRule {
|
|
6
5
|
condition: string;
|
|
7
|
-
constructor(
|
|
8
|
-
super();
|
|
9
|
-
this.condition =
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
get css(): string {
|
|
13
|
-
function findOwnerMediaRule(rule: $CSSRule, contextRules: $CSSMediaRule[]) {
|
|
14
|
-
const ownerRule = rule.ownerRule;
|
|
15
|
-
if (!ownerRule) return contextRules;
|
|
16
|
-
if (_instanceof(ownerRule, $CSSMediaRule)) return findOwnerMediaRule(ownerRule, [ownerRule, ...contextRules]);
|
|
17
|
-
else return findOwnerMediaRule(ownerRule, contextRules);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function findChildRules(rule: $CSSRule, rules: $CSSStyleRule[] = []) {
|
|
21
|
-
_Array_from(rule.rules).forEach((_rule => {
|
|
22
|
-
if (!_instanceof(_rule, $CSSStyleRule)) return;
|
|
23
|
-
rules.push(_rule);
|
|
24
|
-
return findChildRules(_rule, rules);
|
|
25
|
-
}))
|
|
26
|
-
return rules
|
|
27
|
-
}
|
|
28
|
-
return `@media ${findOwnerMediaRule(this, [this]).map(rule => rule.condition).join(' and ')} { ${findChildRules(this).map(rule => rule.css).join(' ')} }`
|
|
6
|
+
constructor(selector: string) {
|
|
7
|
+
super(selector);
|
|
8
|
+
this.condition = selector.replace('@media ', '');
|
|
29
9
|
}
|
|
30
10
|
}
|
|
@@ -1,25 +1,13 @@
|
|
|
1
|
-
import { _instanceof } from "amateras/lib/native";
|
|
2
|
-
import { $CSSMediaRule } from "#structure/$CSSMediaRule";
|
|
1
|
+
import { _Array_from, _instanceof, _Object_fromEntries } from "amateras/lib/native";
|
|
3
2
|
|
|
4
3
|
export abstract class $CSSRule {
|
|
5
4
|
rules = new Set<$CSSRule>();
|
|
6
|
-
|
|
7
|
-
constructor() {
|
|
8
|
-
|
|
9
|
-
abstract get css(): string;
|
|
10
|
-
|
|
11
|
-
get mediaRules() {
|
|
12
|
-
const rules: $CSSMediaRule[] = []
|
|
13
|
-
this.rules.forEach(rule => {
|
|
14
|
-
if (_instanceof(rule, $CSSMediaRule)) rules.push(rule);
|
|
15
|
-
rules.push(...rule.mediaRules)
|
|
16
|
-
})
|
|
17
|
-
return rules;
|
|
5
|
+
selector: string;
|
|
6
|
+
constructor(selector: string) {
|
|
7
|
+
this.selector = selector;
|
|
18
8
|
}
|
|
19
9
|
|
|
20
|
-
|
|
21
|
-
this.rules.
|
|
22
|
-
rule.ownerRule = this;
|
|
23
|
-
return this;
|
|
10
|
+
get options(): {[key: string]: any} {
|
|
11
|
+
return _Object_fromEntries(_Array_from(this.rules).map(rule => [rule.selector, rule.options]))
|
|
24
12
|
}
|
|
25
13
|
}
|
|
@@ -1,23 +1,14 @@
|
|
|
1
1
|
import type { $CSSDeclaration } from "#structure/$CSSDeclaration";
|
|
2
2
|
import { $CSSRule } from "#structure/$CSSRule";
|
|
3
|
-
import { _Array_from, _instanceof } from "amateras/lib/native";
|
|
3
|
+
import { _Array_from, _instanceof, _Object_fromEntries } from "amateras/lib/native";
|
|
4
4
|
|
|
5
5
|
export class $CSSStyleRule extends $CSSRule {
|
|
6
|
-
context: string[] = [];
|
|
7
6
|
declarations = new Map<string, $CSSDeclaration>();
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
super();
|
|
11
|
-
this.context = context;
|
|
7
|
+
constructor(selector: string) {
|
|
8
|
+
super(selector);
|
|
12
9
|
}
|
|
13
10
|
|
|
14
|
-
get
|
|
15
|
-
return
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
get selector() {
|
|
19
|
-
const ctx: string[][] = [];
|
|
20
|
-
this.context.forEach((part, i) => ctx.push(part.split(',').map(sel => ctx[i - 1] ? ctx[i - 1]!.map(prefix => `${prefix} ${sel.trim()}`) : [sel.trim()]).flat()))
|
|
21
|
-
return ctx.at(-1)?.join(', ')
|
|
11
|
+
get options(): {[key: string]: any} {
|
|
12
|
+
return {..._Object_fromEntries(_Array_from(this.declarations).map(([_, dec]) => [dec.key, dec])), ...super.options}
|
|
22
13
|
}
|
|
23
14
|
}
|
package/ext/html/html.ts
CHANGED
|
@@ -10,16 +10,4 @@ import './node/$Media';
|
|
|
10
10
|
import './node/$OptGroup';
|
|
11
11
|
import './node/$Option';
|
|
12
12
|
import './node/$Select';
|
|
13
|
-
import './node/$TextArea';
|
|
14
|
-
export * from './node/$Anchor';
|
|
15
|
-
export * from './node/$Canvas';
|
|
16
|
-
export * from './node/$Dialog';
|
|
17
|
-
export * from './node/$Form';
|
|
18
|
-
export * from './node/$Image';
|
|
19
|
-
export * from './node/$Input';
|
|
20
|
-
export * from './node/$Label';
|
|
21
|
-
export * from './node/$Media';
|
|
22
|
-
export * from './node/$OptGroup';
|
|
23
|
-
export * from './node/$Option';
|
|
24
|
-
export * from './node/$Select';
|
|
25
|
-
export * from './node/$TextArea';
|
|
13
|
+
import './node/$TextArea';
|
package/ext/html/node/$Anchor.ts
CHANGED
|
@@ -8,10 +8,40 @@ export class $Anchor extends $HTMLElement<HTMLAnchorElement> {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export interface $Anchor extends $HTMLElement<HTMLAnchorElement> {
|
|
11
|
-
href
|
|
11
|
+
/** {@link HTMLAnchorElement.href} */
|
|
12
|
+
href(href: $Parameter<string>): this;
|
|
12
13
|
href(): string;
|
|
14
|
+
/** {@link HTMLAnchorElement.hreflang} */
|
|
15
|
+
hreflang(hreflang: $Parameter<string>): this;
|
|
16
|
+
hreflang(): string;
|
|
17
|
+
/** {@link HTMLAnchorElement.download} */
|
|
18
|
+
download(download: $Parameter<string>): this;
|
|
19
|
+
download(): string;
|
|
20
|
+
/** {@link HTMLAnchorElement.ping} */
|
|
21
|
+
ping(ping: $Parameter<string>): this;
|
|
22
|
+
ping(): string;
|
|
23
|
+
/** {@link HTMLAnchorElement.referrerPolicy} */
|
|
24
|
+
referrerPolicy(referrerPolicy: $Parameter<string>): this;
|
|
25
|
+
referrerPolicy(): string;
|
|
26
|
+
/** {@link HTMLAnchorElement.rel} */
|
|
27
|
+
rel(rel: $Parameter<string>): this;
|
|
28
|
+
rel(): string;
|
|
29
|
+
/** {@link HTMLAnchorElement.relList} */
|
|
30
|
+
relList(relList: $Parameter<string>): this;
|
|
31
|
+
relList(): DOMTokenList;
|
|
32
|
+
/** {@link HTMLAnchorElement.target} */
|
|
33
|
+
target(target: $Parameter<AnchorTarget>): this;
|
|
34
|
+
target(): AnchorTarget;
|
|
35
|
+
/** {@link HTMLAnchorElement.text} */
|
|
36
|
+
text(text: $Parameter<string>): this;
|
|
37
|
+
text(): string;
|
|
38
|
+
/** {@link HTMLAnchorElement.type} */
|
|
39
|
+
type(type: $Parameter<string>): this;
|
|
40
|
+
type(): string;
|
|
13
41
|
}
|
|
14
42
|
|
|
43
|
+
export type AnchorTarget = '_self' | '_blank' | '_parent' | '_top' | '_unfenced_top' | '';
|
|
44
|
+
|
|
15
45
|
declare module '#core' {
|
|
16
46
|
export function $(nodeName: 'a'): $Anchor
|
|
17
47
|
}
|
package/ext/html/node/$Image.ts
CHANGED
|
@@ -8,8 +8,61 @@ export class $Image extends $HTMLElement<HTMLImageElement> {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export interface $Image extends $HTMLElement<HTMLImageElement> {
|
|
11
|
-
|
|
11
|
+
/** {@link HTMLImageElement.complete} */
|
|
12
|
+
readonly complete: boolean;
|
|
13
|
+
/** {@link HTMLImageElement.currentSrc} */
|
|
14
|
+
readonly currentSrc: string;
|
|
15
|
+
/** {@link HTMLImageElement.naturalHeight} */
|
|
16
|
+
readonly naturalHeight: number;
|
|
17
|
+
/** {@link HTMLImageElement.naturalWidth} */
|
|
18
|
+
readonly naturalWidth: number;
|
|
19
|
+
/** {@link HTMLImageElement.x} */
|
|
20
|
+
readonly x: number;
|
|
21
|
+
/** {@link HTMLImageElement.y} */
|
|
22
|
+
readonly y: number;
|
|
23
|
+
|
|
24
|
+
/** {@link HTMLImageElement.decode} */
|
|
25
|
+
decode(): Promise<this>;
|
|
26
|
+
|
|
27
|
+
/** {@link HTMLImageElement.alt} */
|
|
28
|
+
alt(alt: $Parameter<string>): this;
|
|
29
|
+
alt(): string;
|
|
30
|
+
/** {@link HTMLImageElement.crossOrigin} */
|
|
31
|
+
crossOrigin(crossOrigin: $Parameter<string | null>): this;
|
|
32
|
+
crossOrigin(): string | null;
|
|
33
|
+
/** {@link HTMLImageElement.decoding} */
|
|
34
|
+
decoding(decoding: $Parameter<"async" | "sync" | "auto">): this;
|
|
35
|
+
decoding(): "async" | "sync" | "auto";
|
|
36
|
+
/** {@link HTMLImageElement.fetchPriority} */
|
|
37
|
+
fetchPriority(fetchPriority: $Parameter<"high" | "low" | "auto">): this;
|
|
38
|
+
fetchPriority(): "high" | "low" | "auto";
|
|
39
|
+
/** {@link HTMLImageElement.height} */
|
|
40
|
+
height(height: $Parameter<number>): this;
|
|
41
|
+
height(): number;
|
|
42
|
+
/** {@link HTMLImageElement.isMap} */
|
|
43
|
+
isMap(isMap: $Parameter<boolean>): this;
|
|
44
|
+
isMap(): boolean;
|
|
45
|
+
/** {@link HTMLImageElement.loading} */
|
|
46
|
+
loading(loading: $Parameter<"eager" | "lazy">): this;
|
|
47
|
+
loading(): "eager" | "lazy";
|
|
48
|
+
/** {@link HTMLImageElement.referrerPolicy} */
|
|
49
|
+
referrerPolicy(referrerPolicy: $Parameter<string>): this;
|
|
50
|
+
referrerPolicy(): string;
|
|
51
|
+
/** {@link HTMLImageElement.sizes} */
|
|
52
|
+
sizes(sizes: $Parameter<string>): this;
|
|
53
|
+
sizes(): string;
|
|
54
|
+
/** {@link HTMLImageElement.src} */
|
|
55
|
+
src(src: $Parameter<string>): this;
|
|
12
56
|
src(): string;
|
|
57
|
+
/** {@link HTMLImageElement.srcset} */
|
|
58
|
+
srcset(srcset: $Parameter<string>): this;
|
|
59
|
+
srcset(): string;
|
|
60
|
+
/** {@link HTMLImageElement.useMap} */
|
|
61
|
+
useMap(useMap: $Parameter<string>): this;
|
|
62
|
+
useMap(): string;
|
|
63
|
+
/** {@link HTMLImageElement.width} */
|
|
64
|
+
width(width: $Parameter<number>): this;
|
|
65
|
+
width(): number;
|
|
13
66
|
}
|
|
14
67
|
|
|
15
68
|
assignHelper(HTMLImageElement, $Image, 'img');
|
package/ext/html/node/$Input.ts
CHANGED
|
@@ -7,7 +7,160 @@ export class $Input extends $HTMLElement<HTMLInputElement> {
|
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export interface $Input extends $HTMLElement<HTMLInputElement> {
|
|
10
|
+
export interface $Input extends $HTMLElement<HTMLInputElement> {
|
|
11
|
+
/** {@link HTMLInputElement.form} */
|
|
12
|
+
readonly form: HTMLFormElement | null;
|
|
13
|
+
/** {@link HTMLInputElement.labels} */
|
|
14
|
+
readonly labels: NodeListOf<HTMLLabelElement> | null;
|
|
15
|
+
/** {@link HTMLInputElement.list} */
|
|
16
|
+
readonly list: HTMLDataListElement | null;
|
|
17
|
+
/** {@link HTMLInputElement.validationMessage} */
|
|
18
|
+
readonly validationMessage: string;
|
|
19
|
+
/** {@link HTMLInputElement.validity} */
|
|
20
|
+
readonly validity: ValidityState;
|
|
21
|
+
/** {@link HTMLInputElement.webkitEntries} */
|
|
22
|
+
readonly webkitEntries: ReadonlyArray<FileSystemEntry>;
|
|
23
|
+
/** {@link HTMLInputElement.willValidate} */
|
|
24
|
+
readonly willValidate: boolean;
|
|
25
|
+
|
|
26
|
+
/** {@link HTMLInputElement.checkValidity} */
|
|
27
|
+
checkValidity(): boolean;
|
|
28
|
+
/** {@link HTMLInputElement.reportValidity} */
|
|
29
|
+
reportValidity(): boolean;
|
|
30
|
+
/** {@link HTMLInputElement.select} */
|
|
31
|
+
select(): this;
|
|
32
|
+
/** {@link HTMLInputElement.setCustomValidity} */
|
|
33
|
+
setCustomValidity(error: string): this;
|
|
34
|
+
/** {@link HTMLInputElement.setRangeText} */
|
|
35
|
+
setRangeText(replacement: string): this;
|
|
36
|
+
setRangeText(replacement: string, start: number, end: number, selectionMode?: SelectionMode): this;
|
|
37
|
+
/** {@link HTMLInputElement.setSelectionRange} */
|
|
38
|
+
setSelectionRange(start: number | null, end: number | null, direction?: "forward" | "backward" | "none"): this;
|
|
39
|
+
/** {@link HTMLInputElement.showPicker} */
|
|
40
|
+
showPicker(): this;
|
|
41
|
+
/** {@link HTMLInputElement.stepDown} */
|
|
42
|
+
stepDown(n?: number): this;
|
|
43
|
+
/** {@link HTMLInputElement.stepUp} */
|
|
44
|
+
stepUp(n?: number): this;
|
|
45
|
+
|
|
46
|
+
/** {@link HTMLInputElement.accept} */
|
|
47
|
+
accept(accept: $Parameter<string>): this;
|
|
48
|
+
accept(): string;
|
|
49
|
+
/** {@link HTMLInputElement.alt} */
|
|
50
|
+
alt(alt: $Parameter<string>): this;
|
|
51
|
+
alt(): string;
|
|
52
|
+
/** {@link HTMLInputElement.autoFill} */
|
|
53
|
+
autoFill(autoFill: $Parameter<AutoFill>): this;
|
|
54
|
+
autoFill(): AutoFill;
|
|
55
|
+
/** {@link HTMLInputElement.capture} */
|
|
56
|
+
capture(capture: $Parameter<string>): this;
|
|
57
|
+
capture(): string;
|
|
58
|
+
/** {@link HTMLInputElement.checked} */
|
|
59
|
+
checked(checked: $Parameter<boolean>): this;
|
|
60
|
+
checked(): boolean;
|
|
61
|
+
/** {@link HTMLInputElement.defaultChecked} */
|
|
62
|
+
defaultChecked(defaultChecked: $Parameter<boolean>): this;
|
|
63
|
+
defaultChecked(): string;
|
|
64
|
+
/** {@link HTMLInputElement.defaultValue} */
|
|
65
|
+
defaultValue(defaultValue: $Parameter<string>): this;
|
|
66
|
+
defaultValue(): string;
|
|
67
|
+
/** {@link HTMLInputElement.dirName} */
|
|
68
|
+
dirName(dirName: $Parameter<string>): this;
|
|
69
|
+
dirName(): string;
|
|
70
|
+
/** {@link HTMLInputElement.disabled} */
|
|
71
|
+
disabled(disabled: $Parameter<boolean>): this;
|
|
72
|
+
disabled(): boolean;
|
|
73
|
+
/** {@link HTMLInputElement.files} */
|
|
74
|
+
files(files: $Parameter<FileList | null>): this;
|
|
75
|
+
files(): string;
|
|
76
|
+
/** {@link HTMLInputElement.formAction} */
|
|
77
|
+
formAction(formAction: $Parameter<string>): this;
|
|
78
|
+
formAction(): string;
|
|
79
|
+
/** {@link HTMLInputElement.formEnctype} */
|
|
80
|
+
formEnctype(formEnctype: $Parameter<string>): this;
|
|
81
|
+
formEnctype(): string;
|
|
82
|
+
/** {@link HTMLInputElement.formMethod} */
|
|
83
|
+
formMethod(formMethod: $Parameter<string>): this;
|
|
84
|
+
formMethod(): string;
|
|
85
|
+
/** {@link HTMLInputElement.formNoValidate} */
|
|
86
|
+
formNoValidate(formNoValidate: $Parameter<boolean>): this;
|
|
87
|
+
formNoValidate(): boolean;
|
|
88
|
+
/** {@link HTMLInputElement.formTarget} */
|
|
89
|
+
formTarget(formTarget: $Parameter<string>): this;
|
|
90
|
+
formTarget(): string;
|
|
91
|
+
/** {@link HTMLInputElement.height} */
|
|
92
|
+
height(height: $Parameter<number>): this;
|
|
93
|
+
height(): number;
|
|
94
|
+
/** {@link HTMLInputElement.indeterminate} */
|
|
95
|
+
indeterminate(indeterminate: $Parameter<boolean>): this;
|
|
96
|
+
indeterminate(): boolean;
|
|
97
|
+
/** {@link HTMLInputElement.max} */
|
|
98
|
+
max(max: $Parameter<string>): this;
|
|
99
|
+
max(): string;
|
|
100
|
+
/** {@link HTMLInputElement.maxLength} */
|
|
101
|
+
maxLength(maxLength: $Parameter<number>): this;
|
|
102
|
+
maxLength(): number;
|
|
103
|
+
/** {@link HTMLInputElement.min} */
|
|
104
|
+
min(min: $Parameter<string>): this;
|
|
105
|
+
min(): string;
|
|
106
|
+
/** {@link HTMLInputElement.minLength} */
|
|
107
|
+
minLength(minLength: $Parameter<string>): this;
|
|
108
|
+
minLength(): string;
|
|
109
|
+
/** {@link HTMLInputElement.multiple} */
|
|
110
|
+
multiple(multiple: $Parameter<boolean>): this;
|
|
111
|
+
multiple(): boolean;
|
|
112
|
+
/** {@link HTMLInputElement.name} */
|
|
113
|
+
name(name: $Parameter<string>): this;
|
|
114
|
+
name(): string;
|
|
115
|
+
/** {@link HTMLInputElement.pattern} */
|
|
116
|
+
pattern(pattern: $Parameter<string>): this;
|
|
117
|
+
pattern(): string;
|
|
118
|
+
/** {@link HTMLInputElement.placeholder} */
|
|
119
|
+
placeholder(placeholder: $Parameter<string>): this;
|
|
120
|
+
placeholder(): string;
|
|
121
|
+
/** {@link HTMLInputElement.readOnly} */
|
|
122
|
+
readOnly(readOnly: $Parameter<boolean>): this;
|
|
123
|
+
readOnly(): boolean;
|
|
124
|
+
/** {@link HTMLInputElement.required} */
|
|
125
|
+
required(required: $Parameter<boolean>): this;
|
|
126
|
+
required(): boolean;
|
|
127
|
+
/** {@link HTMLInputElement.selectionDirection} */
|
|
128
|
+
selectionDirection(selectionDirection: $Parameter<'forward' | 'backward' | 'none' | null>): this;
|
|
129
|
+
selectionDirection(): 'forward' | 'backward' | 'none' | null;
|
|
130
|
+
/** {@link HTMLInputElement.selectionEnd} */
|
|
131
|
+
selectionEnd(selectionEnd: $Parameter<number | null>): this;
|
|
132
|
+
selectionEnd(): number | null;
|
|
133
|
+
/** {@link HTMLInputElement.selectionStart} */
|
|
134
|
+
selectionStart(selectionStart: $Parameter<number>): this;
|
|
135
|
+
selectionStart(): number;
|
|
136
|
+
/** {@link HTMLInputElement.size} */
|
|
137
|
+
size(size: $Parameter<number>): this;
|
|
138
|
+
size(): number;
|
|
139
|
+
/** {@link HTMLInputElement.src} */
|
|
140
|
+
src(src: $Parameter<string>): this;
|
|
141
|
+
src(): string;
|
|
142
|
+
/** {@link HTMLInputElement.step} */
|
|
143
|
+
step(step: $Parameter<string>): this;
|
|
144
|
+
step(): string;
|
|
145
|
+
/** {@link HTMLInputElement.type} */
|
|
146
|
+
type(type: $Parameter<string>): this;
|
|
147
|
+
type(): string;
|
|
148
|
+
/** {@link HTMLInputElement.value} */
|
|
149
|
+
value(value: $Parameter<string>): this;
|
|
150
|
+
value(): string;
|
|
151
|
+
/** {@link HTMLInputElement.valueAsDate} */
|
|
152
|
+
valueAsDate(valueAsDate: $Parameter<Date | null>): this;
|
|
153
|
+
valueAsDate(): Date | null;
|
|
154
|
+
/** {@link HTMLInputElement.valueAsNumber} */
|
|
155
|
+
valueAsNumber(valueAsNumber: $Parameter<number>): this;
|
|
156
|
+
valueAsNumber(): number;
|
|
157
|
+
/** {@link HTMLInputElement.webkitdirectory} */
|
|
158
|
+
webkitdirectory(webkitdirectory: $Parameter<boolean>): this;
|
|
159
|
+
webkitdirectory(): boolean;
|
|
160
|
+
/** {@link HTMLInputElement.width} */
|
|
161
|
+
width(width: $Parameter<number>): this;
|
|
162
|
+
width(): number;
|
|
163
|
+
}
|
|
11
164
|
|
|
12
165
|
assignHelper(HTMLInputElement, $Input, 'input');
|
|
13
166
|
|
|
@@ -7,7 +7,14 @@ export class $OptGroup extends $HTMLElement<HTMLOptGroupElement> {
|
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export interface $OptGroup extends $HTMLElement<HTMLOptGroupElement> {
|
|
10
|
+
export interface $OptGroup extends $HTMLElement<HTMLOptGroupElement> {
|
|
11
|
+
/** {@link HTMLOptGroupElement.disabled} */
|
|
12
|
+
disabled(disabled: $Parameter<boolean>): this;
|
|
13
|
+
disabled(): boolean;
|
|
14
|
+
/** {@link HTMLOptGroupElement.label} */
|
|
15
|
+
label(label: $Parameter<string>): this;
|
|
16
|
+
label(): string;
|
|
17
|
+
}
|
|
11
18
|
|
|
12
19
|
assignHelper(HTMLOptGroupElement, $OptGroup, 'optgroup');
|
|
13
20
|
|
package/ext/html/node/$Option.ts
CHANGED
|
@@ -7,7 +7,31 @@ export class $Option extends $HTMLElement<HTMLOptionElement> {
|
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export interface $Option extends $HTMLElement<HTMLOptionElement> {
|
|
10
|
+
export interface $Option extends $HTMLElement<HTMLOptionElement> {
|
|
11
|
+
/** {@link HTMLOptionElement.form} */
|
|
12
|
+
readonly form: HTMLFormElement | null;
|
|
13
|
+
/** {@link HTMLOptionElement.index} */
|
|
14
|
+
readonly index: number;
|
|
15
|
+
|
|
16
|
+
/** {@link HTMLOptionElement.defaultSelected} */
|
|
17
|
+
defaultSelected(defaultSelected: $Parameter<boolean>): this;
|
|
18
|
+
defaultSelected(): boolean;
|
|
19
|
+
/** {@link HTMLOptionElement.disabled} */
|
|
20
|
+
disabled(disabled: $Parameter<boolean>): this;
|
|
21
|
+
disabled(): boolean;
|
|
22
|
+
/** {@link HTMLOptionElement.label} */
|
|
23
|
+
label(label: $Parameter<string>): this;
|
|
24
|
+
label(): string;
|
|
25
|
+
/** {@link HTMLOptionElement.selected} */
|
|
26
|
+
selected(selected: $Parameter<boolean>): this;
|
|
27
|
+
selected(): boolean;
|
|
28
|
+
/** {@link HTMLOptionElement.text} */
|
|
29
|
+
text(text: $Parameter<string>): this;
|
|
30
|
+
text(): string;
|
|
31
|
+
/** {@link HTMLOptionElement.value} */
|
|
32
|
+
value(value: $Parameter<string>): this;
|
|
33
|
+
value(): string;
|
|
34
|
+
}
|
|
11
35
|
|
|
12
36
|
assignHelper(HTMLOptionElement, $Option, 'option');
|
|
13
37
|
|
package/ext/html/node/$Select.ts
CHANGED
|
@@ -7,7 +7,67 @@ export class $Select extends $HTMLElement<HTMLSelectElement> {
|
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export interface $Select extends $HTMLElement<HTMLSelectElement> {
|
|
10
|
+
export interface $Select extends $HTMLElement<HTMLSelectElement> {
|
|
11
|
+
/** {@link HTMLSelectElement.form} */
|
|
12
|
+
readonly form: HTMLFormElement | null;
|
|
13
|
+
/** {@link HTMLSelectElement.labels} */
|
|
14
|
+
readonly labels: NodeListOf<HTMLLabelElement>;
|
|
15
|
+
/** {@link HTMLSelectElement.options} */
|
|
16
|
+
readonly options: HTMLOptionsCollection;
|
|
17
|
+
/** {@link HTMLSelectElement.selectedOptions} */
|
|
18
|
+
readonly selectedOptions: HTMLCollectionOf<HTMLOptionElement>;
|
|
19
|
+
/** {@link HTMLSelectElement.type} */
|
|
20
|
+
readonly type: "select-one" | "select-multiple";
|
|
21
|
+
/** {@link HTMLSelectElement.validationMessage} */
|
|
22
|
+
readonly validationMessage: string;
|
|
23
|
+
/** {@link HTMLSelectElement.validity} */
|
|
24
|
+
readonly validity: ValidityState;
|
|
25
|
+
/** {@link HTMLSelectElement.willValidate} */
|
|
26
|
+
readonly willValidate: boolean;
|
|
27
|
+
|
|
28
|
+
/** {@link HTMLSelectElement.autocomplete} */
|
|
29
|
+
autocomplete(autocomplete: $Parameter<AutoFill>): this;
|
|
30
|
+
autocomplete(): AutoFill;
|
|
31
|
+
/** {@link HTMLSelectElement.disabled} */
|
|
32
|
+
disabled(disabled: $Parameter<boolean>): this;
|
|
33
|
+
disabled(): boolean;
|
|
34
|
+
/** {@link HTMLSelectElement.length} */
|
|
35
|
+
length(length: $Parameter<number>): this;
|
|
36
|
+
length(): number;
|
|
37
|
+
/** {@link HTMLSelectElement.multiple} */
|
|
38
|
+
multiple(multiple: $Parameter<boolean>): this;
|
|
39
|
+
multiple(): boolean;
|
|
40
|
+
/** {@link HTMLSelectElement.name} */
|
|
41
|
+
name(name: $Parameter<string>): this;
|
|
42
|
+
name(): string;
|
|
43
|
+
/** {@link HTMLSelectElement.required} */
|
|
44
|
+
required(required: $Parameter<boolean>): this;
|
|
45
|
+
required(): boolean;
|
|
46
|
+
/** {@link HTMLSelectElement.selectedIndex} */
|
|
47
|
+
selectedIndex(selectedIndex: $Parameter<number>): this;
|
|
48
|
+
selectedIndex(): number;
|
|
49
|
+
/** {@link HTMLSelectElement.size} */
|
|
50
|
+
size(size: $Parameter<number>): this;
|
|
51
|
+
size(): number;
|
|
52
|
+
/** {@link HTMLSelectElement.value} */
|
|
53
|
+
value(value: $Parameter<string>): this;
|
|
54
|
+
value(): string;
|
|
55
|
+
|
|
56
|
+
/** {@link HTMLSelectElement.add} */
|
|
57
|
+
add(element: HTMLOptionElement | HTMLOptGroupElement, before?: HTMLElement | number | null): this;
|
|
58
|
+
/** {@link HTMLSelectElement.checkValidity} */
|
|
59
|
+
checkValidity(): boolean;
|
|
60
|
+
/** {@link HTMLSelectElement.item} */
|
|
61
|
+
item(index: number): HTMLOptionElement | null;
|
|
62
|
+
/** {@link HTMLSelectElement.namedItem} */
|
|
63
|
+
namedItem(name: string): HTMLOptionElement | null;
|
|
64
|
+
/** {@link HTMLSelectElement.reportValidity} */
|
|
65
|
+
reportValidity(): boolean;
|
|
66
|
+
/** {@link HTMLSelectElement.setCustomValidity} */
|
|
67
|
+
setCustomValidity(error: string): this;
|
|
68
|
+
/** {@link HTMLSelectElement.showPicker} */
|
|
69
|
+
showPicker(): this;
|
|
70
|
+
}
|
|
11
71
|
|
|
12
72
|
assignHelper(HTMLSelectElement, $Select, 'select');
|
|
13
73
|
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# amateras/i18n
|
|
2
|
+
|
|
3
|
+
## Usage
|
|
4
|
+
```ts
|
|
5
|
+
import 'amateras';
|
|
6
|
+
import 'amateras/i18n';
|
|
7
|
+
|
|
8
|
+
const $t = $.i18n()
|
|
9
|
+
// add 'en' locale dictionary context
|
|
10
|
+
.add('en', {
|
|
11
|
+
homepage: {
|
|
12
|
+
_: 'Home',
|
|
13
|
+
hello: 'Hello, $name$!',
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
// set 'en' as locale language
|
|
17
|
+
.locale('en')
|
|
18
|
+
|
|
19
|
+
$(document.body).content([
|
|
20
|
+
$('h1').content( $t('homepage') )
|
|
21
|
+
// <h1><text>Home</text></h1>
|
|
22
|
+
$t('homepage.hello', {name: 'Amateras'})
|
|
23
|
+
// <text>Hello, Amateras!</text>
|
|
24
|
+
])
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Change Language
|
|
28
|
+
```ts
|
|
29
|
+
$t.locale('zh')
|
|
30
|
+
// all translation text will be updated
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Import Dictionary Context
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
// ./i18n/en.ts
|
|
37
|
+
export default {
|
|
38
|
+
hello: 'Hello, $name$!'
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ./i18n/zh.ts
|
|
42
|
+
export default {
|
|
43
|
+
hello: '您好,$name$!'
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ./entry_file.ts
|
|
47
|
+
const $t = $.i18n()
|
|
48
|
+
.add('en', () => import('./i18n/en.ts'))
|
|
49
|
+
.add('zh', () => import('./i18n/zh.ts'))
|
|
50
|
+
// set 'zh' as locale language
|
|
51
|
+
// and fetch file automatically from path
|
|
52
|
+
.locale('zh');
|
|
53
|
+
```
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { _Array_from, _instanceof, _Object_assign } from "amateras/lib/native"
|
|
2
|
+
import { $ } from "amateras/core"
|
|
3
|
+
import { I18n } from "#structure/I18n"
|
|
4
|
+
import type { I18nText as _I18nText, I18nTextOptions } from "#node/I18nText";
|
|
5
|
+
import { I18nDictionary, type I18nDictionaryContext, type I18nDictionaryContextImporter } from "#structure/I18nDictionary";
|
|
6
|
+
|
|
7
|
+
_Object_assign($, {
|
|
8
|
+
i18n(defaultLocale: string) {
|
|
9
|
+
const i18n = new I18n(defaultLocale);
|
|
10
|
+
const i18nFn = (key: string, options?: I18nTextOptions) => i18n.translate(key, options);
|
|
11
|
+
_Object_assign(i18nFn, {
|
|
12
|
+
i18n,
|
|
13
|
+
locale(locale: string) {
|
|
14
|
+
if (!arguments.length) return i18n.locale();
|
|
15
|
+
i18n.locale(locale);
|
|
16
|
+
return this;
|
|
17
|
+
},
|
|
18
|
+
add(lang: string, context: I18nDictionaryContext | I18nDictionaryContextImporter) {
|
|
19
|
+
i18n.map.set(lang, new I18nDictionary(context));
|
|
20
|
+
return this;
|
|
21
|
+
},
|
|
22
|
+
delete(lang: string) {
|
|
23
|
+
i18n.map.delete(lang);
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
return i18nFn
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
type ResolvedAsyncDictionary<F extends I18nDictionaryContextImporter> = Awaited<ReturnType<F>>['default'];
|
|
32
|
+
|
|
33
|
+
type DeepKeys<T> = T extends I18nDictionaryContext
|
|
34
|
+
? {
|
|
35
|
+
[K in keyof T]: K extends string
|
|
36
|
+
? K extends '_' ? never : `${K}` | `${K}.${DeepKeys<T[K]>}`
|
|
37
|
+
: never;
|
|
38
|
+
}[keyof T]
|
|
39
|
+
: never;
|
|
40
|
+
|
|
41
|
+
declare module "amateras/core" {
|
|
42
|
+
export namespace $ {
|
|
43
|
+
export interface I18nFunction<D extends I18nDictionaryContext = {}> {
|
|
44
|
+
(path: DeepKeys<D>, ...args: any[]): I18nText;
|
|
45
|
+
i18n: I18n;
|
|
46
|
+
locale(): string;
|
|
47
|
+
locale(lang?: $Parameter<string>): this;
|
|
48
|
+
add<F extends I18nDictionaryContext | I18nDictionaryContextImporter>(lang: string, dictionary: F): I18nFunction<D | (F extends I18nDictionaryContextImporter ? ResolvedAsyncDictionary<F> : F)>;
|
|
49
|
+
delete(lang: string): this;
|
|
50
|
+
}
|
|
51
|
+
export function i18n(defaultLocale: string): I18nFunction;
|
|
52
|
+
export type I18nText = _I18nText;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { _Array_from, isUndefined } from "amateras/lib/native";
|
|
2
|
+
import { $HTMLElement } from "amateras/node/$HTMLElement";
|
|
3
|
+
import type { I18n } from "#structure/I18n";
|
|
4
|
+
|
|
5
|
+
export class I18nText extends $HTMLElement<HTMLElement, { i18nupdate: Event }> {
|
|
6
|
+
i18n: I18n;
|
|
7
|
+
key: string;
|
|
8
|
+
options: I18nTextOptions | undefined;
|
|
9
|
+
constructor(i18n: I18n, key: string, options?: I18nTextOptions) {
|
|
10
|
+
super('text');
|
|
11
|
+
this.i18n = i18n;
|
|
12
|
+
this.key = key;
|
|
13
|
+
this.options = options;
|
|
14
|
+
i18n.locale$.signal.subscribe(() => this.update())
|
|
15
|
+
this.update();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async update() {
|
|
19
|
+
update: {
|
|
20
|
+
const {key, i18n} = this;
|
|
21
|
+
const dictionary = i18n.dictionary();
|
|
22
|
+
if (!dictionary) {this.content(key); break update}
|
|
23
|
+
const target = await dictionary.find(key);
|
|
24
|
+
if (isUndefined(target)) break update;
|
|
25
|
+
const snippets = target.split(/\$[a-zA-Z0-9_]+\$/);
|
|
26
|
+
if (snippets.length === 1 || !this.options) {this.content(target); break update}
|
|
27
|
+
const matches = target.matchAll(/(\$([a-zA-Z0-9_]+)\$)/g);
|
|
28
|
+
this.content(snippets.map(text => [text, this.options?.[matches.next().value?.at(2)!] ?? null]));
|
|
29
|
+
}
|
|
30
|
+
this.dispatchEvent(new Event('i18nupdate'));
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type I18nTextOptions = {[key: string]: any}
|