@taybart/corvid 0.1.31 → 0.2.2
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/dist/dom.d.ts +99 -14
- package/dist/dom.js +247 -36
- package/dist/index.js +263 -36
- package/dist/ls.js +227 -39
- package/dist/qr.js +227 -39
- package/dist/style.d.ts +36 -0
- package/dist/style.js +100 -1
- package/dist/style.test.d.ts +1 -0
- package/package.json +11 -9
package/dist/ls.js
CHANGED
|
@@ -6,6 +6,97 @@ function render(style) {
|
|
|
6
6
|
Object.entries(style).forEach(([k, v])=>s += `${toKebab(k)}:${v};`);
|
|
7
7
|
return s;
|
|
8
8
|
}
|
|
9
|
+
function splitSelectors(selector) {
|
|
10
|
+
const out = [];
|
|
11
|
+
let depth = 0;
|
|
12
|
+
let quote = '';
|
|
13
|
+
let current = '';
|
|
14
|
+
for (const ch of selector){
|
|
15
|
+
if (quote) {
|
|
16
|
+
if (ch === quote) quote = '';
|
|
17
|
+
} else if ('"' === ch || "'" === ch) quote = ch;
|
|
18
|
+
else if ('(' === ch || '[' === ch) depth++;
|
|
19
|
+
else if (')' === ch || ']' === ch) depth--;
|
|
20
|
+
else if (',' === ch && 0 === depth) {
|
|
21
|
+
if (current.trim()) out.push(current.trim());
|
|
22
|
+
current = '';
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
current += ch;
|
|
26
|
+
}
|
|
27
|
+
if (current.trim()) out.push(current.trim());
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
function resolve(parents, selector) {
|
|
31
|
+
const out = [];
|
|
32
|
+
for (const parent of parents)for (const part of splitSelectors(selector))out.push(part.includes('&') ? part.replaceAll('&', parent) : `${parent} ${part}`);
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
function compile(parents, decls, indent = '') {
|
|
36
|
+
const blocks = [];
|
|
37
|
+
const props = [];
|
|
38
|
+
const nested = [];
|
|
39
|
+
for (const [k, v] of Object.entries(decls))if (null !== v && 'object' == typeof v) nested.push([
|
|
40
|
+
k,
|
|
41
|
+
v
|
|
42
|
+
]);
|
|
43
|
+
else props.push(`${indent} ${toKebab(k)}: ${v};`);
|
|
44
|
+
if (props.length) blocks.push(`${indent}${parents.join(', ')} {\n${props.join('\n')}\n${indent}}`);
|
|
45
|
+
for (const [selector, block] of nested){
|
|
46
|
+
if (selector.startsWith('@')) {
|
|
47
|
+
const inner = selector.startsWith('@keyframes') ? Object.entries(block).flatMap(([step, d])=>null !== d && 'object' == typeof d ? compile([
|
|
48
|
+
step
|
|
49
|
+
], d, `${indent} `) : []) : compile(parents, block, `${indent} `);
|
|
50
|
+
if (inner.length) blocks.push(`${indent}${selector} {\n${inner.join('\n')}\n${indent}}`);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
blocks.push(...compile(resolve(parents, selector), block, indent));
|
|
54
|
+
}
|
|
55
|
+
return blocks;
|
|
56
|
+
}
|
|
57
|
+
function css(selector, style) {
|
|
58
|
+
return compile(splitSelectors(selector), style).join('\n');
|
|
59
|
+
}
|
|
60
|
+
function registry() {
|
|
61
|
+
const doc = document;
|
|
62
|
+
if (!doc.__corvidSheets) doc.__corvidSheets = new Map();
|
|
63
|
+
return doc.__corvidSheets;
|
|
64
|
+
}
|
|
65
|
+
function adoptable() {
|
|
66
|
+
return 'undefined' != typeof CSSStyleSheet && 'replaceSync' in CSSStyleSheet.prototype && 'undefined' != typeof Document && 'adoptedStyleSheets' in Document.prototype;
|
|
67
|
+
}
|
|
68
|
+
function styleTag(key) {
|
|
69
|
+
const tagged = Array.from(document.head.querySelectorAll('style[data-corvid]'));
|
|
70
|
+
for (const node of tagged)if (node.dataset.corvid === key) return node;
|
|
71
|
+
const node = document.createElement('style');
|
|
72
|
+
node.dataset.corvid = key;
|
|
73
|
+
document.head.appendChild(node);
|
|
74
|
+
return node;
|
|
75
|
+
}
|
|
76
|
+
function inject(selector, style, { key = selector } = {}) {
|
|
77
|
+
const rules = css(selector, style);
|
|
78
|
+
const sheets = registry();
|
|
79
|
+
const existing = sheets.get(key);
|
|
80
|
+
if (existing) {
|
|
81
|
+
if ('replaceSync' in existing) existing.replaceSync(rules);
|
|
82
|
+
else existing.textContent = rules;
|
|
83
|
+
return rules;
|
|
84
|
+
}
|
|
85
|
+
if (adoptable()) {
|
|
86
|
+
const sheet = new CSSStyleSheet();
|
|
87
|
+
sheet.replaceSync(rules);
|
|
88
|
+
document.adoptedStyleSheets = [
|
|
89
|
+
...document.adoptedStyleSheets,
|
|
90
|
+
sheet
|
|
91
|
+
];
|
|
92
|
+
sheets.set(key, sheet);
|
|
93
|
+
return rules;
|
|
94
|
+
}
|
|
95
|
+
const node = styleTag(key);
|
|
96
|
+
node.textContent = rules;
|
|
97
|
+
sheets.set(key, node);
|
|
98
|
+
return rules;
|
|
99
|
+
}
|
|
9
100
|
function _define_property(obj, key, value) {
|
|
10
101
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
11
102
|
value: value,
|
|
@@ -61,6 +152,37 @@ class utils_logger {
|
|
|
61
152
|
});
|
|
62
153
|
}
|
|
63
154
|
}
|
|
155
|
+
function _check_private_redeclaration(obj, privateCollection) {
|
|
156
|
+
if (privateCollection.has(obj)) throw new TypeError("Cannot initialize the same private elements twice on an object");
|
|
157
|
+
}
|
|
158
|
+
function _class_apply_descriptor_get(receiver, descriptor) {
|
|
159
|
+
if (descriptor.get) return descriptor.get.call(receiver);
|
|
160
|
+
return descriptor.value;
|
|
161
|
+
}
|
|
162
|
+
function _class_apply_descriptor_set(receiver, descriptor, value) {
|
|
163
|
+
if (descriptor.set) descriptor.set.call(receiver, value);
|
|
164
|
+
else {
|
|
165
|
+
if (!descriptor.writable) throw new TypeError("attempted to set read only private field");
|
|
166
|
+
descriptor.value = value;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function _class_extract_field_descriptor(receiver, privateMap, action) {
|
|
170
|
+
if (!privateMap.has(receiver)) throw new TypeError("attempted to " + action + " private field on non-instance");
|
|
171
|
+
return privateMap.get(receiver);
|
|
172
|
+
}
|
|
173
|
+
function _class_private_field_get(receiver, privateMap) {
|
|
174
|
+
var descriptor = _class_extract_field_descriptor(receiver, privateMap, "get");
|
|
175
|
+
return _class_apply_descriptor_get(receiver, descriptor);
|
|
176
|
+
}
|
|
177
|
+
function _class_private_field_init(obj, privateMap, value) {
|
|
178
|
+
_check_private_redeclaration(obj, privateMap);
|
|
179
|
+
privateMap.set(obj, value);
|
|
180
|
+
}
|
|
181
|
+
function _class_private_field_set(receiver, privateMap, value) {
|
|
182
|
+
var descriptor = _class_extract_field_descriptor(receiver, privateMap, "set");
|
|
183
|
+
_class_apply_descriptor_set(receiver, descriptor, value);
|
|
184
|
+
return value;
|
|
185
|
+
}
|
|
64
186
|
function dom_define_property(obj, key, value) {
|
|
65
187
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
66
188
|
value: value,
|
|
@@ -71,6 +193,14 @@ function dom_define_property(obj, key, value) {
|
|
|
71
193
|
else obj[key] = value;
|
|
72
194
|
return obj;
|
|
73
195
|
}
|
|
196
|
+
function registerElement(name, ctor) {
|
|
197
|
+
const existing = customElements.get(name);
|
|
198
|
+
if (existing) {
|
|
199
|
+
if (existing !== ctor) throw new Error(`custom element ${name} is already registered by ${existing.name}`);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
customElements.define(name, ctor);
|
|
203
|
+
}
|
|
74
204
|
class dom_el {
|
|
75
205
|
static query(query, verbose = false) {
|
|
76
206
|
return new dom_el(query, verbose);
|
|
@@ -93,21 +223,29 @@ class dom_el {
|
|
|
93
223
|
parent.appendChild(this.el);
|
|
94
224
|
return this;
|
|
95
225
|
}
|
|
226
|
+
append(ch) {
|
|
227
|
+
return this.child(ch);
|
|
228
|
+
}
|
|
96
229
|
appendChild(ch) {
|
|
97
230
|
return this.child(ch);
|
|
98
231
|
}
|
|
99
232
|
child(ch) {
|
|
100
233
|
if (!this.el) throw new Error(`no element from query: ${this.query}`);
|
|
101
|
-
if (
|
|
234
|
+
if ('string' == typeof ch) this.el.append(ch);
|
|
235
|
+
else if (ch instanceof dom_el) this.el.appendChild(ch.el);
|
|
102
236
|
else this.el.appendChild(ch);
|
|
103
237
|
return this;
|
|
104
238
|
}
|
|
105
|
-
|
|
239
|
+
prepend(ch) {
|
|
106
240
|
if (!this.el) throw new Error(`no element from query: ${this.query}`);
|
|
107
|
-
if (
|
|
241
|
+
if ('string' == typeof ch) this.el.prepend(ch);
|
|
242
|
+
else if (ch instanceof dom_el) this.el.prepend(ch.el);
|
|
108
243
|
else this.el.prepend(ch);
|
|
109
244
|
return this;
|
|
110
245
|
}
|
|
246
|
+
prependChild(ch) {
|
|
247
|
+
return this.prepend(ch);
|
|
248
|
+
}
|
|
111
249
|
empty() {
|
|
112
250
|
if (this.el) this.el.innerHTML = '';
|
|
113
251
|
return this;
|
|
@@ -118,17 +256,37 @@ class dom_el {
|
|
|
118
256
|
else this.el.innerHTML = content;
|
|
119
257
|
return this;
|
|
120
258
|
}
|
|
259
|
+
html(content) {
|
|
260
|
+
if (!this.el) throw new Error(`no element from query: ${this.query}`);
|
|
261
|
+
this.el.innerHTML = content;
|
|
262
|
+
return this;
|
|
263
|
+
}
|
|
121
264
|
src(url) {
|
|
122
265
|
if (this.el && 'src' in this.el) this.el.src = url;
|
|
123
266
|
return this;
|
|
124
267
|
}
|
|
268
|
+
attrs(attrs) {
|
|
269
|
+
if (!this.el) throw new Error(`no element from query: ${this.query}`);
|
|
270
|
+
for (const [k, v] of Object.entries(attrs))this.el.setAttribute(k, v);
|
|
271
|
+
return this;
|
|
272
|
+
}
|
|
273
|
+
attr(key, val) {
|
|
274
|
+
if (!this.el) throw new Error(`no element from query: ${this.query}`);
|
|
275
|
+
this.el.setAttribute(key, val);
|
|
276
|
+
return this;
|
|
277
|
+
}
|
|
278
|
+
removeAttr(key) {
|
|
279
|
+
if (!this.el) throw new Error(`no element from query: ${this.query}`);
|
|
280
|
+
this.el.removeAttribute(key);
|
|
281
|
+
return this;
|
|
282
|
+
}
|
|
125
283
|
style(update, stringify = false) {
|
|
126
284
|
if (this.el) {
|
|
127
285
|
if ('string' == typeof update) this.el.style = update;
|
|
128
286
|
else if ('object' == typeof update) {
|
|
129
287
|
if (!stringify) {
|
|
130
288
|
for (const [k, v] of Object.entries(update))this.el.style[k] = v;
|
|
131
|
-
return;
|
|
289
|
+
return this;
|
|
132
290
|
}
|
|
133
291
|
const s = render(update);
|
|
134
292
|
this.log.debug(`set style: ${this.el.style} -> ${s}`);
|
|
@@ -153,38 +311,23 @@ class dom_el {
|
|
|
153
311
|
else for (const sc of className)this.el.classList.remove(sc);
|
|
154
312
|
return this;
|
|
155
313
|
}
|
|
156
|
-
|
|
157
|
-
if (!this.el) throw new Error(`no element from query: ${this.query}`);
|
|
158
|
-
this.el.innerHTML = content;
|
|
159
|
-
}
|
|
160
|
-
render(vars = {}) {
|
|
161
|
-
if (!this.el) throw new Error(`no element from query: ${this.query}`);
|
|
162
|
-
try {
|
|
163
|
-
return interpolate(this.el.innerHTML, vars);
|
|
164
|
-
} catch (e) {
|
|
165
|
-
throw new Error(`could not render template ${this.query}: ${e}`);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
appendTemplate(template, vars) {
|
|
169
|
-
if (!this.el) throw new Error(`no element from query: ${this.query}`);
|
|
170
|
-
if (!template.el) throw new Error("template does not contain element");
|
|
171
|
-
const tmpl = template.render(vars);
|
|
172
|
-
this.el.insertAdjacentHTML('beforeend', tmpl);
|
|
173
|
-
}
|
|
174
|
-
on(event, cb) {
|
|
314
|
+
on(event, cb, options) {
|
|
175
315
|
if (!this.el) throw new Error(`no element from query: ${this.query}`);
|
|
176
316
|
if (!this.listeners[event]) this.listeners[event] = [];
|
|
177
|
-
this.listeners[event].push(
|
|
178
|
-
|
|
317
|
+
this.listeners[event].push({
|
|
318
|
+
cb,
|
|
319
|
+
options
|
|
320
|
+
});
|
|
321
|
+
this.el.addEventListener(event, cb, options);
|
|
179
322
|
return this;
|
|
180
323
|
}
|
|
181
|
-
listen(event, cb) {
|
|
182
|
-
return this.on(event, cb);
|
|
324
|
+
listen(event, cb, options) {
|
|
325
|
+
return this.on(event, cb, options);
|
|
183
326
|
}
|
|
184
327
|
removeListeners(event) {
|
|
185
328
|
if (!this.el) throw new Error(`no element from query: ${this.query}`);
|
|
186
329
|
if (!this.listeners[event]) return this;
|
|
187
|
-
for (const cb of this.listeners[event])this.el.removeEventListener(event, cb);
|
|
330
|
+
for (const { cb, options } of this.listeners[event])this.el.removeEventListener(event, cb, options);
|
|
188
331
|
this.listeners[event] = [];
|
|
189
332
|
return this;
|
|
190
333
|
}
|
|
@@ -204,7 +347,7 @@ class dom_el {
|
|
|
204
347
|
this.el = opts;
|
|
205
348
|
return;
|
|
206
349
|
}
|
|
207
|
-
const { query, element,
|
|
350
|
+
const { query, element, tag, class: styleClass, style, id, content, parent, attrs } = opts;
|
|
208
351
|
if (query) {
|
|
209
352
|
this.log.debug(`using query: ${query}`);
|
|
210
353
|
this.query = query;
|
|
@@ -213,11 +356,11 @@ class dom_el {
|
|
|
213
356
|
} else if (element) {
|
|
214
357
|
this.log.debug(`using existing element: ${element}`);
|
|
215
358
|
this.el = element;
|
|
216
|
-
} else if (
|
|
217
|
-
this.query =
|
|
218
|
-
this.log.debug(`creating element: ${
|
|
219
|
-
this.el = document.createElement(
|
|
220
|
-
} else throw new Error('no query or
|
|
359
|
+
} else if (tag) {
|
|
360
|
+
this.query = tag;
|
|
361
|
+
this.log.debug(`creating element: ${tag}`);
|
|
362
|
+
this.el = document.createElement(tag);
|
|
363
|
+
} else throw new Error('no query or tag provided');
|
|
221
364
|
if (this.el) {
|
|
222
365
|
if (id) {
|
|
223
366
|
this.log.debug(`setting id: ${id}`);
|
|
@@ -232,7 +375,12 @@ class dom_el {
|
|
|
232
375
|
}
|
|
233
376
|
if (parent) {
|
|
234
377
|
this.log.debug("adding to parent");
|
|
235
|
-
parent
|
|
378
|
+
let p = parent;
|
|
379
|
+
if ('string' == typeof parent) {
|
|
380
|
+
this.log.debug(`parent query: ${parent}`);
|
|
381
|
+
p = document.querySelector(parent);
|
|
382
|
+
}
|
|
383
|
+
p.appendChild(this.el);
|
|
236
384
|
}
|
|
237
385
|
}
|
|
238
386
|
if (attrs) for (const [key, val] of Object.entries(attrs)){
|
|
@@ -241,11 +389,51 @@ class dom_el {
|
|
|
241
389
|
}
|
|
242
390
|
}
|
|
243
391
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
392
|
+
var _mounted = /*#__PURE__*/ new WeakMap(), _pendingAttrs = /*#__PURE__*/ new WeakMap();
|
|
393
|
+
class component extends HTMLElement {
|
|
394
|
+
static register(tag) {
|
|
395
|
+
const name = tag ?? this.tag;
|
|
396
|
+
if (!name) throw new Error(`${this.name}: nothing to register as, set \`static tag = 'x-...'\``);
|
|
397
|
+
if (!name.includes('-')) throw new Error(`${this.name}: '${name}' is not a valid custom element name, it needs a hyphen`);
|
|
398
|
+
if (this.styles) inject(name, this.styles);
|
|
399
|
+
registerElement(name, this);
|
|
400
|
+
}
|
|
401
|
+
mount() {}
|
|
402
|
+
unmount() {}
|
|
403
|
+
onAttr(_name, _value, _prev) {}
|
|
404
|
+
connectedCallback() {
|
|
405
|
+
if (!_class_private_field_get(this, _mounted)) {
|
|
406
|
+
_class_private_field_set(this, _mounted, true);
|
|
407
|
+
this.mount();
|
|
408
|
+
const queued = _class_private_field_get(this, _pendingAttrs);
|
|
409
|
+
_class_private_field_set(this, _pendingAttrs, []);
|
|
410
|
+
for (const [name, value, prev] of queued)this.onAttr(name, value, prev);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
disconnectedCallback() {
|
|
414
|
+
this.unmount();
|
|
415
|
+
}
|
|
416
|
+
attributeChangedCallback(name, prev, value) {
|
|
417
|
+
if (prev === value) return;
|
|
418
|
+
if (!_class_private_field_get(this, _mounted)) return void _class_private_field_get(this, _pendingAttrs).push([
|
|
419
|
+
name,
|
|
420
|
+
value,
|
|
421
|
+
prev
|
|
422
|
+
]);
|
|
423
|
+
this.onAttr(name, value, prev);
|
|
424
|
+
}
|
|
425
|
+
constructor(...args){
|
|
426
|
+
super(...args), _class_private_field_init(this, _mounted, {
|
|
427
|
+
writable: true,
|
|
428
|
+
value: false
|
|
429
|
+
}), _class_private_field_init(this, _pendingAttrs, {
|
|
430
|
+
writable: true,
|
|
431
|
+
value: []
|
|
432
|
+
});
|
|
433
|
+
}
|
|
248
434
|
}
|
|
435
|
+
dom_define_property(component, "tag", '');
|
|
436
|
+
dom_define_property(component, "styles", null);
|
|
249
437
|
function get(key, _default) {
|
|
250
438
|
let ret = localStorage.getItem(key);
|
|
251
439
|
if (null === ret && null != _default) {
|