amateras 0.0.1 → 0.1.1
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 +10 -3
- package/ext/css/README.md +109 -0
- package/ext/css/package.json +9 -0
- package/ext/css/src/index.ts +442 -0
- package/ext/css/{$CSSDeclaration.ts → src/structure/$CSSDeclaration.ts} +4 -0
- package/ext/css/src/structure/$CSSKeyframeRule.ts +13 -0
- package/ext/css/src/structure/$CSSKeyframesRule.ts +17 -0
- package/ext/css/src/structure/$CSSMediaRule.ts +30 -0
- package/ext/css/src/structure/$CSSRule.ts +25 -0
- package/ext/css/src/structure/$CSSStyleRule.ts +23 -0
- package/ext/css/src/structure/$CSSVariable.ts +12 -0
- package/package.json +9 -4
- package/src/core.ts +16 -11
- package/src/lib/assign.ts +4 -3
- package/src/lib/assignHelper.ts +2 -1
- package/src/lib/native.ts +34 -0
- package/src/lib/randomId.ts +6 -4
- package/src/node/$Element.ts +6 -5
- package/src/node/$Node.ts +12 -11
- package/src/structure/Signal.ts +3 -1
- package/ext/css/$CSSMediaRule.ts +0 -13
- package/ext/css/$CSSRule.ts +0 -7
- package/ext/css/$CSSStyleRule.ts +0 -20
- package/ext/css/css.ts +0 -101
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Amateras
|
|
2
2
|
Amateras is a DOM Utility library.
|
|
3
3
|
|
|
4
|
-
## Build DOM
|
|
4
|
+
## Build DOM Tree in JS
|
|
5
5
|
```ts
|
|
6
6
|
import 'amateras';
|
|
7
7
|
|
|
8
8
|
$(document.body).content([
|
|
9
|
-
$('h1').
|
|
9
|
+
$('h1').class('title').content('Hello, World')
|
|
10
10
|
])
|
|
11
11
|
```
|
|
12
12
|
|
|
@@ -80,4 +80,11 @@ function NameCard(name: string, avatarURL: string) {
|
|
|
80
80
|
$(document.body).content([
|
|
81
81
|
$(NameCard, 'The dancing man', 'https://media.tenor.com/x8v1oNUOmg4AAAAM/rickroll-roll.gif')
|
|
82
82
|
])
|
|
83
|
-
```
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Packages
|
|
86
|
+
|-|-|
|
|
87
|
+
|Package name|Size|Size(gzip)|Description|
|
|
88
|
+
|amateras|5.56 kB|2.35 kB|Core
|
|
89
|
+
|amateras/html|0.66 kB|0.28 kB|Import HTMLElement types and methods|
|
|
90
|
+
|[amateras/css](./ext/css/README.md)|3.74 kB|1.40 kB|Style in JS|
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# amateras/css
|
|
2
|
+
|
|
3
|
+
## Usage
|
|
4
|
+
```ts
|
|
5
|
+
import 'amateras';
|
|
6
|
+
import 'amateras/css';
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Define Style
|
|
10
|
+
```ts
|
|
11
|
+
const style = $.css({
|
|
12
|
+
backgroundColor: 'black',
|
|
13
|
+
margin: 0,
|
|
14
|
+
|
|
15
|
+
'p': {
|
|
16
|
+
color: 'blue'
|
|
17
|
+
|
|
18
|
+
'@media (max-width: 800px)': {
|
|
19
|
+
color: 'red'
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
$(document.body).css(style).content([
|
|
25
|
+
$('p').content('Text with blue color.')
|
|
26
|
+
]);
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Define Style in Method Chain
|
|
30
|
+
```ts
|
|
31
|
+
$(document.body).content([
|
|
32
|
+
$('h1').css({ color: 'red' }).content('This is a title with red color!')
|
|
33
|
+
])
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Define Variables
|
|
37
|
+
|
|
38
|
+
### Single Variable
|
|
39
|
+
```ts
|
|
40
|
+
const largeText = $.css.variables('1.2rem');
|
|
41
|
+
|
|
42
|
+
$.css({
|
|
43
|
+
fontSize: largeText
|
|
44
|
+
})
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Variable Group
|
|
48
|
+
```ts
|
|
49
|
+
const text = $.css.variables({
|
|
50
|
+
small: '0.8rem',
|
|
51
|
+
medium: '1rem',
|
|
52
|
+
large: '1.2rem'
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
$.css({
|
|
56
|
+
fontSize: text.large
|
|
57
|
+
})
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Define Keyframes
|
|
61
|
+
```ts
|
|
62
|
+
const keyframes = $.css.keyframes({
|
|
63
|
+
fadeIn: {
|
|
64
|
+
'0%': { opacity: 0 },
|
|
65
|
+
'100%': { opacity: 1 }
|
|
66
|
+
},
|
|
67
|
+
fadeOut: {
|
|
68
|
+
from: { opacity: 1 },
|
|
69
|
+
to: { opacity: 0 }
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
$.css({
|
|
74
|
+
animation: keyframes.fadeIn
|
|
75
|
+
})
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Define CSS Rules with Selectors
|
|
79
|
+
```ts
|
|
80
|
+
$.CSS({
|
|
81
|
+
'html': {
|
|
82
|
+
fontSize: '18px',
|
|
83
|
+
fontFamily: 'Noto Sans',
|
|
84
|
+
|
|
85
|
+
'body': {
|
|
86
|
+
margin: 0,
|
|
87
|
+
|
|
88
|
+
'.title': {
|
|
89
|
+
color: 'red'
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
'@media (max-width: 800px)': {
|
|
95
|
+
'html': {
|
|
96
|
+
fontSize: '1rem',
|
|
97
|
+
|
|
98
|
+
'@media (orientation: landscape)': {
|
|
99
|
+
fontSize: '1.2rem'
|
|
100
|
+
},
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
$(document.body).content([
|
|
106
|
+
$('h1').class('title').content('A red color title.')
|
|
107
|
+
])
|
|
108
|
+
|
|
109
|
+
```
|
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
import { _instanceof, _Object_assign, _Object_entries, _Object_fromEntries, isObject, isUndefined } from "amateras/lib/native";
|
|
2
|
+
import { randomId } from "amateras/lib/randomId";
|
|
3
|
+
import { $Element } from "amateras/node/$Element";
|
|
4
|
+
import { $CSSDeclaration } from "#structure/$CSSDeclaration";
|
|
5
|
+
import { $CSSMediaRule } from "#structure/$CSSMediaRule";
|
|
6
|
+
import { $CSSRule } from "#structure/$CSSRule";
|
|
7
|
+
import { $CSSStyleRule } from "#structure/$CSSStyleRule";
|
|
8
|
+
import { $CSSKeyframesRule } from "#structure/$CSSKeyframesRule";
|
|
9
|
+
import { $CSSVariable } from "#structure/$CSSVariable";
|
|
10
|
+
import { $CSSKeyframeRule } from "#structure/$CSSKeyframeRule";
|
|
11
|
+
|
|
12
|
+
declare module 'amateras/core' {
|
|
13
|
+
export namespace $ {
|
|
14
|
+
export function css(options: $CSSOptions): $CSSStyleRule
|
|
15
|
+
export function CSS(options: $CSSSelectorType | $CSSMediaSelectorType<false> | $CSSKeyframesSelectorType): void
|
|
16
|
+
|
|
17
|
+
export namespace css {
|
|
18
|
+
export function variables(value: string): $CSSVariable;
|
|
19
|
+
export function variables<T extends $CSSVariableType>(options: T, conditions?: $CSSVariableConditionType<T>): { [key in keyof T]: $CSSVariable }
|
|
20
|
+
export function keyframes<T extends { [key: string]: $CSSKeyframesType }>(options: T): { [key in keyof T]: $CSSKeyframesRule };
|
|
21
|
+
export const stylesheet: CSSStyleSheet;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
declare module 'amateras/node/$Element' {
|
|
27
|
+
export interface $Element {
|
|
28
|
+
css(...options: $CSSOptions[]): this;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const generatedIds = new Set<string>();
|
|
33
|
+
function generateId(lettercase?: 'any' | 'lower' | 'upper'): string {
|
|
34
|
+
const id = randomId({lettercase: lettercase});
|
|
35
|
+
if (generatedIds.has(id)) return generateId(lettercase);
|
|
36
|
+
generatedIds.add(id);
|
|
37
|
+
return id;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const stylesheet = new CSSStyleSheet();
|
|
41
|
+
document.adoptedStyleSheets.push(stylesheet);
|
|
42
|
+
|
|
43
|
+
function processCSSOptions<T extends $CSSStyleRule | $CSSKeyframeRule>(
|
|
44
|
+
rule: T,
|
|
45
|
+
options: $CSSDeclarationType | $CSSSelectorType | $CSSMediaSelectorType<boolean>,
|
|
46
|
+
context: string[] = [],
|
|
47
|
+
): T {
|
|
48
|
+
for (const [key, value] of _Object_entries(options)) {
|
|
49
|
+
if (isUndefined(value)) continue;
|
|
50
|
+
if (isObject(value) && !_instanceof(value, $CSSKeyframesRule) && !_instanceof(value, $CSSVariable))
|
|
51
|
+
rule.addRule( createRule(key, value, context) );
|
|
52
|
+
else {
|
|
53
|
+
const declaration = new $CSSDeclaration(key, `${value}`);
|
|
54
|
+
rule.declarations.set(declaration.key, declaration);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return rule;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function createRule(selector: string, options: $CSSOptions, context: string[] = [], global = false) {
|
|
61
|
+
if (selector.startsWith('@media')) return createMediaRule(selector.replace('@media ', ''), options, context, global);
|
|
62
|
+
if (selector.startsWith('@keyframes')) return createKeyframesRule(selector.replace('@keyframes ', ''), options as $CSSKeyframesType)
|
|
63
|
+
return createStyleRule(options, [...context, selector]);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function createStyleRule<T extends $CSSRule>(options: T, context?: string[]): T;
|
|
67
|
+
function createStyleRule<T extends $CSSOptions>(options: T, context?: string[]): $CSSStyleRule;
|
|
68
|
+
function createStyleRule<T extends $CSSOptions>(options: T, context: string[] = []) {
|
|
69
|
+
if (_instanceof(options, $CSSRule)) return options;
|
|
70
|
+
return processCSSOptions(new $CSSStyleRule(context), options, context);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function createMediaRule(condition: string, options: $CSSOptions, context: string[] = [], global: boolean) {
|
|
74
|
+
const rule = new $CSSMediaRule(condition);
|
|
75
|
+
// create media rule from $.CSS
|
|
76
|
+
if (global) _Object_entries(options).forEach(([key, value]) => rule.addRule( createRule(key, value, context) ))
|
|
77
|
+
// create from $.css
|
|
78
|
+
else rule.addRule( createStyleRule(options, context) );
|
|
79
|
+
return rule;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function createKeyframesRule(name: string, options: $CSSKeyframesType) {
|
|
83
|
+
const rule = new $CSSKeyframesRule(name);
|
|
84
|
+
_Object_entries(options).forEach(([key, value]) => {
|
|
85
|
+
rule.addRule( processCSSOptions(new $CSSKeyframeRule(key), value) );
|
|
86
|
+
})
|
|
87
|
+
return rule;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function insertRule(rule: $CSSRule, recursive = false) {
|
|
91
|
+
if (_instanceof(rule, $CSSStyleRule) && !CSS.supports(`selector(${rule.selector})`)) return rule;
|
|
92
|
+
stylesheet.insertRule(rule.css, stylesheet.cssRules.length);
|
|
93
|
+
if (_instanceof(rule, $CSSKeyframesRule)) return rule;
|
|
94
|
+
if (!_instanceof(rule, $CSSMediaRule)) rule.rules.forEach(rule => insertRule(rule));
|
|
95
|
+
else if (!recursive) rule.mediaRules.forEach(rule => insertRule(rule, true));
|
|
96
|
+
return rule;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
_Object_assign($, {
|
|
100
|
+
css(options: $CSSOptions) {
|
|
101
|
+
if (_instanceof(options, $CSSRule)) return options;
|
|
102
|
+
const className = `.${generateId()}`;
|
|
103
|
+
const rule = createStyleRule(options, [className]);
|
|
104
|
+
rule.className = className;
|
|
105
|
+
return insertRule( rule );
|
|
106
|
+
},
|
|
107
|
+
CSS(options: $CSSSelectorType | $CSSMediaRule) {
|
|
108
|
+
return _Object_entries(options).map(([selector, declarations]) => {
|
|
109
|
+
return insertRule( createRule(selector, declarations, [], true) );
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
_Object_assign($.css, {
|
|
115
|
+
stylesheet: stylesheet,
|
|
116
|
+
variables<T extends $CSSVariableType | string>(options: T, conditions?: $CSSVariableConditionType<T>) {
|
|
117
|
+
if (isObject(options)) {
|
|
118
|
+
const variables = _Object_fromEntries(_Object_entries(options).map(([key, value]) => [
|
|
119
|
+
key,
|
|
120
|
+
new $CSSVariable(`${key.replaceAll(/([A-Z])/g, ((_, $1) => `-${$1.toLowerCase()}`))}_${generateId('lower')}`, `${value}`)
|
|
121
|
+
]))
|
|
122
|
+
|
|
123
|
+
const conditionObj = conditions ? _Object_entries(conditions).map(([condition, _options]) => [
|
|
124
|
+
condition,
|
|
125
|
+
_Object_fromEntries(_Object_entries(_options).map(([key, value]) => [`--${variables[key]?.key}`, `${value}`] as const))
|
|
126
|
+
] as const) : [];
|
|
127
|
+
|
|
128
|
+
$.CSS({':root': {
|
|
129
|
+
..._Object_fromEntries(_Object_entries(variables).map(([_, varobj]) => [`--${varobj.key}`, varobj.value])),
|
|
130
|
+
..._Object_fromEntries(conditionObj)
|
|
131
|
+
}})
|
|
132
|
+
|
|
133
|
+
return variables;
|
|
134
|
+
} else {
|
|
135
|
+
const variable = new $CSSVariable(generateId('lower'), options);
|
|
136
|
+
$.CSS({':root': {[`--${variable.key}`]: variable.value}});
|
|
137
|
+
return variable;
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
keyframes(options: $CSSKeyframesType) {
|
|
141
|
+
return _Object_fromEntries( _Object_entries(options).map(([name, value]) => {
|
|
142
|
+
return [name, insertRule( createKeyframesRule(`${name}_${generateId()}`, value) )];
|
|
143
|
+
}) )
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
_Object_assign($Element.prototype, {
|
|
148
|
+
css(this: $Element, ...options: $CSSOptions[]) {
|
|
149
|
+
options.forEach(options => {
|
|
150
|
+
const rule = $.css(options);
|
|
151
|
+
this.addClass(rule.context[0]?.slice(1) as string);
|
|
152
|
+
})
|
|
153
|
+
return this;
|
|
154
|
+
}
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
export * from "#structure/$CSSDeclaration";
|
|
158
|
+
export * from "#structure/$CSSKeyframeRule";
|
|
159
|
+
export * from "#structure/$CSSKeyframesRule";
|
|
160
|
+
export * from "#structure/$CSSMediaRule";
|
|
161
|
+
export * from "#structure/$CSSRule";
|
|
162
|
+
export * from "#structure/$CSSStyleRule";
|
|
163
|
+
export * from "#structure/$CSSVariable";
|
|
164
|
+
|
|
165
|
+
type $CSSOptions = $CSSDeclarationType | $CSSSelectorType | $CSSStyleRule | $CSSMediaSelectorType<true>;
|
|
166
|
+
type $CSSValueType = '' | 'unset' | 'initial' | 'inherit' | string & {} | number | $CSSVariable
|
|
167
|
+
type $CSSDeclarationType = { [key in keyof $CSSDeclarationMap]?: $CSSDeclarationMap[key] }
|
|
168
|
+
type $CSSSelectorType = { [key: string & {}]: $CSSOptions }
|
|
169
|
+
type $CSSMediaSelectorType<Nested extends boolean> = { [key: `@media ${string}`]: Nested extends true ? $CSSOptions : $CSSSelectorType | $CSSMediaSelectorType<Nested> }
|
|
170
|
+
type $CSSVariableType<T = any> = { [key in keyof T]: $CSSValueType }
|
|
171
|
+
type $CSSVariableConditionType<T extends $CSSVariableType | string> = T extends string ? { [key: string]: $CSSValueType } : { [key: string]: $CSSVariableType<T> }
|
|
172
|
+
type $CSSKeyframesSelectorType = { [key: `@keyframes ${string}`]: $CSSKeyframesType }
|
|
173
|
+
type $CSSKeyframesType = { [key: `${number}%`]: $CSSDeclarationType } | { from?: $CSSDeclarationType, to?: $CSSDeclarationType }
|
|
174
|
+
|
|
175
|
+
type $CSSDeclarationMap = {
|
|
176
|
+
[key in keyof CSSStyleDeclaration]: $CSSValueType;
|
|
177
|
+
} | {
|
|
178
|
+
alignContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly' | 'stretch' | 'normal';
|
|
179
|
+
alignItems?: 'normal' | 'stretch' | 'center' | 'flex-start' | 'flex-end' | 'baseline';
|
|
180
|
+
alignSelf?: 'auto' | 'normal' | 'stretch' | 'center' | 'flex-start' | 'flex-end' | 'baseline';
|
|
181
|
+
all?: 'initial' | 'inherit' | 'unset';
|
|
182
|
+
animation?: string | $CSSKeyframesRule;
|
|
183
|
+
animationDelay?: string;
|
|
184
|
+
animationDirection?: 'normal' | 'reverse' | 'alternate' | 'alternate-reverse';
|
|
185
|
+
animationDuration?: string;
|
|
186
|
+
animationFillMode?: 'none' | 'forwards' | 'backwards' | 'both';
|
|
187
|
+
animationIterationCount?: 'infinite' | number;
|
|
188
|
+
animationName?: string | $CSSKeyframesRule;
|
|
189
|
+
animationPlayState?: 'running' | 'paused';
|
|
190
|
+
animationTimingFunction?: 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'linear' | 'step-start' | 'step-end';
|
|
191
|
+
animationComposition?: 'replace' | 'add' | 'accumulate';
|
|
192
|
+
backdropFilter?: string;
|
|
193
|
+
backfaceVisibility?: 'visible' | 'hidden';
|
|
194
|
+
background?: string;
|
|
195
|
+
backgroundAttachment?: 'scroll' | 'fixed' | 'local';
|
|
196
|
+
backgroundBlendMode?: 'normal' | 'multiply' | 'screen' | 'overlay' | 'darken' | 'lighten' | 'color-dodge' | 'color-burn' | 'hard-light' | 'soft-light' | 'difference' | 'exclusion' | 'hue' | 'saturation' | 'color' | 'luminosity';
|
|
197
|
+
backgroundClip?: 'border-box' | 'padding-box' | 'content-box' | 'text';
|
|
198
|
+
backgroundColor?: string;
|
|
199
|
+
backgroundImage?: string;
|
|
200
|
+
backgroundOrigin?: 'border-box' | 'padding-box' | 'content-box';
|
|
201
|
+
backgroundPosition?: string;
|
|
202
|
+
backgroundRepeat?: 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat' | 'space' | 'round';
|
|
203
|
+
backgroundSize?: 'auto' | 'cover' | 'contain';
|
|
204
|
+
border?: string;
|
|
205
|
+
borderBottom?: string;
|
|
206
|
+
borderBottomColor?: string;
|
|
207
|
+
borderBottomLeftRadius?: string;
|
|
208
|
+
borderBottomRightRadius?: string;
|
|
209
|
+
borderBottomStyle?: 'none' | 'hidden' | 'dotted' | 'dashed' | 'solid' | 'double' | 'groove' | 'ridge' | 'inset' | 'outset';
|
|
210
|
+
borderBottomWidth?: string;
|
|
211
|
+
borderCollapse?: 'collapse' | 'separate';
|
|
212
|
+
borderColor?: string;
|
|
213
|
+
borderImage?: string;
|
|
214
|
+
borderImageOutset?: string;
|
|
215
|
+
borderImageRepeat?: 'stretch' | 'repeat' | 'round' | 'space';
|
|
216
|
+
borderImageSlice?: string;
|
|
217
|
+
borderImageSource?: string;
|
|
218
|
+
borderImageWidth?: string;
|
|
219
|
+
borderLeft?: string;
|
|
220
|
+
borderLeftColor?: string;
|
|
221
|
+
borderLeftStyle?: 'none' | 'hidden' | 'dotted' | 'dashed' | 'solid' | 'double' | 'groove' | 'ridge' | 'inset' | 'outset';
|
|
222
|
+
borderLeftWidth?: string;
|
|
223
|
+
borderRadius?: string;
|
|
224
|
+
borderRight?: string;
|
|
225
|
+
borderRightColor?: string;
|
|
226
|
+
borderRightStyle?: 'none' | 'hidden' | 'dotted' | 'dashed' | 'solid' | 'double' | 'groove' | 'ridge' | 'inset' | 'outset';
|
|
227
|
+
borderRightWidth?: string;
|
|
228
|
+
borderSpacing?: string;
|
|
229
|
+
borderStyle?: 'none' | 'hidden' | 'dotted' | 'dashed' | 'solid' | 'double' | 'groove' | 'ridge' | 'inset' | 'outset';
|
|
230
|
+
borderTop?: string;
|
|
231
|
+
borderTopColor?: string;
|
|
232
|
+
borderTopLeftRadius?: string;
|
|
233
|
+
borderTopRightRadius?: string;
|
|
234
|
+
borderTopStyle?: 'none' | 'hidden' | 'dotted' | 'dashed' | 'solid' | 'double' | 'groove' | 'ridge' | 'inset' | 'outset';
|
|
235
|
+
borderTopWidth?: string;
|
|
236
|
+
borderWidth?: string;
|
|
237
|
+
bottom?: string;
|
|
238
|
+
boxShadow?: string;
|
|
239
|
+
boxSizing?: 'content-box' | 'border-box';
|
|
240
|
+
breakAfter?: 'auto' | 'avoid' | 'always' | 'all' | 'avoid-page' | 'page' | 'left' | 'right' | 'recto' | 'verso' | 'column' | 'avoid-column';
|
|
241
|
+
breakBefore?: 'auto' | 'avoid' | 'always' | 'all' | 'avoid-page' | 'page' | 'left' | 'right' | 'recto' | 'verso' | 'column' | 'avoid-column';
|
|
242
|
+
breakInside?: 'auto' | 'avoid' | 'avoid-page' | 'avoid-column';
|
|
243
|
+
captionSide?: 'top' | 'bottom';
|
|
244
|
+
caretColor?: string;
|
|
245
|
+
clear?: 'none' | 'left' | 'right' | 'both';
|
|
246
|
+
clip?: string;
|
|
247
|
+
clipPath?: string;
|
|
248
|
+
color?: string;
|
|
249
|
+
columnCount?: 'auto' | number;
|
|
250
|
+
columnFill?: 'balance' | 'auto';
|
|
251
|
+
columnGap?: string;
|
|
252
|
+
columnRule?: string;
|
|
253
|
+
columnRuleColor?: string;
|
|
254
|
+
columnRuleStyle?: 'none' | 'hidden' | 'dotted' | 'dashed' | 'solid' | 'double' | 'groove' | 'ridge' | 'inset' | 'outset';
|
|
255
|
+
columnRuleWidth?: string;
|
|
256
|
+
columnSpan?: 'none' | 'all';
|
|
257
|
+
columnWidth?: string;
|
|
258
|
+
columns?: string;
|
|
259
|
+
content?: string;
|
|
260
|
+
counterIncrement?: string;
|
|
261
|
+
counterReset?: string;
|
|
262
|
+
cursor?: 'auto' | 'default' | 'none' | 'context-menu' | 'help' | 'pointer' | 'progress' | 'wait' | 'cell' | 'crosshair' | 'text' | 'vertical-text' | 'alias' | 'copy' | 'move' | 'no-drop' | 'not-allowed' | 'e-resize' | 'n-resize' | 'ne-resize' | 'nw-resize' | 's-resize' | 'se-resize' | 'sw-resize' | 'w-resize' | 'ew-resize' | 'ns-resize' | 'nesw-resize' | 'nwse-resize' | 'col-resize' | 'row-resize' | 'all-scroll' | 'zoom-in' | 'zoom-out' | 'grab' | 'grabbing';
|
|
263
|
+
direction?: 'ltr' | 'rtl';
|
|
264
|
+
display?: 'block' | 'inline' | 'inline-block' | 'flex' | 'inline-flex' | 'grid' | 'inline-grid' | 'flow-root' | 'none' | 'contents' | 'table' | 'table-row' | 'table-cell' | 'table-column' | 'table-column-group' | 'table-header-group' | 'table-footer-group' | 'table-row-group' | 'list-item';
|
|
265
|
+
emptyCells?: 'show' | 'hide';
|
|
266
|
+
filter?: string;
|
|
267
|
+
flex?: string;
|
|
268
|
+
flexBasis?: string;
|
|
269
|
+
flexDirection?: 'row' | 'row-reverse' | 'column' | 'column-reverse';
|
|
270
|
+
flexFlow?: string;
|
|
271
|
+
flexGrow?: number;
|
|
272
|
+
flexShrink?: number;
|
|
273
|
+
flexWrap?: 'nowrap' | 'wrap' | 'wrap-reverse';
|
|
274
|
+
float?: 'left' | 'right' | 'none';
|
|
275
|
+
font?: string;
|
|
276
|
+
fontFamily?: string;
|
|
277
|
+
fontFeatureSettings?: string;
|
|
278
|
+
fontKerning?: 'auto' | 'normal' | 'none';
|
|
279
|
+
fontLanguageOverride?: string;
|
|
280
|
+
fontOpticalSizing?: 'auto' | 'none';
|
|
281
|
+
fontSize?: string;
|
|
282
|
+
fontSizeAdjust?: string;
|
|
283
|
+
fontStretch?: 'normal' | 'ultra-condensed' | 'extra-condensed' | 'condensed' | 'semi-condensed' | 'semi-expanded' | 'expanded' | 'extra-expanded' | 'ultra-expanded';
|
|
284
|
+
fontStyle?: 'normal' | 'italic' | 'oblique';
|
|
285
|
+
fontSynthesis?: string;
|
|
286
|
+
fontVariant?: 'normal' | 'small-caps';
|
|
287
|
+
fontVariantCaps?: 'normal' | 'small-caps' | 'all-small-caps' | 'petite-caps' | 'all-petite-caps' | 'unicase' | 'titling-caps';
|
|
288
|
+
fontVariantEastAsian?: string;
|
|
289
|
+
fontVariantLigatures?: string;
|
|
290
|
+
fontVariantNumeric?: string;
|
|
291
|
+
fontVariantPosition?: 'normal' | 'sub' | 'super';
|
|
292
|
+
fontWeight?: 'normal' | 'bold' | 'bolder' | 'lighter' | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
|
|
293
|
+
gap?: string;
|
|
294
|
+
grid?: string;
|
|
295
|
+
gridArea?: string;
|
|
296
|
+
gridAutoColumns?: string;
|
|
297
|
+
gridAutoFlow?: 'row' | 'column' | 'dense' | 'row dense' | 'column dense';
|
|
298
|
+
gridAutoRows?: string;
|
|
299
|
+
gridColumn?: string;
|
|
300
|
+
gridColumnEnd?: string;
|
|
301
|
+
gridColumnGap?: string;
|
|
302
|
+
gridColumnStart?: string;
|
|
303
|
+
gridGap?: string;
|
|
304
|
+
gridRow?: string;
|
|
305
|
+
gridRowEnd?: string;
|
|
306
|
+
gridRowGap?: string;
|
|
307
|
+
gridRowStart?: string;
|
|
308
|
+
gridTemplate?: string;
|
|
309
|
+
gridTemplateAreas?: string;
|
|
310
|
+
gridTemplateColumns?: string;
|
|
311
|
+
gridTemplateRows?: string;
|
|
312
|
+
height?: string;
|
|
313
|
+
hyphens?: 'none' | 'manual' | 'auto';
|
|
314
|
+
imageRendering?: 'auto' | 'crisp-edges' | 'pixelated';
|
|
315
|
+
isolation?: 'auto' | 'isolate';
|
|
316
|
+
justifyContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly';
|
|
317
|
+
justifyItems?: 'normal' | 'stretch' | 'center' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'left' | 'right';
|
|
318
|
+
justifySelf?: 'auto' | 'normal' | 'stretch' | 'center' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'left' | 'right';
|
|
319
|
+
left?: string;
|
|
320
|
+
letterSpacing?: 'normal';
|
|
321
|
+
lineHeight?: 'normal' | number;
|
|
322
|
+
listStyle?: string;
|
|
323
|
+
listStyleImage?: string;
|
|
324
|
+
listStylePosition?: 'inside' | 'outside';
|
|
325
|
+
listStyleType?: 'disc' | 'circle' | 'square' | 'decimal' | 'georgian' | 'trad-chinese-informal' | 'none';
|
|
326
|
+
margin?: string;
|
|
327
|
+
marginBottom?: string;
|
|
328
|
+
marginLeft?: string;
|
|
329
|
+
marginRight?: string;
|
|
330
|
+
marginTop?: string;
|
|
331
|
+
mask?: string;
|
|
332
|
+
maskClip?: string;
|
|
333
|
+
maskComposite?: string;
|
|
334
|
+
maskImage?: string;
|
|
335
|
+
maskMode?: string;
|
|
336
|
+
maskOrigin?: string;
|
|
337
|
+
maskPosition?: string;
|
|
338
|
+
maskRepeat?: string;
|
|
339
|
+
maskSize?: string;
|
|
340
|
+
maskType?: string;
|
|
341
|
+
maxHeight?: string;
|
|
342
|
+
maxWidth?: string;
|
|
343
|
+
minHeight?: string;
|
|
344
|
+
minWidth?: string;
|
|
345
|
+
mixBlendMode?: 'normal' | 'multiply' | 'screen' | 'overlay' | 'darken' | 'lighten' | 'color-dodge' | 'color-burn' | 'hard-light' | 'soft-light' | 'difference' | 'exclusion' | 'hue' | 'saturation' | 'color' | 'luminosity';
|
|
346
|
+
objectFit?: 'fill' | 'contain' | 'cover' | 'none' | 'scale-down';
|
|
347
|
+
objectPosition?: string;
|
|
348
|
+
opacity?: number;
|
|
349
|
+
order?: number;
|
|
350
|
+
outline?: string;
|
|
351
|
+
outlineColor?: string;
|
|
352
|
+
outlineOffset?: string;
|
|
353
|
+
outlineStyle?: 'none' | 'hidden' | 'dotted' | 'dashed' | 'solid' | 'double' | 'groove' | 'ridge' | 'inset' | 'outset';
|
|
354
|
+
outlineWidth?: string;
|
|
355
|
+
overflow?: 'visible' | 'hidden' | 'scroll' | 'auto';
|
|
356
|
+
overflowWrap?: 'normal' | 'break-word' | 'anywhere';
|
|
357
|
+
overflowX?: 'visible' | 'hidden' | 'scroll' | 'auto';
|
|
358
|
+
overflowY?: 'visible' | 'hidden' | 'scroll' | 'auto';
|
|
359
|
+
overscrollBehavior?: 'auto' | 'contain' | 'none';
|
|
360
|
+
overscrollBehaviorX?: 'auto' | 'contain' | 'none';
|
|
361
|
+
overscrollBehaviorY?: 'auto' | 'contain' | 'none';
|
|
362
|
+
padding?: string;
|
|
363
|
+
paddingBottom?: string;
|
|
364
|
+
paddingLeft?: string;
|
|
365
|
+
paddingRight?: string;
|
|
366
|
+
paddingTop?: string;
|
|
367
|
+
pageBreakAfter?: 'auto' | 'always' | 'avoid' | 'left' | 'right';
|
|
368
|
+
pageBreakBefore?: 'auto' | 'always' | 'avoid' | 'left' | 'right';
|
|
369
|
+
pageBreakInside?: 'auto' | 'avoid';
|
|
370
|
+
paintOrder?: string;
|
|
371
|
+
perspective?: string;
|
|
372
|
+
perspectiveOrigin?: string;
|
|
373
|
+
placeContent?: string;
|
|
374
|
+
placeItems?: string;
|
|
375
|
+
placeSelf?: string;
|
|
376
|
+
pointerEvents?: 'auto' | 'none';
|
|
377
|
+
position?: 'static' | 'relative' | 'absolute' | 'fixed' | 'sticky';
|
|
378
|
+
quotes?: string;
|
|
379
|
+
resize?: 'none' | 'both' | 'horizontal' | 'vertical' | 'block' | 'inline';
|
|
380
|
+
right?: string;
|
|
381
|
+
rotate?: string;
|
|
382
|
+
rowGap?: string;
|
|
383
|
+
scale?: string;
|
|
384
|
+
scrollBehavior?: 'auto' | 'smooth';
|
|
385
|
+
shapeRendering?: 'auto' | 'optimizeSpeed' | 'crispEdges' | 'geometricPrecision';
|
|
386
|
+
stopColor?: string;
|
|
387
|
+
stopOpacity?: string;
|
|
388
|
+
stroke?: string;
|
|
389
|
+
strokeDasharray?: string;
|
|
390
|
+
strokeDashoffset?: string;
|
|
391
|
+
strokeLinecap?: 'butt' | 'round' | 'square';
|
|
392
|
+
strokeLinejoin?: 'miter' | 'round' | 'bevel';
|
|
393
|
+
strokeMiterlimit?: string;
|
|
394
|
+
strokeOpacity?: string;
|
|
395
|
+
strokeWidth?: string;
|
|
396
|
+
tabSize?: string;
|
|
397
|
+
tableLayout?: 'auto' | 'fixed';
|
|
398
|
+
textAlign?: 'left' | 'right' | 'center' | 'justify' | 'start' | 'end';
|
|
399
|
+
textAlignLast?: 'auto' | 'left' | 'right' | 'center' | 'justify' | 'start' | 'end';
|
|
400
|
+
textAnchor?: 'start' | 'middle' | 'end';
|
|
401
|
+
textCombineUpright?: 'none' | 'all';
|
|
402
|
+
textDecoration?: string;
|
|
403
|
+
textDecorationColor?: string;
|
|
404
|
+
textDecorationLine?: 'none' | 'underline' | 'overline' | 'line-through' | 'grammar-error' | 'spelling-error';
|
|
405
|
+
textDecorationStyle?: 'solid' | 'double' | 'dotted' | 'dashed' | 'wavy';
|
|
406
|
+
textDecorationThickness?: string;
|
|
407
|
+
textDecorationSkipInk?: 'auto' | 'none';
|
|
408
|
+
textEmphasis?: string;
|
|
409
|
+
textIndent?: string;
|
|
410
|
+
textJustify?: 'auto' | 'inter-word' | 'inter-character' | 'none';
|
|
411
|
+
textOrientation?: 'mixed' | 'upright' | 'sideways';
|
|
412
|
+
textOverflow?: 'clip' | 'ellipsis';
|
|
413
|
+
textRendering?: 'auto' | 'optimizeSpeed' | 'optimizeLegibility' | 'geometricPrecision';
|
|
414
|
+
textShadow?: string;
|
|
415
|
+
textTransform?: 'none' | 'capitalize' | 'uppercase' | 'lowercase';
|
|
416
|
+
textUnderlineOffset?: string;
|
|
417
|
+
textUnderlinePosition?: 'auto' | 'under' | 'left' | 'right';
|
|
418
|
+
top?: string;
|
|
419
|
+
touchAction?: 'auto' | 'none' | 'pan-x' | 'pan-y' | 'manipulation';
|
|
420
|
+
transform?: string;
|
|
421
|
+
transformBox?: 'border-box' | 'fill-box' | 'view-box';
|
|
422
|
+
transformOrigin?: string;
|
|
423
|
+
transformStyle?: 'flat' | 'preserve-3d';
|
|
424
|
+
transition?: string;
|
|
425
|
+
transitionDelay?: string;
|
|
426
|
+
transitionDuration?: string;
|
|
427
|
+
transitionProperty?: string;
|
|
428
|
+
transitionTimingFunction?: 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'linear' | 'step-start' | 'step-end';
|
|
429
|
+
translate?: string;
|
|
430
|
+
unicodeBidi?: 'normal' | 'embed' | 'isolate' | 'bidi-override' | 'isolate-override' | 'plaintext';
|
|
431
|
+
userSelect?: 'auto' | 'none' | 'text' | 'contain' | 'all';
|
|
432
|
+
verticalAlign?: 'baseline' | 'sub' | 'super' | 'text-top' | 'text-bottom' | 'middle' | 'top' | 'bottom';
|
|
433
|
+
visibility?: 'visible' | 'hidden' | 'collapse';
|
|
434
|
+
whiteSpace?: 'normal' | 'nowrap' | 'pre' | 'pre-wrap' | 'pre-line' | 'break-spaces';
|
|
435
|
+
width?: string;
|
|
436
|
+
willChange?: string;
|
|
437
|
+
wordBreak?: 'normal' | 'break-all' | 'keep-all' | 'break-word';
|
|
438
|
+
wordSpacing?: string;
|
|
439
|
+
wordWrap?: 'normal' | 'break-word';
|
|
440
|
+
writingMode?: 'horizontal-tb' | 'vertical-rl' | 'vertical-lr';
|
|
441
|
+
zIndex?: 'auto' | number;
|
|
442
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { $CSSRule } from "#structure/$CSSRule";
|
|
2
|
+
|
|
3
|
+
export class $CSSKeyframesRule extends $CSSRule {
|
|
4
|
+
name: string;
|
|
5
|
+
constructor(name: string) {
|
|
6
|
+
super();
|
|
7
|
+
this.name = name;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
toString(): string {
|
|
11
|
+
return this.name;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get css() {
|
|
15
|
+
return `@keyframes ${this.name} { ${Array.from(this.rules).map(rule => rule.css).join(' ')} }`
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { _Array_from, _instanceof } from "amateras/lib/native";
|
|
2
|
+
import { $CSSRule } from "#structure/$CSSRule";
|
|
3
|
+
import { $CSSStyleRule } from "./$CSSStyleRule";
|
|
4
|
+
|
|
5
|
+
export class $CSSMediaRule extends $CSSRule {
|
|
6
|
+
condition: string;
|
|
7
|
+
constructor(condition: string) {
|
|
8
|
+
super();
|
|
9
|
+
this.condition = 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(' ')} }`
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { _instanceof } from "amateras/lib/native";
|
|
2
|
+
import { $CSSMediaRule } from "#structure/$CSSMediaRule";
|
|
3
|
+
|
|
4
|
+
export abstract class $CSSRule {
|
|
5
|
+
rules = new Set<$CSSRule>();
|
|
6
|
+
ownerRule: $CSSRule | null = null;
|
|
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;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
addRule(rule: $CSSRule) {
|
|
21
|
+
this.rules.add(rule);
|
|
22
|
+
rule.ownerRule = this;
|
|
23
|
+
return this;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { $CSSDeclaration } from "#structure/$CSSDeclaration";
|
|
2
|
+
import { $CSSRule } from "#structure/$CSSRule";
|
|
3
|
+
import { _Array_from, _instanceof } from "amateras/lib/native";
|
|
4
|
+
|
|
5
|
+
export class $CSSStyleRule extends $CSSRule {
|
|
6
|
+
context: string[] = [];
|
|
7
|
+
declarations = new Map<string, $CSSDeclaration>();
|
|
8
|
+
className: string = '';
|
|
9
|
+
constructor(context: string[] = []) {
|
|
10
|
+
super();
|
|
11
|
+
this.context = context;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get css(): string {
|
|
15
|
+
return `${this.selector} { ${_Array_from(this.declarations).map(([_, dec]) => `${dec}`).join(' ')} }`
|
|
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(', ')
|
|
22
|
+
}
|
|
23
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "amateras",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Amateras is a DOM Utility library.",
|
|
5
5
|
"module": "index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -31,7 +31,12 @@
|
|
|
31
31
|
"./lib/*": "./src/lib/*.ts",
|
|
32
32
|
"./structure/*": "./src/structure/*.ts",
|
|
33
33
|
"./html": "./ext/html/html.ts",
|
|
34
|
-
"./css": "./ext/css/
|
|
35
|
-
|
|
34
|
+
"./css": "./ext/css/src/index.ts"
|
|
35
|
+
},
|
|
36
|
+
"workspaces": [
|
|
37
|
+
"./ext/*"
|
|
38
|
+
],
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"@amateras/css": "./ext/css"
|
|
36
41
|
}
|
|
37
|
-
}
|
|
42
|
+
}
|
package/src/core.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Signal } from "#structure/Signal";
|
|
|
3
3
|
import { $Element } from "#node/$Element";
|
|
4
4
|
import { $Node, type $NodeContentTypes } from '#node/$Node';
|
|
5
5
|
import '#node/node';
|
|
6
|
+
import { _instanceof, _Object_defineProperty, _Object_entries, isFunction, isObject, isString, isUndefined } from '#lib/native';
|
|
6
7
|
|
|
7
8
|
const tagNameMap: {[key: string]: Constructor<$Node>} = {}
|
|
8
9
|
export function $<K extends (...args: any[]) => $Node>(fn: K, ...args: Parameters<K>): ReturnType<K>;
|
|
@@ -14,16 +15,16 @@ export function $<K extends Element>(element: K): $Element<K>;
|
|
|
14
15
|
export function $<K extends keyof HTMLElementTagNameMap>(tagname: K): $Element<HTMLElementTagNameMap[K]>
|
|
15
16
|
export function $(tagname: string): $Element<HTMLElement>
|
|
16
17
|
export function $(resolver: string | HTMLElement | $Node | Function | TemplateStringsArray, ...args: any[]) {
|
|
17
|
-
if (resolver
|
|
18
|
-
if (
|
|
19
|
-
if (
|
|
18
|
+
if (_instanceof(resolver, $Node)) return resolver;
|
|
19
|
+
if (isString(resolver) && tagNameMap[resolver]) return new tagNameMap[resolver]();
|
|
20
|
+
if (isFunction(resolver))
|
|
20
21
|
if (resolver.prototype?.constructor) return resolver.prototype.constructor(...args);
|
|
21
22
|
else return resolver(...args);
|
|
22
23
|
if (resolver instanceof Array) {
|
|
23
24
|
const iterate = args.values();
|
|
24
25
|
return resolver.map(str => [str ?? undefined, iterate.next().value]).flat().filter(item => item);
|
|
25
26
|
}
|
|
26
|
-
if (resolver
|
|
27
|
+
if (_instanceof(resolver, Node) && _instanceof(resolver.$, $Node)) return resolver.$;
|
|
27
28
|
return new $Element(resolver);
|
|
28
29
|
}
|
|
29
30
|
|
|
@@ -35,15 +36,15 @@ export namespace $ {
|
|
|
35
36
|
const signal = new Signal<T>(value);
|
|
36
37
|
const signalFn = function (newValue?: T) {
|
|
37
38
|
if (!arguments.length) return signal.value();
|
|
38
|
-
if (newValue
|
|
39
|
+
if (!isUndefined(newValue)) signal.value(newValue);
|
|
39
40
|
return signalFn;
|
|
40
41
|
}
|
|
41
|
-
|
|
42
|
-
if (value
|
|
43
|
-
for (const [key, val] of
|
|
42
|
+
_Object_defineProperty(signalFn, 'signal', { value: signal });
|
|
43
|
+
if (isObject(value)) {
|
|
44
|
+
for (const [key, val] of _Object_entries(value)) {
|
|
44
45
|
const val$ = $.signal(val);
|
|
45
46
|
val$.signal.subscribe(newValue => { value[key as keyof typeof value] = newValue; signal.emit() });
|
|
46
|
-
|
|
47
|
+
_Object_defineProperty(signalFn, `${key}$`, {value: val$});
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
return signalFn as unknown as SignalFunction<T>
|
|
@@ -67,7 +68,7 @@ export namespace $ {
|
|
|
67
68
|
subscribed = true;
|
|
68
69
|
return result;
|
|
69
70
|
}
|
|
70
|
-
|
|
71
|
+
_Object_defineProperty(computeFn, 'signal', { value: signalFn.signal });
|
|
71
72
|
return computeFn as ComputeFunction<T>
|
|
72
73
|
}
|
|
73
74
|
|
|
@@ -77,7 +78,11 @@ export namespace $ {
|
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
export function orArrayResolver<T>(item: OrArray<T>): T[] {
|
|
80
|
-
return item
|
|
81
|
+
return _instanceof(item, Array) ? item : [item];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function span(content: string) {
|
|
85
|
+
return $('span').content(content);
|
|
81
86
|
}
|
|
82
87
|
}
|
|
83
88
|
export type $ = typeof $;
|
package/src/lib/assign.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Signal } from "../structure/Signal";
|
|
2
|
+
import { _instanceof, _Object_defineProperty, isUndefined } from "./native";
|
|
2
3
|
|
|
3
4
|
export function assign(target: any, {set, get, fn}: {
|
|
4
5
|
set?: string[],
|
|
@@ -10,7 +11,7 @@ export function assign(target: any, {set, get, fn}: {
|
|
|
10
11
|
}
|
|
11
12
|
const list = [...filterAndMap('get', get), ...filterAndMap('set', set), ...filterAndMap('fn', fn)] as [string, string][];
|
|
12
13
|
for (const [type, prop] of list) {
|
|
13
|
-
|
|
14
|
+
_Object_defineProperty(target.prototype, prop, {
|
|
14
15
|
...(type === 'get' ? {
|
|
15
16
|
get() { return this.node[prop as any] }
|
|
16
17
|
} : {
|
|
@@ -19,8 +20,8 @@ export function assign(target: any, {set, get, fn}: {
|
|
|
19
20
|
// set
|
|
20
21
|
value: function (this, args: any) {
|
|
21
22
|
if (!arguments.length) return this.node[prop];
|
|
22
|
-
const set = (value: any) => value
|
|
23
|
-
if (args
|
|
23
|
+
const set = (value: any) => !isUndefined(value) && (this.node[prop] = value);
|
|
24
|
+
if (_instanceof(args, Signal)) args = args.subscribe(set).value();
|
|
24
25
|
set(args)
|
|
25
26
|
return this;
|
|
26
27
|
}
|
package/src/lib/assignHelper.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { $Node } from "#node/$Node";
|
|
2
2
|
import { assign } from "./assign";
|
|
3
|
+
import { _Object_entries, _Object_getOwnPropertyDescriptors } from "./native";
|
|
3
4
|
|
|
4
5
|
export function assignHelper(targets: [object: Constructor<Node>, target: Constructor<$Node>, tagname?: string][]) {
|
|
5
6
|
for (const [object, target, tagname] of targets) {
|
|
6
7
|
const {set, get, fn} = { set: [] as string[], get: [] as string[], fn: [] as string[] }
|
|
7
8
|
// assign native object properties to target
|
|
8
|
-
for (const [prop, value] of
|
|
9
|
+
for (const [prop, value] of _Object_entries(_Object_getOwnPropertyDescriptors(object.prototype))) {
|
|
9
10
|
if (prop in target.prototype) continue;
|
|
10
11
|
if (value.get && !value.set) get.push(prop);
|
|
11
12
|
else if (value.value) fn.push(prop);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Object
|
|
2
|
+
export const _Object_fromEntries = Object.fromEntries;
|
|
3
|
+
export const _Object_entries = Object.entries;
|
|
4
|
+
export const _Object_assign = Object.assign;
|
|
5
|
+
export const _Object_values = Object.values;
|
|
6
|
+
export const _Object_defineProperty = Object.defineProperty;
|
|
7
|
+
export const _Object_getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors;
|
|
8
|
+
// Array
|
|
9
|
+
export const _Array_from = Array.from;
|
|
10
|
+
// typeof
|
|
11
|
+
export function _typeof(target: any, type: 'string' | 'number' | 'object' | 'boolean' | 'function' | 'bigint' | 'symbol' | 'undefined') {
|
|
12
|
+
return typeof target === type;
|
|
13
|
+
}
|
|
14
|
+
export function isString(target: any): target is string {
|
|
15
|
+
return _typeof(target, 'string');
|
|
16
|
+
}
|
|
17
|
+
export function isNumber(target: any): target is number {
|
|
18
|
+
return _typeof(target, 'number')
|
|
19
|
+
}
|
|
20
|
+
export function isObject(target: any): target is object {
|
|
21
|
+
return _typeof(target, 'object')
|
|
22
|
+
}
|
|
23
|
+
export function isFunction(target: any): target is Function {
|
|
24
|
+
return _typeof(target, 'function')
|
|
25
|
+
}
|
|
26
|
+
export function isUndefined(target: any): target is undefined {
|
|
27
|
+
return _typeof(target, 'undefined')
|
|
28
|
+
}
|
|
29
|
+
export function isNull(target: any): target is null {
|
|
30
|
+
return target === null;
|
|
31
|
+
}
|
|
32
|
+
export function _instanceof<T>(target: any, instance: abstract new (...args: any[]) => T): target is T {
|
|
33
|
+
return target instanceof instance;
|
|
34
|
+
}
|
package/src/lib/randomId.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { _Array_from } from "./native";
|
|
2
|
+
|
|
1
3
|
const LOWER = 'abcdefghijklmnopqrstuvwxyz';
|
|
2
4
|
const UPPER = LOWER.toUpperCase();
|
|
3
|
-
export function randomId(options?: {length?: number,
|
|
4
|
-
options = {length: 5,
|
|
5
|
-
const char = options.
|
|
6
|
-
return
|
|
5
|
+
export function randomId(options?: {length?: number, lettercase?: 'any' | 'lower' | 'upper'}): string {
|
|
6
|
+
options = {length: 5, lettercase: 'any', ...options};
|
|
7
|
+
const char = options.lettercase === 'any' ? LOWER + UPPER : options.lettercase === 'lower' ? LOWER : UPPER;
|
|
8
|
+
return _Array_from({length: options.length as number}, (_, i) => {
|
|
7
9
|
const rand = Math.round(Math.random() * char.length); return char[rand]
|
|
8
10
|
}).join('');
|
|
9
11
|
}
|
package/src/node/$Element.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
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
4
|
|
|
4
5
|
export class $Element<Ele extends Element = Element> extends $Node {
|
|
5
6
|
listeners = new Map<Function, (event: Event) => void>;
|
|
6
7
|
declare node: Ele
|
|
7
8
|
constructor(resolver: Ele | string) {
|
|
8
|
-
super(resolver
|
|
9
|
+
super(_instanceof(resolver, Element) ? resolver : document.createElement(resolver) as unknown as Ele)
|
|
9
10
|
//@ts-expect-error
|
|
10
11
|
this.node.$ = this;
|
|
11
12
|
}
|
|
@@ -13,10 +14,10 @@ export class $Element<Ele extends Element = Element> extends $Node {
|
|
|
13
14
|
attr(): {[key: string]: string};
|
|
14
15
|
attr(obj: {[key: string]: string | number | boolean | Signal<any>}): this;
|
|
15
16
|
attr(obj?: {[key: string]: string | number | boolean | Signal<any>}) {
|
|
16
|
-
if (!arguments.length) return
|
|
17
|
-
if (obj) for (let [key, value] of
|
|
18
|
-
const set = (value: any) => value
|
|
19
|
-
if (value
|
|
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}`)
|
|
20
|
+
if (_instanceof(value, Signal)) value = value.subscribe(set).value();
|
|
20
21
|
set(value);
|
|
21
22
|
}
|
|
22
23
|
return this;
|
package/src/node/$Node.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { _Array_from, _instanceof, isFunction, isNull, isObject, isUndefined } from "#lib/native";
|
|
1
2
|
import { Signal } from "#structure/Signal";
|
|
2
3
|
|
|
3
4
|
export class $Node {
|
|
@@ -9,14 +10,14 @@ export class $Node {
|
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
content(children: $NodeContentResolver<this>) {
|
|
12
|
-
this.node.childNodes.forEach(node => node.remove());
|
|
13
|
+
_Array_from(this.node.childNodes).forEach(node => node.remove());
|
|
13
14
|
return this.insert(children);
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
insert(resolver: $NodeContentResolver<this>, position = -1) {
|
|
17
|
-
if (resolver
|
|
18
|
+
if (isFunction(resolver)) {
|
|
18
19
|
const content = resolver(this);
|
|
19
|
-
if (content
|
|
20
|
+
if (_instanceof(content, Promise)) content.then(content => $Node.insertChild(this.node, content, position))
|
|
20
21
|
else $Node.insertChild(this.node, content, position);
|
|
21
22
|
} else $Node.insertChild(this.node, resolver, position);
|
|
22
23
|
return this;
|
|
@@ -36,7 +37,7 @@ export class $Node {
|
|
|
36
37
|
static insertChild(node: Node, children: OrArray<OrPromise<$NodeContentTypes>>, position = -1) {
|
|
37
38
|
children = $.orArrayResolver(children);
|
|
38
39
|
// get child node at position
|
|
39
|
-
const positionChild =
|
|
40
|
+
const positionChild = _Array_from(node.childNodes).filter(node => node.nodeType !== node.TEXT_NODE).at(position);
|
|
40
41
|
// insert node helper function for depend position
|
|
41
42
|
const append = (child: Node | undefined | null) => {
|
|
42
43
|
if (!child) return;
|
|
@@ -44,7 +45,7 @@ export class $Node {
|
|
|
44
45
|
else node.insertBefore(child, position < 0 ? positionChild.nextSibling : positionChild);
|
|
45
46
|
}
|
|
46
47
|
// process nodes
|
|
47
|
-
for (const child of children)
|
|
48
|
+
for (const child of children) !isUndefined(child) && append($Node.processContent(child))
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
static processContent(content: $NodeContentTypes): Node;
|
|
@@ -53,19 +54,19 @@ export class $Node {
|
|
|
53
54
|
static processContent(content: OrPromise<$NodeContentTypes>): Node;
|
|
54
55
|
static processContent(content: OrPromise<$NodeContentTypes | undefined | null>): Node | undefined | null
|
|
55
56
|
static processContent(content: OrPromise<$NodeContentTypes | undefined | null>) {
|
|
56
|
-
if (content
|
|
57
|
-
if (content
|
|
57
|
+
if (isUndefined(content)) return;
|
|
58
|
+
if (isNull(content)) return content;
|
|
58
59
|
// is $Element
|
|
59
|
-
if (content
|
|
60
|
+
if (_instanceof(content, $Node)) return content.node;
|
|
60
61
|
// is Promise
|
|
61
|
-
if (content
|
|
62
|
+
if (_instanceof(content, Promise)) {
|
|
62
63
|
const async = $('async').await(content, ($async, $child) => $async.replace($child));
|
|
63
64
|
return async.node;
|
|
64
65
|
}
|
|
65
66
|
// is SignalFunction
|
|
66
|
-
if (content
|
|
67
|
+
if (isFunction(content) && _instanceof((content as $.SignalFunction<any>).signal ,Signal)) {
|
|
67
68
|
const text = new Text();
|
|
68
|
-
const set = (value: any) => text.textContent = value
|
|
69
|
+
const set = (value: any) => text.textContent = isObject(value) ? JSON.stringify(value) : value;
|
|
69
70
|
(content as $.SignalFunction<any>).signal.subscribe(set);
|
|
70
71
|
set((content as $.SignalFunction<any>)());
|
|
71
72
|
return text;
|
package/src/structure/Signal.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { isUndefined } from "#lib/native";
|
|
2
|
+
|
|
1
3
|
export class Signal<T> {
|
|
2
4
|
#value: T;
|
|
3
5
|
subscribers = new Set<(value: T) => void>();
|
|
@@ -15,7 +17,7 @@ export class Signal<T> {
|
|
|
15
17
|
return this.#value;
|
|
16
18
|
}
|
|
17
19
|
if (resolver instanceof Function) this.value(resolver(this.#value));
|
|
18
|
-
else if (resolver
|
|
20
|
+
else if (!isUndefined(resolver)) {
|
|
19
21
|
this.#value = resolver;
|
|
20
22
|
this.emit();
|
|
21
23
|
}
|
package/ext/css/$CSSMediaRule.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { $CSSRule } from "#css/$CSSRule";
|
|
2
|
-
|
|
3
|
-
export class $CSSMediaRule extends $CSSRule {
|
|
4
|
-
condition: string;
|
|
5
|
-
constructor(condition: string) {
|
|
6
|
-
super();
|
|
7
|
-
this.condition = condition;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
toString() {
|
|
11
|
-
return `@media ${this.condition} { ${[...this.rules.values()].map(rule => rule.toString()).join('\n')} }`
|
|
12
|
-
}
|
|
13
|
-
}
|
package/ext/css/$CSSRule.ts
DELETED
package/ext/css/$CSSStyleRule.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { $CSSDeclaration } from "#css/$CSSDeclaration";
|
|
2
|
-
import { $CSSRule } from "#css/$CSSRule";
|
|
3
|
-
|
|
4
|
-
export class $CSSStyleRule extends $CSSRule {
|
|
5
|
-
context: string[] = [];
|
|
6
|
-
declarations = new Map<string, $CSSDeclaration>();
|
|
7
|
-
className: string = '';
|
|
8
|
-
constructor(context: string[] = []) {
|
|
9
|
-
super();
|
|
10
|
-
this.context = context;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
toString() {
|
|
14
|
-
return `${this.selector} { ${[...this.declarations.values()].map(dec => `${dec.property}: ${dec.value};`).join('\n')} }`
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
get selector() {
|
|
18
|
-
return this.context.join(' ');
|
|
19
|
-
}
|
|
20
|
-
}
|
package/ext/css/css.ts
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { $CSSDeclaration } from "#css/$CSSDeclaration";
|
|
2
|
-
import { $CSSMediaRule } from "#css/$CSSMediaRule";
|
|
3
|
-
import { $CSSRule } from "#css/$CSSRule";
|
|
4
|
-
import { $CSSStyleRule } from "#css/$CSSStyleRule";
|
|
5
|
-
import { randomId } from "#lib/randomId";
|
|
6
|
-
import { $Element } from "#node/$Element";
|
|
7
|
-
|
|
8
|
-
declare module '#core' {
|
|
9
|
-
export namespace $ {
|
|
10
|
-
export function css(options: $CSSOptions): $CSSStyleRule
|
|
11
|
-
export function CSS(options: $CSSSelector | $CSSMediaSelector): void
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
declare module '#node/$Element' {
|
|
16
|
-
export interface $Element {
|
|
17
|
-
css(...options: $CSSOptions[]): this;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
Object.defineProperty($, 'css', {
|
|
22
|
-
value: function (options: $CSSOptions) {
|
|
23
|
-
if (options instanceof $CSSRule) return options;
|
|
24
|
-
const className = $CSS.generateClassName();
|
|
25
|
-
const rule = $CSS.createStyleRule(options, [className]);
|
|
26
|
-
rule.className = className;
|
|
27
|
-
return $CSS.insertRule( rule );
|
|
28
|
-
}
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
Object.defineProperty($, 'CSS', {
|
|
32
|
-
value: function (options: $CSSSelector | $CSSMediaRule) {
|
|
33
|
-
return Object.entries(options).map(([selector, declarations]) => {
|
|
34
|
-
return $CSS.insertRule( $CSS.createRule(selector, declarations) );
|
|
35
|
-
})
|
|
36
|
-
}
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
Object.defineProperty($Element.prototype, 'css', {
|
|
40
|
-
value: function (this: $Element, ...options: $CSSOptions[]) {
|
|
41
|
-
options.forEach(options => {
|
|
42
|
-
const rule = $.css(options);
|
|
43
|
-
this.addClass(rule.context[0]?.slice(1) as string);
|
|
44
|
-
})
|
|
45
|
-
return this;
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
export namespace $CSS {
|
|
50
|
-
export const stylesheet = new CSSStyleSheet();
|
|
51
|
-
const generatedIds = new Set<string>();
|
|
52
|
-
document.adoptedStyleSheets.push($CSS.stylesheet);
|
|
53
|
-
export function generateClassName(): string {
|
|
54
|
-
const id = randomId();
|
|
55
|
-
if (generatedIds.has(id)) return generateClassName();
|
|
56
|
-
generatedIds.add(id);
|
|
57
|
-
return `.${id}`;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function createStyleRule<T extends $CSSRule>(options: T, context?: string[]): T;
|
|
61
|
-
export function createStyleRule<T extends $CSSOptions>(options: T, context?: string[]): $CSSStyleRule;
|
|
62
|
-
export function createStyleRule<T extends $CSSOptions>(options: T, context: string[] = []) {
|
|
63
|
-
if (options instanceof $CSSRule) return options;
|
|
64
|
-
const rule = new $CSSStyleRule(context);
|
|
65
|
-
for (const [key, value] of Object.entries(options)) {
|
|
66
|
-
if (value === undefined) continue;
|
|
67
|
-
if (value instanceof Object) rule.rules.add( createRule(key, value, context) )
|
|
68
|
-
else {
|
|
69
|
-
const declaration = new $CSSDeclaration(key, value);
|
|
70
|
-
rule.declarations.set(declaration.key, declaration);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return rule;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function createRule(selector: string, options: $CSSOptions, context: string[] = []) {
|
|
77
|
-
if (selector.startsWith('@media')) return createMediaRule(selector.replace('@media ', ''), options, context);
|
|
78
|
-
else return createStyleRule(options, [...context, selector],);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export function createMediaRule(key: string, options: $CSSOptions, context: string[] = []) {
|
|
82
|
-
const rule = new $CSSMediaRule(key);
|
|
83
|
-
rule.rules.add(createStyleRule(options, context));
|
|
84
|
-
return rule;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export function insertRule(rule: $CSSRule) {
|
|
88
|
-
if (rule instanceof $CSSStyleRule && !CSS.supports(`selector(${rule.selector})`)) return rule;
|
|
89
|
-
$CSS.stylesheet.insertRule(rule.toString(), $CSS.stylesheet.cssRules.length);
|
|
90
|
-
if (rule instanceof $CSSMediaRule) return;
|
|
91
|
-
rule.rules.forEach(rule => insertRule(rule))
|
|
92
|
-
return rule;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
type $CSSOptions = $CSSDeclarations | $CSSSelector | $CSSRule | $CSSMediaSelector;
|
|
97
|
-
type $CSSDeclarations = { [key in keyof CSSStyleDeclaration]?: string | number }
|
|
98
|
-
type $CSSSelector = { [key: string & {}]: $CSSOptions }
|
|
99
|
-
type $CSSMediaSelector = { [key: `@${string}`]: $CSSOptions }
|
|
100
|
-
|
|
101
|
-
console.debug(document.adoptedStyleSheets[0])
|