@thi.ng/rdom 0.13.2 → 0.13.4
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/CHANGELOG.md +13 -1
- package/README.md +3 -1
- package/api.js +0 -1
- package/checks.js +8 -23
- package/compile.js +57 -87
- package/component.js +143 -133
- package/dom.d.ts +7 -4
- package/dom.js +197 -376
- package/event.js +14 -51
- package/idgen.js +4 -2
- package/klist.js +105 -161
- package/list.js +64 -108
- package/object.js +34 -97
- package/package.json +14 -12
- package/promise.js +24 -40
- package/replace.js +30 -58
- package/scheduler.js +36 -51
- package/sub.js +49 -47
- package/switch.js +66 -135
- package/wrap.js +31 -47
package/dom.js
CHANGED
|
@@ -7,401 +7,222 @@ import { isNumber } from "@thi.ng/checks/is-number";
|
|
|
7
7
|
import { isString } from "@thi.ng/checks/is-string";
|
|
8
8
|
import { assert } from "@thi.ng/errors/assert";
|
|
9
9
|
import { unsupported } from "@thi.ng/errors/unsupported";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
ATTRIB_JOIN_DELIMS,
|
|
12
|
+
NO_SPANS,
|
|
13
|
+
RE_TAG,
|
|
14
|
+
SVG_TAGS
|
|
15
|
+
} from "@thi.ng/hiccup/api";
|
|
11
16
|
import { mergeClasses, mergeEmmetAttribs } from "@thi.ng/hiccup/attribs";
|
|
12
17
|
import { formatPrefixes } from "@thi.ng/hiccup/prefix";
|
|
13
18
|
import { XML_SVG, XML_XLINK, XML_XMLNS } from "@thi.ng/prefixes/xml";
|
|
14
19
|
import { isComment, isComponent } from "./checks.js";
|
|
15
|
-
|
|
16
|
-
* hdom-style DOM tree creation from hiccup format. Returns DOM element of
|
|
17
|
-
* `tree` root. See {@link $el} for further details.
|
|
18
|
-
*
|
|
19
|
-
* @remarks
|
|
20
|
-
* Supports elements given in these forms:
|
|
21
|
-
*
|
|
22
|
-
* - {@link IComponent} instance
|
|
23
|
-
* - {@link IDeref} instance (must resolve to another supported type in this
|
|
24
|
-
* list)
|
|
25
|
-
* - `["div#id.class", {...attribs}, ...children]`
|
|
26
|
-
* - `[COMMENT, "foo", "bar"...]` (DOM comment node)
|
|
27
|
-
* - `[IComponent, ...mountargs]`
|
|
28
|
-
* - `[function, ...args]`
|
|
29
|
-
* - ES6 iterable of the above (for child values only!)
|
|
30
|
-
*
|
|
31
|
-
* Any other values will be cast to strings and added as spans to current
|
|
32
|
-
* `parent`.
|
|
33
|
-
*
|
|
34
|
-
* Note: `COMMENT` is defined as constant in thi.ng/hiccup package. Also see
|
|
35
|
-
* {@link $comment} function to create comments directly.
|
|
36
|
-
*
|
|
37
|
-
* @param tree -
|
|
38
|
-
* @param parent -
|
|
39
|
-
* @param idx -
|
|
40
|
-
*/
|
|
41
|
-
export const $tree = async (tree, parent, idx = -1) => isArray(tree)
|
|
42
|
-
? isComment(tree)
|
|
43
|
-
? $comment(tree.slice(1), parent, idx)
|
|
44
|
-
: $treeElem(tree, parent, idx)
|
|
45
|
-
: isComponent(tree)
|
|
46
|
-
? tree.mount(parent, idx)
|
|
47
|
-
: isDeref(tree)
|
|
48
|
-
? $tree(tree.deref(), parent)
|
|
49
|
-
: isNotStringAndIterable(tree)
|
|
50
|
-
? $treeIter(tree, parent)
|
|
51
|
-
: tree != null
|
|
52
|
-
? $el("span", null, tree, parent, idx)
|
|
53
|
-
: null;
|
|
20
|
+
const $tree = async (tree, parent, idx = -1) => isArray(tree) ? isComment(tree) ? $comment(tree.slice(1), parent, idx) : $treeElem(tree, parent, idx) : isComponent(tree) ? tree.mount(parent, idx) : isDeref(tree) ? $tree(tree.deref(), parent) : isNotStringAndIterable(tree) ? $treeIter(tree, parent) : tree != null ? $el("span", null, tree, parent, idx) : null;
|
|
54
21
|
const $treeElem = (tree, parent, idx) => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
unsupported(`tag: ${tag}`);
|
|
22
|
+
const tag = tree[0];
|
|
23
|
+
return isString(tag) ? $treeTag(tree, parent, idx) : (
|
|
24
|
+
// [icomponent, ...args]
|
|
25
|
+
isComponent(tag) ? tag.mount(parent, idx, ...tree.slice(1)) : (
|
|
26
|
+
// [fn, ...args]
|
|
27
|
+
isFunction(tag) ? $tree(tag.apply(null, tree.slice(1)), parent) : (
|
|
28
|
+
// unsupported
|
|
29
|
+
unsupported(`tag: ${tag}`)
|
|
30
|
+
)
|
|
31
|
+
)
|
|
32
|
+
);
|
|
67
33
|
};
|
|
68
34
|
const $treeTag = (tree, parent, idx) => {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
parent = $el(tag, attribs, body, parent, idx);
|
|
77
|
-
return parent;
|
|
78
|
-
}
|
|
35
|
+
const n = tree.length;
|
|
36
|
+
const { 0: tag, 1: attribs, 2: body } = tree;
|
|
37
|
+
if (n === 3 && (isString(body) || isNumber(body))) {
|
|
38
|
+
const tmp = /^\w+/.exec(tag);
|
|
39
|
+
if (tmp && NO_SPANS[tmp[0]]) {
|
|
40
|
+
parent = $el(tag, attribs, body, parent, idx);
|
|
41
|
+
return parent;
|
|
79
42
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
43
|
+
}
|
|
44
|
+
parent = $el(tag, attribs, null, parent, idx);
|
|
45
|
+
for (let i = 2; i < n; i++) {
|
|
46
|
+
$tree(tree[i], parent);
|
|
47
|
+
}
|
|
48
|
+
return parent;
|
|
85
49
|
};
|
|
86
50
|
const $treeIter = (tree, parent) => {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
* at `idx`. Returns comment node.
|
|
139
|
-
*
|
|
140
|
-
* @remarks
|
|
141
|
-
* See thi.ng/hiccup docs for reference:
|
|
142
|
-
* - https://docs.thi.ng/umbrella/hiccup/functions/serialize.html
|
|
143
|
-
*
|
|
144
|
-
* @param body
|
|
145
|
-
* @param parent
|
|
146
|
-
* @param idx
|
|
147
|
-
*/
|
|
148
|
-
export const $comment = (body, parent, idx = -1) => {
|
|
149
|
-
const comment = document.createComment(isString(body)
|
|
150
|
-
? body
|
|
151
|
-
: body.length < 2
|
|
152
|
-
? body[0] || ""
|
|
153
|
-
: ["", ...body, ""].join("\n"));
|
|
154
|
-
parent && $addChild(parent, comment, idx);
|
|
155
|
-
return comment;
|
|
156
|
-
};
|
|
157
|
-
/**
|
|
158
|
-
* Appends or inserts `child` as child element of `parent`. The default `idx` of
|
|
159
|
-
* -1 means the child will be appended, else uses `parent.insertBefore()` to
|
|
160
|
-
* insert at given index.
|
|
161
|
-
*
|
|
162
|
-
* @param parent
|
|
163
|
-
* @param child
|
|
164
|
-
* @param idx
|
|
165
|
-
*/
|
|
166
|
-
export const $addChild = (parent, child, idx = -1) => {
|
|
167
|
-
isNumber(idx)
|
|
168
|
-
? idx < 0 || idx >= parent.children.length
|
|
169
|
-
? parent.appendChild(child)
|
|
170
|
-
: parent.insertBefore(child, parent.children[idx])
|
|
171
|
-
: parent.insertBefore(child, idx);
|
|
172
|
-
};
|
|
173
|
-
/**
|
|
174
|
-
* Removes given element or comment from the DOM.
|
|
175
|
-
*
|
|
176
|
-
* @param el
|
|
177
|
-
*/
|
|
178
|
-
export const $remove = (el) => el && el.remove();
|
|
179
|
-
/**
|
|
180
|
-
* Migrates given element to `newParent`, following the same append or insertion
|
|
181
|
-
* logic as {@link $addChild}.
|
|
182
|
-
*
|
|
183
|
-
* @param newParent
|
|
184
|
-
* @param el
|
|
185
|
-
* @param idx
|
|
186
|
-
*/
|
|
187
|
-
export const $moveTo = (newParent, el, idx = -1) => {
|
|
188
|
-
$remove(el);
|
|
189
|
-
$addChild(newParent, el, idx);
|
|
190
|
-
};
|
|
191
|
-
/**
|
|
192
|
-
* Removes all content from given element.
|
|
193
|
-
*
|
|
194
|
-
* @param el
|
|
195
|
-
*/
|
|
196
|
-
export const $clear = (el) => ((el.innerHTML = ""), el);
|
|
197
|
-
/**
|
|
198
|
-
* Same as `el.textContent = body`, however if `body` is an
|
|
199
|
-
* [`IDeref`](https://docs.thi.ng/umbrella/api/interfaces/IDeref.html) it'll be
|
|
200
|
-
* first automatically deref'd and coerced to a string. If `body === undefined`
|
|
201
|
-
* an empty string will be used.
|
|
202
|
-
*
|
|
203
|
-
* @param el -
|
|
204
|
-
* @param body -
|
|
205
|
-
*/
|
|
206
|
-
export const $text = (el, body) => {
|
|
207
|
-
body = deref(body);
|
|
208
|
-
el.textContent = body !== undefined ? String(body) : "";
|
|
209
|
-
};
|
|
210
|
-
/**
|
|
211
|
-
* Same as `el.innerHtml = body`, use with caution! If `body` is an
|
|
212
|
-
* [`IDeref`](https://docs.thi.ng/umbrella/api/interfaces/IDeref.html) it'll be
|
|
213
|
-
* automatically deref'd.
|
|
214
|
-
*
|
|
215
|
-
* @param el -
|
|
216
|
-
* @param body -
|
|
217
|
-
*/
|
|
218
|
-
export const $html = (el, body) => {
|
|
219
|
-
el.innerHTML = String(deref(body));
|
|
220
|
-
};
|
|
221
|
-
/**
|
|
222
|
-
* Takes an object of attributes and applies them to given DOM element.
|
|
223
|
-
*
|
|
224
|
-
* @remarks
|
|
225
|
-
* The following rules & transformations are applied (in the stated order):
|
|
226
|
-
*
|
|
227
|
-
* - [`IDeref`](https://docs.thi.ng/umbrella/api/interfaces/IDeref.html) values
|
|
228
|
-
* are `deref`d
|
|
229
|
-
* - attributes prefixed with `on` are considered event listeners and can either
|
|
230
|
-
* have a function value or tuple of `[listener, opts]`, where `opts` are the
|
|
231
|
-
* standard `.addEventListener()` options
|
|
232
|
-
* - function values for any other attribs are first called with the entire
|
|
233
|
-
* `attribs` object and return value used
|
|
234
|
-
* - array values are converted into space-delimited string
|
|
235
|
-
*
|
|
236
|
-
* CSS classs are to given as `class` attribute, with its value either a string
|
|
237
|
-
* or an object of booleans. If the latter, the given class names are either
|
|
238
|
-
* added to or removed from the current list of classes.
|
|
239
|
-
*
|
|
240
|
-
* CSS style rules can be defined via the `style` attrib. Please {@link $style}
|
|
241
|
-
* for further details.
|
|
242
|
-
*
|
|
243
|
-
* Data attributes are to be given as object under the `data` attribute name,
|
|
244
|
-
* with its values being merged with the element's current `dataset` property.
|
|
245
|
-
*
|
|
246
|
-
* Depending on element type the `value` attribute will be updated keeping the
|
|
247
|
-
* current cursor position / selection intact.
|
|
248
|
-
*
|
|
249
|
-
* @param el -
|
|
250
|
-
* @param attribs -
|
|
251
|
-
*/
|
|
252
|
-
export const $attribs = (el, attribs) => {
|
|
253
|
-
for (let id in attribs) {
|
|
254
|
-
setAttrib(el, id, attribs[id], attribs);
|
|
255
|
-
}
|
|
256
|
-
return el;
|
|
51
|
+
for (let t of tree) {
|
|
52
|
+
$tree(t, parent);
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
};
|
|
56
|
+
const $el = (tag, attribs, body, parent, idx = -1) => {
|
|
57
|
+
const match = RE_TAG.exec(tag);
|
|
58
|
+
if (match) {
|
|
59
|
+
attribs = mergeEmmetAttribs({ ...attribs }, match[2], match[3]);
|
|
60
|
+
tag = match[1];
|
|
61
|
+
}
|
|
62
|
+
let el;
|
|
63
|
+
const qidx = tag.indexOf(":");
|
|
64
|
+
if (qidx < 0) {
|
|
65
|
+
el = SVG_TAGS[tag] ? document.createElementNS(XML_SVG, tag) : document.createElement(tag);
|
|
66
|
+
} else {
|
|
67
|
+
el = document.createElementNS(PREFIXES[tag.substring(0, qidx)], tag);
|
|
68
|
+
}
|
|
69
|
+
attribs && $attribs(el, attribs);
|
|
70
|
+
body != null && $text(el, body);
|
|
71
|
+
parent && $addChild(parent, el, idx);
|
|
72
|
+
return el;
|
|
73
|
+
};
|
|
74
|
+
const $comment = (body, parent, idx = -1) => {
|
|
75
|
+
const comment = document.createComment(
|
|
76
|
+
isString(body) ? body : body.length < 2 ? body[0] || "" : ["", ...body, ""].join("\n")
|
|
77
|
+
);
|
|
78
|
+
parent && $addChild(parent, comment, idx);
|
|
79
|
+
return comment;
|
|
80
|
+
};
|
|
81
|
+
const $addChild = (parent, child, idx = -1) => {
|
|
82
|
+
isNumber(idx) ? idx < 0 || idx >= parent.children.length ? parent.appendChild(child) : parent.insertBefore(child, parent.children[idx]) : parent.insertBefore(child, idx);
|
|
83
|
+
};
|
|
84
|
+
const $remove = (el) => el && el.remove();
|
|
85
|
+
const $moveTo = (newParent, el, idx = -1) => {
|
|
86
|
+
$remove(el);
|
|
87
|
+
$addChild(newParent, el, idx);
|
|
88
|
+
};
|
|
89
|
+
const $clear = (el) => (el.innerHTML = "", el);
|
|
90
|
+
const $text = (el, body) => {
|
|
91
|
+
body = deref(body);
|
|
92
|
+
el.textContent = body !== void 0 ? String(body) : "";
|
|
93
|
+
};
|
|
94
|
+
const $html = (el, body) => {
|
|
95
|
+
el.innerHTML = String(deref(body));
|
|
96
|
+
};
|
|
97
|
+
const $attribs = (el, attribs) => {
|
|
98
|
+
for (let id in attribs) {
|
|
99
|
+
setAttrib(el, id, attribs[id], attribs);
|
|
100
|
+
}
|
|
101
|
+
return el;
|
|
257
102
|
};
|
|
258
103
|
const setAttrib = (el, id, val, attribs) => {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
isArray(val)
|
|
268
|
-
? el.addEventListener(id, val[0], val[1])
|
|
269
|
-
: el.addEventListener(id, val);
|
|
270
|
-
}
|
|
271
|
-
return;
|
|
104
|
+
implementsFunction(val, "deref") && (val = val.deref());
|
|
105
|
+
const isListener = id.startsWith("on");
|
|
106
|
+
if (isListener) {
|
|
107
|
+
if (isString(val)) {
|
|
108
|
+
el.setAttribute(id, val);
|
|
109
|
+
} else {
|
|
110
|
+
id = id.substring(2);
|
|
111
|
+
isArray(val) ? el.addEventListener(id, val[0], val[1]) : el.addEventListener(id, val);
|
|
272
112
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
const ns = PREFIXES[id.substring(0, idx)];
|
|
322
|
-
val === false || val == null
|
|
323
|
-
? el.removeAttributeNS(ns, id)
|
|
324
|
-
: el.setAttributeNS(ns, id, val);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
isFunction(val) && (val = val(attribs));
|
|
116
|
+
isArray(val) && (val = val.join(ATTRIB_JOIN_DELIMS[id] || " "));
|
|
117
|
+
switch (id) {
|
|
118
|
+
case "class":
|
|
119
|
+
el.className = isString(val) ? val : mergeClasses(el.className, val);
|
|
120
|
+
break;
|
|
121
|
+
case "style":
|
|
122
|
+
$style(el, val);
|
|
123
|
+
break;
|
|
124
|
+
case "value":
|
|
125
|
+
updateValueAttrib(el, val);
|
|
126
|
+
break;
|
|
127
|
+
case "data":
|
|
128
|
+
updateDataAttribs(el, val);
|
|
129
|
+
break;
|
|
130
|
+
case "prefix":
|
|
131
|
+
el.setAttribute(id, isString(val) ? val : formatPrefixes(val));
|
|
132
|
+
break;
|
|
133
|
+
case "accessKey":
|
|
134
|
+
case "autocapitalize":
|
|
135
|
+
case "checked":
|
|
136
|
+
case "contentEditable":
|
|
137
|
+
case "dir":
|
|
138
|
+
case "draggable":
|
|
139
|
+
case "hidden":
|
|
140
|
+
case "id":
|
|
141
|
+
case "indeterminate":
|
|
142
|
+
case "lang":
|
|
143
|
+
case "scrollLeft":
|
|
144
|
+
case "scrollTop":
|
|
145
|
+
case "selectionEnd":
|
|
146
|
+
case "selectionStart":
|
|
147
|
+
case "slot":
|
|
148
|
+
case "spellcheck":
|
|
149
|
+
case "tabIndex":
|
|
150
|
+
case "title":
|
|
151
|
+
el[id] = val;
|
|
152
|
+
break;
|
|
153
|
+
default: {
|
|
154
|
+
const idx = id.indexOf(":");
|
|
155
|
+
if (idx < 0) {
|
|
156
|
+
val === false || val == null ? el.removeAttribute(id) : el.setAttribute(id, val === true ? id : val);
|
|
157
|
+
} else {
|
|
158
|
+
const ns = PREFIXES[id.substring(0, idx)];
|
|
159
|
+
val === false || val == null ? el.removeAttributeNS(ns, id) : el.setAttributeNS(ns, id, val);
|
|
160
|
+
}
|
|
327
161
|
}
|
|
162
|
+
}
|
|
328
163
|
};
|
|
329
164
|
const updateValueAttrib = (el, value) => {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
el.selectionStart = el.selectionEnd = off;
|
|
349
|
-
break;
|
|
350
|
-
}
|
|
351
|
-
default:
|
|
352
|
-
el.value = value;
|
|
353
|
-
}
|
|
165
|
+
let ev;
|
|
166
|
+
switch (el.type) {
|
|
167
|
+
case "text":
|
|
168
|
+
case "textarea":
|
|
169
|
+
case "password":
|
|
170
|
+
case "search":
|
|
171
|
+
case "number":
|
|
172
|
+
case "url":
|
|
173
|
+
case "tel":
|
|
174
|
+
if ((ev = el.value) !== void 0 && isString(value)) {
|
|
175
|
+
const off = value.length - (ev.length - (el.selectionStart || 0));
|
|
176
|
+
el.value = value;
|
|
177
|
+
el.selectionStart = el.selectionEnd = off;
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
default:
|
|
181
|
+
el.value = value;
|
|
182
|
+
}
|
|
354
183
|
};
|
|
355
184
|
const updateDataAttribs = (el, attribs) => {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
185
|
+
const data = el.dataset;
|
|
186
|
+
for (let id in attribs) {
|
|
187
|
+
const v = deref(attribs[id]);
|
|
188
|
+
data[id] = isFunction(v) ? v(attribs) : v;
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
const $style = (el, rules) => {
|
|
192
|
+
if (isString(rules)) {
|
|
193
|
+
el.setAttribute("style", rules);
|
|
194
|
+
} else {
|
|
195
|
+
const style = el.style;
|
|
196
|
+
for (let id in rules) {
|
|
197
|
+
let v = deref(rules[id]);
|
|
198
|
+
isFunction(v) && (v = v(rules));
|
|
199
|
+
style[id] = v != null ? v : "";
|
|
360
200
|
}
|
|
201
|
+
}
|
|
361
202
|
};
|
|
362
|
-
/**
|
|
363
|
-
* Takes an object (or string) of CSS properties, compiles them into a single
|
|
364
|
-
* CSS string and sets it as `style` attribute on the given element.
|
|
365
|
-
*
|
|
366
|
-
* @remarks
|
|
367
|
-
* All property values can be
|
|
368
|
-
* [`IDeref`](https://docs.thi.ng/umbrella/api/interfaces/IDeref.html) values,
|
|
369
|
-
* in which case they're are first `deref`d before use. If the value is a
|
|
370
|
-
* function, it will be called with the entire `rules` object as arg and the
|
|
371
|
-
* return value used.
|
|
372
|
-
*
|
|
373
|
-
* @param el -
|
|
374
|
-
* @param rules -
|
|
375
|
-
*/
|
|
376
|
-
export const $style = (el, rules) => {
|
|
377
|
-
if (isString(rules)) {
|
|
378
|
-
el.setAttribute("style", rules);
|
|
379
|
-
}
|
|
380
|
-
else {
|
|
381
|
-
const style = el.style;
|
|
382
|
-
for (let id in rules) {
|
|
383
|
-
let v = deref(rules[id]);
|
|
384
|
-
isFunction(v) && (v = v(rules));
|
|
385
|
-
style[id] = v != null ? v : "";
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
};
|
|
389
|
-
/**
|
|
390
|
-
* @internal
|
|
391
|
-
*/
|
|
392
203
|
const PREFIXES = {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
};
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
export
|
|
405
|
-
|
|
406
|
-
|
|
204
|
+
svg: XML_SVG,
|
|
205
|
+
xlink: XML_XLINK,
|
|
206
|
+
xmlns: XML_XMLNS
|
|
207
|
+
};
|
|
208
|
+
const registerPrefix = (prefix, url) => {
|
|
209
|
+
assert(
|
|
210
|
+
!PREFIXES[prefix],
|
|
211
|
+
`${prefix} already registered: ${PREFIXES[prefix]}`
|
|
212
|
+
);
|
|
213
|
+
PREFIXES[prefix] = url;
|
|
214
|
+
};
|
|
215
|
+
export {
|
|
216
|
+
$addChild,
|
|
217
|
+
$attribs,
|
|
218
|
+
$clear,
|
|
219
|
+
$comment,
|
|
220
|
+
$el,
|
|
221
|
+
$html,
|
|
222
|
+
$moveTo,
|
|
223
|
+
$remove,
|
|
224
|
+
$style,
|
|
225
|
+
$text,
|
|
226
|
+
$tree,
|
|
227
|
+
registerPrefix
|
|
407
228
|
};
|
package/event.js
CHANGED
|
@@ -1,52 +1,15 @@
|
|
|
1
1
|
import { maybeParseFloat } from "@thi.ng/strings/parse";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export const $input = (stream) => (e) => stream.next(e.target.value);
|
|
17
|
-
/**
|
|
18
|
-
* Similar to {@link $input}, but attempts to first coerce value using
|
|
19
|
-
* `parseFloat()`. Uses given `fallback` value (default: 0) if coercion failed
|
|
20
|
-
* (i.e. if the event target's `.value` isn't numeric).
|
|
21
|
-
*
|
|
22
|
-
* @param stream -
|
|
23
|
-
* @param fallback -
|
|
24
|
-
*/
|
|
25
|
-
export const $inputNum = (stream, fallback = 0) => (e) => stream.next(maybeParseFloat(e.target.value, fallback));
|
|
26
|
-
/**
|
|
27
|
-
* HOF DOM event listener to emit a checkbox input's value on given stream.
|
|
28
|
-
*
|
|
29
|
-
* @param stream -
|
|
30
|
-
*/
|
|
31
|
-
export const $inputCheckbox = (stream) => (e) => stream.next(e.target.checked);
|
|
32
|
-
/**
|
|
33
|
-
* HOF DOM event listener to emit `true` on given stream when event is
|
|
34
|
-
* triggered.
|
|
35
|
-
*
|
|
36
|
-
* @param stream -
|
|
37
|
-
*/
|
|
38
|
-
export const $inputTrigger = (stream) => () => stream.next(true);
|
|
39
|
-
/**
|
|
40
|
-
* HOF DOM event listener to emit a file input's first selected file on given
|
|
41
|
-
* stream.
|
|
42
|
-
*
|
|
43
|
-
* @param stream -
|
|
44
|
-
*/
|
|
45
|
-
export const $inputFile = (stream) => (e) => stream.next(e.target.files[0]);
|
|
46
|
-
/**
|
|
47
|
-
* HOF DOM event listener to emit a file input's entire selected list of files
|
|
48
|
-
* on given stream.
|
|
49
|
-
*
|
|
50
|
-
* @param stream -
|
|
51
|
-
*/
|
|
52
|
-
export const $inputFiles = (stream) => (e) => stream.next(e.target.files);
|
|
2
|
+
const $input = (stream) => (e) => stream.next(e.target.value);
|
|
3
|
+
const $inputNum = (stream, fallback = 0) => (e) => stream.next(maybeParseFloat(e.target.value, fallback));
|
|
4
|
+
const $inputCheckbox = (stream) => (e) => stream.next(e.target.checked);
|
|
5
|
+
const $inputTrigger = (stream) => () => stream.next(true);
|
|
6
|
+
const $inputFile = (stream) => (e) => stream.next(e.target.files[0]);
|
|
7
|
+
const $inputFiles = (stream) => (e) => stream.next(e.target.files);
|
|
8
|
+
export {
|
|
9
|
+
$input,
|
|
10
|
+
$inputCheckbox,
|
|
11
|
+
$inputFile,
|
|
12
|
+
$inputFiles,
|
|
13
|
+
$inputNum,
|
|
14
|
+
$inputTrigger
|
|
15
|
+
};
|
package/idgen.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
let NEXT_ID = 0;
|
|
2
|
-
|
|
3
|
-
export
|
|
2
|
+
const __nextID = (name, src) => src ? `rdom$${name}-${src.id}-${NEXT_ID++}` : `rdom$${name}-${NEXT_ID++}`;
|
|
3
|
+
export {
|
|
4
|
+
__nextID
|
|
5
|
+
};
|