@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/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 (ch instanceof dom_el) this.el.appendChild(ch.el);
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
- prependChild(ch) {
239
+ prepend(ch) {
106
240
  if (!this.el) throw new Error(`no element from query: ${this.query}`);
107
- if (ch instanceof dom_el) this.el.prepend(ch.el);
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
- html(content) {
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(cb);
178
- this.el.addEventListener(event, cb);
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, type, class: styleClass, style, id, content, parent, attrs } = opts;
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 (type) {
217
- this.query = type;
218
- this.log.debug(`creating element: ${type}`);
219
- this.el = document.createElement(type);
220
- } else throw new Error('no query or type provided');
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.appendChild(this.el);
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
- function interpolate(str, params) {
245
- let names = Object.keys(params).map((k)=>`_${k}`);
246
- let vals = Object.values(params);
247
- return new Function(...names, `return \`${str.replace(/\$\{(\w*)\}/g, '${_$1}')}\`;`)(...vals);
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) {