@xtia/jel 0.2.2 → 0.3.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 +85 -1
- package/index.d.ts +26 -8
- package/index.js +76 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,9 +5,12 @@ Jel is a thin layer over the DOM to simplify element structure creation, manipul
|
|
|
5
5
|
|
|
6
6
|
See [demo/index.ts](https://github.com/tiadrop/jel-ts/blob/main/demo/index.ts) for example operation. Compare with [resulting page](https://aleta.codes/jel-ts-demo/).
|
|
7
7
|
|
|
8
|
-
## `$`
|
|
8
|
+
## `$` Basic Use:
|
|
9
9
|
|
|
10
10
|
`$.[tagname](details)` produces an element of `<tagname>`. `details` can be content of various types or a descriptor object.
|
|
11
|
+
```
|
|
12
|
+
$ npm i @xtia/jel
|
|
13
|
+
```
|
|
11
14
|
|
|
12
15
|
```ts
|
|
13
16
|
import { $ } from "@xtia/jel";
|
|
@@ -44,4 +47,85 @@ body.append([
|
|
|
44
47
|
)
|
|
45
48
|
])
|
|
46
49
|
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## `DOMContent`
|
|
53
|
+
|
|
54
|
+
Content can be string, Text, HTMLElement, JelEntity or arbitrarily nested array of content. Typing as DOMContent where possible enables flexibility.
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
function showDialogue(content: DOMContent) => {
|
|
58
|
+
const element = $.div({
|
|
59
|
+
classes: "dialogue",
|
|
60
|
+
content: [
|
|
61
|
+
content,
|
|
62
|
+
$.div({
|
|
63
|
+
classes: "buttons",
|
|
64
|
+
// content: [...]
|
|
65
|
+
})
|
|
66
|
+
]
|
|
67
|
+
});
|
|
68
|
+
// ...
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
interface Job {
|
|
72
|
+
name: string;
|
|
73
|
+
completionMessage: DOMContent;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
showDialogue("Hello, world");
|
|
77
|
+
showDialogue(["Hello, ", $.i("world")]);
|
|
78
|
+
showDialogue([
|
|
79
|
+
$.h2(`${job.name} Complete`),
|
|
80
|
+
$.p(job.completionMessage),
|
|
81
|
+
]);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## `ElementClassDescriptor`
|
|
85
|
+
|
|
86
|
+
Element classes can be specified as string, `{ [className]: boolean }` and arbitrarily nested array thereof.
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
function renderFancyButton(
|
|
90
|
+
caption: DOMContent,
|
|
91
|
+
onClick: () => void,
|
|
92
|
+
classes: ElementClassDescriptor = []
|
|
93
|
+
) {
|
|
94
|
+
return $.button({
|
|
95
|
+
content: caption,
|
|
96
|
+
classes: ["fancy-button", classes],
|
|
97
|
+
// ...
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function showDialogue(content: DOMContent, danger: boolean = false) {
|
|
102
|
+
const element = $.div({
|
|
103
|
+
// ...
|
|
104
|
+
classes: "dialogue",
|
|
105
|
+
content: [
|
|
106
|
+
content,
|
|
107
|
+
renderFancyButton("OK", close, ["ok-button", { danger }]),
|
|
108
|
+
]
|
|
109
|
+
});
|
|
110
|
+
// ...
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Jel-Wrapped Elements
|
|
115
|
+
|
|
116
|
+
Jel wraps its elements in an interface for common operations plus an `append()` method that accepts `DOMContent`.
|
|
117
|
+
|
|
118
|
+
For other operations the element is accessible via `ent.element`:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
const div = $.div();
|
|
122
|
+
div.element.requestFullscreen();
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Shorthand
|
|
126
|
+
|
|
127
|
+
If you need an element with just a class, id and/or content you can use `tag#id.classes` notation, ie `$("div#someId.class1.class2", content?)`.
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
showDialogue(["Hello ", $("span.green", "world")]);
|
|
47
131
|
```
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export type ElementClassDescriptor = string | Record<string, boolean> | ElementClassDescriptor[];
|
|
2
2
|
export type DOMContent = number | null | string | Element | JelEntity<object, any> | Text | DOMContent[];
|
|
3
3
|
export type DomEntity<T extends HTMLElement> = JelEntity<ElementAPI<T>, HTMLElementEventMap>;
|
|
4
4
|
type JelConstructor<Spec, API, EventDataMap> = (spec?: Partial<Spec & CommonOptions<EventDataMap>>) => JelEntity<API, EventDataMap>;
|
|
@@ -11,17 +11,18 @@ type JelEntity<API, EventDataMap> = API & {
|
|
|
11
11
|
on<E extends keyof EventDataMap>(eventId: E, handler: (this: JelEntity<API, EventDataMap>, data: EventDataMap[E]) => void): void;
|
|
12
12
|
readonly [componentDataSymbol]: JelComponentData;
|
|
13
13
|
};
|
|
14
|
-
type
|
|
15
|
-
[key in keyof CSSStyleDeclaration]:
|
|
16
|
-
}
|
|
14
|
+
type StylesDescriptor = Partial<{
|
|
15
|
+
[key in keyof CSSStyleDeclaration]: CSSValue;
|
|
16
|
+
}>;
|
|
17
17
|
interface ElementDescriptor {
|
|
18
|
-
classes?:
|
|
18
|
+
classes?: ElementClassDescriptor;
|
|
19
19
|
content?: DOMContent;
|
|
20
20
|
attribs?: Record<string, string | number | boolean>;
|
|
21
21
|
on?: Partial<{
|
|
22
22
|
[E in keyof HTMLElementEventMap]: (event: HTMLElementEventMap[E]) => void;
|
|
23
23
|
}>;
|
|
24
|
-
style?:
|
|
24
|
+
style?: StylesDescriptor;
|
|
25
|
+
cssVariables?: Record<string, CSSValue>;
|
|
25
26
|
}
|
|
26
27
|
type DomHelper = ((<T extends keyof HTMLElementTagNameMap>(tagName: T, descriptor: ElementDescriptor) => DomEntity<HTMLElementTagNameMap[T]>) & (<T extends keyof HTMLElementTagNameMap>(selector: `${T}#${string}`, content?: DOMContent) => DomEntity<HTMLElementTagNameMap[T]>) & (<T extends keyof HTMLElementTagNameMap>(selector: `${T}.${string}`, content?: DOMContent) => DomEntity<HTMLElementTagNameMap[T]>) & (<T extends keyof HTMLElementTagNameMap>(selector: T, content?: DOMContent) => DomEntity<HTMLElementTagNameMap[T]>) & (<T extends HTMLElement>(element: T) => DomEntity<T>) & {
|
|
27
28
|
[T in keyof HTMLElementTagNameMap]: (descriptor: ElementDescriptor) => DomEntity<HTMLElementTagNameMap[T]>;
|
|
@@ -31,6 +32,7 @@ type DomHelper = ((<T extends keyof HTMLElementTagNameMap>(tagName: T, descripto
|
|
|
31
32
|
type JelComponentData = {
|
|
32
33
|
dom: DOMContent;
|
|
33
34
|
};
|
|
35
|
+
type CSSValue = string | number;
|
|
34
36
|
type ElementAPI<T extends HTMLElement> = {
|
|
35
37
|
readonly element: T;
|
|
36
38
|
content: DOMContent;
|
|
@@ -38,12 +40,28 @@ type ElementAPI<T extends HTMLElement> = {
|
|
|
38
40
|
attribs: {
|
|
39
41
|
[key: string]: string | null;
|
|
40
42
|
};
|
|
41
|
-
style:
|
|
43
|
+
style: StylesDescriptor & ((styles: StylesDescriptor) => void);
|
|
42
44
|
innerHTML: string;
|
|
45
|
+
setCSSVariable(table: Record<string, CSSValue>): void;
|
|
46
|
+
setCSSVariable(variableName: string, value: CSSValue): void;
|
|
43
47
|
qsa(selector: string): DomEntity<any>[];
|
|
44
48
|
append(...content: DOMContent[]): void;
|
|
45
49
|
remove(): void;
|
|
46
|
-
|
|
50
|
+
getRect(): DOMRect;
|
|
51
|
+
focus(): void;
|
|
52
|
+
blur(): void;
|
|
53
|
+
} & (T extends HTMLInputElement ? {
|
|
54
|
+
value: string;
|
|
55
|
+
select(): void;
|
|
56
|
+
} : T extends HTMLCanvasElement ? {
|
|
57
|
+
width: number;
|
|
58
|
+
height: number;
|
|
59
|
+
getContext(contextId: "2d", options?: CanvasRenderingContext2DSettings): CanvasRenderingContext2D | null;
|
|
60
|
+
getContext(contextId: "bitmaprenderer", options?: ImageBitmapRenderingContextSettings): ImageBitmapRenderingContext | null;
|
|
61
|
+
getContext(contextId: "webgl", options?: WebGLContextAttributes): WebGLRenderingContext | null;
|
|
62
|
+
getContext(contextId: "webgl2", options?: WebGLContextAttributes): WebGL2RenderingContext | null;
|
|
63
|
+
getContext(contextId: string, options?: any): RenderingContext | null;
|
|
64
|
+
} : {});
|
|
47
65
|
type OptionalKeys<T> = {
|
|
48
66
|
[K in keyof T]-?: {} extends Pick<T, K> ? K : never;
|
|
49
67
|
}[keyof T];
|
package/index.js
CHANGED
|
@@ -13,6 +13,22 @@ var __assign = (this && this.__assign) || function () {
|
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
14
|
exports.$ = void 0;
|
|
15
15
|
exports.definePart = definePart;
|
|
16
|
+
var elementProxy = {
|
|
17
|
+
get: function (style, prop) {
|
|
18
|
+
return style[prop];
|
|
19
|
+
},
|
|
20
|
+
set: function (style, prop, value) {
|
|
21
|
+
style[prop] = value;
|
|
22
|
+
return true;
|
|
23
|
+
},
|
|
24
|
+
apply: function (style, _, _a) {
|
|
25
|
+
var styles = _a[0];
|
|
26
|
+
Object.entries(styles).forEach(function (_a) {
|
|
27
|
+
var prop = _a[0], val = _a[1];
|
|
28
|
+
return style[prop] = val;
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
};
|
|
16
32
|
function createElement(tag, descriptor) {
|
|
17
33
|
if (descriptor === void 0) { descriptor = {}; }
|
|
18
34
|
if (isContent(descriptor))
|
|
@@ -47,12 +63,13 @@ function createElement(tag, descriptor) {
|
|
|
47
63
|
if (descriptor.style) {
|
|
48
64
|
Object.entries(descriptor.style).forEach(function (_a) {
|
|
49
65
|
var prop = _a[0], val = _a[1];
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
66
|
+
ent.element.style[prop] = val;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
if (descriptor.cssVariables) {
|
|
70
|
+
Object.entries(descriptor.cssVariables).forEach(function (_a) {
|
|
71
|
+
var prop = _a[0], val = _a[1];
|
|
72
|
+
ent.element.style.setProperty("--" + prop, val);
|
|
56
73
|
});
|
|
57
74
|
}
|
|
58
75
|
if (descriptor.on) {
|
|
@@ -112,7 +129,13 @@ var attribsProxy = {
|
|
|
112
129
|
set: function (element, key, value) {
|
|
113
130
|
element.setAttribute(key, value);
|
|
114
131
|
return true;
|
|
115
|
-
}
|
|
132
|
+
},
|
|
133
|
+
has: function (element, key) {
|
|
134
|
+
return element.hasAttribute(key);
|
|
135
|
+
},
|
|
136
|
+
ownKeys: function (element) {
|
|
137
|
+
return element.getAttributeNames();
|
|
138
|
+
},
|
|
116
139
|
};
|
|
117
140
|
var recursiveAppend = function (parent, c) {
|
|
118
141
|
if (c === null)
|
|
@@ -156,10 +179,35 @@ function getWrappedElement(element) {
|
|
|
156
179
|
_a.remove = function () {
|
|
157
180
|
element.remove();
|
|
158
181
|
},
|
|
182
|
+
_a.setCSSVariable = function (variableNameOrTable, value) {
|
|
183
|
+
if (typeof variableNameOrTable == "object") {
|
|
184
|
+
Object.entries(variableNameOrTable).forEach(function (_a) {
|
|
185
|
+
var k = _a[0], v = _a[1];
|
|
186
|
+
element.style.setProperty("--" + k, v);
|
|
187
|
+
});
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
element.style.setProperty("--" + variableNameOrTable, value);
|
|
191
|
+
},
|
|
159
192
|
_a.classes = element.classList,
|
|
160
193
|
_a.qsa = function (selector) {
|
|
161
194
|
return [].slice.call(element.querySelectorAll(selector)).map(function (el) { return getWrappedElement(el); });
|
|
162
195
|
},
|
|
196
|
+
_a.getRect = function () {
|
|
197
|
+
return element.getBoundingClientRect();
|
|
198
|
+
},
|
|
199
|
+
_a.focus = function () {
|
|
200
|
+
element.focus();
|
|
201
|
+
},
|
|
202
|
+
_a.blur = function () {
|
|
203
|
+
element.blur();
|
|
204
|
+
},
|
|
205
|
+
_a.select = function () {
|
|
206
|
+
element.select();
|
|
207
|
+
},
|
|
208
|
+
_a.getContext = function (mode, options) {
|
|
209
|
+
return element.getContext(mode, options);
|
|
210
|
+
},
|
|
163
211
|
Object.defineProperty(_a, "content", {
|
|
164
212
|
get: function () {
|
|
165
213
|
return [].slice.call(element.children).map(function (child) {
|
|
@@ -186,7 +234,27 @@ function getWrappedElement(element) {
|
|
|
186
234
|
enumerable: false,
|
|
187
235
|
configurable: true
|
|
188
236
|
}),
|
|
189
|
-
_a
|
|
237
|
+
Object.defineProperty(_a, "value", {
|
|
238
|
+
get: function () {
|
|
239
|
+
return element.value;
|
|
240
|
+
},
|
|
241
|
+
set: function (v) {
|
|
242
|
+
element.value = v;
|
|
243
|
+
},
|
|
244
|
+
enumerable: false,
|
|
245
|
+
configurable: true
|
|
246
|
+
}),
|
|
247
|
+
Object.defineProperty(_a, "width", {
|
|
248
|
+
get: function () {
|
|
249
|
+
return element.width;
|
|
250
|
+
},
|
|
251
|
+
set: function (v) {
|
|
252
|
+
element.width = v;
|
|
253
|
+
},
|
|
254
|
+
enumerable: false,
|
|
255
|
+
configurable: true
|
|
256
|
+
}),
|
|
257
|
+
_a.style = new Proxy(element.style, elementProxy),
|
|
190
258
|
_a);
|
|
191
259
|
elementWrapCache.set(element, domEntity_1);
|
|
192
260
|
}
|