@xtia/jel 0.2.2 → 0.3.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 +85 -1
- package/index.d.ts +14 -8
- package/index.js +44 -7
- 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: ElementClassDefinition = []
|
|
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 button = $.button();
|
|
122
|
+
const rect = button.element.getBoundingClientRect();
|
|
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,16 @@ 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
|
+
} & (T extends HTMLInputElement ? {
|
|
51
|
+
value: string;
|
|
52
|
+
} : {});
|
|
47
53
|
type OptionalKeys<T> = {
|
|
48
54
|
[K in keyof T]-?: {} extends Pick<T, K> ? K : never;
|
|
49
55
|
}[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) {
|
|
@@ -156,6 +173,16 @@ function getWrappedElement(element) {
|
|
|
156
173
|
_a.remove = function () {
|
|
157
174
|
element.remove();
|
|
158
175
|
},
|
|
176
|
+
_a.setCSSVariable = function (variableNameOrTable, value) {
|
|
177
|
+
if (typeof variableNameOrTable == "object") {
|
|
178
|
+
Object.entries(variableNameOrTable).forEach(function (_a) {
|
|
179
|
+
var k = _a[0], v = _a[1];
|
|
180
|
+
element.style.setProperty("--" + k, v);
|
|
181
|
+
});
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
element.style.setProperty("--" + variableNameOrTable, value);
|
|
185
|
+
},
|
|
159
186
|
_a.classes = element.classList,
|
|
160
187
|
_a.qsa = function (selector) {
|
|
161
188
|
return [].slice.call(element.querySelectorAll(selector)).map(function (el) { return getWrappedElement(el); });
|
|
@@ -186,7 +213,17 @@ function getWrappedElement(element) {
|
|
|
186
213
|
enumerable: false,
|
|
187
214
|
configurable: true
|
|
188
215
|
}),
|
|
189
|
-
_a
|
|
216
|
+
Object.defineProperty(_a, "value", {
|
|
217
|
+
get: function () {
|
|
218
|
+
return element.value;
|
|
219
|
+
},
|
|
220
|
+
set: function (v) {
|
|
221
|
+
element.value = v;
|
|
222
|
+
},
|
|
223
|
+
enumerable: false,
|
|
224
|
+
configurable: true
|
|
225
|
+
}),
|
|
226
|
+
_a.style = new Proxy(element.style, elementProxy),
|
|
190
227
|
_a);
|
|
191
228
|
elementWrapCache.set(element, domEntity_1);
|
|
192
229
|
}
|