@taybart/corvid 0.2.0 → 0.2.3

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/index.js CHANGED
@@ -29,18 +29,23 @@ __webpack_require__.d(strings_namespaceObject, {
29
29
  var style_namespaceObject = {};
30
30
  __webpack_require__.r(style_namespaceObject);
31
31
  __webpack_require__.d(style_namespaceObject, {
32
+ css: ()=>css,
32
33
  cssVar: ()=>cssVar,
34
+ eject: ()=>eject,
33
35
  gradient: ()=>gradient,
34
36
  handleThemeSwitch: ()=>handleThemeSwitch,
35
37
  inject: ()=>inject,
36
38
  isDarkMode: ()=>isDarkMode,
37
39
  onDarkMode: ()=>onDarkMode,
38
40
  render: ()=>render,
41
+ shadowSheet: ()=>shadowSheet,
39
42
  switchTheme: ()=>switchTheme
40
43
  });
41
44
  var dom_namespaceObject = {};
42
45
  __webpack_require__.r(dom_namespaceObject);
43
46
  __webpack_require__.d(dom_namespaceObject, {
47
+ component: ()=>component,
48
+ create: ()=>create,
44
49
  default: ()=>dom,
45
50
  el: ()=>dom_el,
46
51
  els: ()=>els,
@@ -49,7 +54,9 @@ __webpack_require__.d(dom_namespaceObject, {
49
54
  onBlur: ()=>onBlur,
50
55
  onFocus: ()=>onFocus,
51
56
  onKey: ()=>onKey,
52
- ready: ()=>ready
57
+ ready: ()=>ready,
58
+ registerComponents: ()=>registerComponents,
59
+ registerElement: ()=>registerElement
53
60
  });
54
61
  var network_namespaceObject = {};
55
62
  __webpack_require__.r(network_namespaceObject);
@@ -126,17 +133,161 @@ function render(style) {
126
133
  Object.entries(style).forEach(([k, v])=>s += `${toKebab(k)}:${v};`);
127
134
  return s;
128
135
  }
129
- function inject(selector, style) {
130
- const existing = document.getElementById(`corvid-injected-${encodeURIComponent(selector)}`);
131
- if (existing) existing.remove();
132
- const injected = document.createElement('style');
133
- injected.id = `corvid-injected-${encodeURIComponent(selector)}`;
134
- let s = `${selector} {\n`;
135
- Object.entries(style).forEach(([k, v])=>s += `${toKebab(k)}: ${v};\n`);
136
- s += '}';
137
- injected.textContent = s;
138
- document.head.appendChild(injected);
139
- return s;
136
+ function splitSelectors(selector) {
137
+ const out = [];
138
+ let depth = 0;
139
+ let quote = '';
140
+ let current = '';
141
+ for (const ch of selector){
142
+ if (quote) {
143
+ if (ch === quote) quote = '';
144
+ } else if ('"' === ch || "'" === ch) quote = ch;
145
+ else if ('(' === ch || '[' === ch) depth++;
146
+ else if (')' === ch || ']' === ch) depth--;
147
+ else if (',' === ch && 0 === depth) {
148
+ if (current.trim()) out.push(current.trim());
149
+ current = '';
150
+ continue;
151
+ }
152
+ current += ch;
153
+ }
154
+ if (current.trim()) out.push(current.trim());
155
+ return out;
156
+ }
157
+ function hostCompound(selector) {
158
+ if (!selector.startsWith(':host')) return selector;
159
+ let i = 5;
160
+ let inner = '';
161
+ if ('(' === selector[i]) {
162
+ const open = i;
163
+ let depth = 0;
164
+ let quote = '';
165
+ while(i < selector.length){
166
+ const ch = selector[i];
167
+ if (quote) {
168
+ if (ch === quote) quote = '';
169
+ } else if ('"' === ch || "'" === ch) quote = ch;
170
+ else if ('(' === ch) depth++;
171
+ else if (')' === ch) {
172
+ depth--;
173
+ if (0 === depth) {
174
+ i++;
175
+ break;
176
+ }
177
+ }
178
+ i++;
179
+ }
180
+ inner = selector.slice(open + 1, i - 1);
181
+ }
182
+ const start = i;
183
+ let depth = 0;
184
+ let quote = '';
185
+ while(i < selector.length){
186
+ const ch = selector[i];
187
+ if (quote) {
188
+ if (ch === quote) quote = '';
189
+ } else if ('"' === ch || "'" === ch) quote = ch;
190
+ else if (0 === depth && (' ' === ch || '>' === ch || '+' === ch || '~' === ch)) break;
191
+ else if (0 === depth && ':' === ch && ':' === selector[i + 1]) break;
192
+ else if ('(' === ch || '[' === ch) depth++;
193
+ else if (')' === ch || ']' === ch) depth--;
194
+ i++;
195
+ }
196
+ const compound = selector.slice(start, i);
197
+ if (!compound) return selector;
198
+ return `:host(${inner}${compound})${selector.slice(i)}`;
199
+ }
200
+ function resolve(parents, selector) {
201
+ const out = [];
202
+ for (const parent of parents)for (const part of splitSelectors(selector))out.push(hostCompound(part.includes('&') ? part.replaceAll('&', parent) : `${parent} ${part}`));
203
+ return out;
204
+ }
205
+ function compile(parents, decls, indent = '') {
206
+ const blocks = [];
207
+ const props = [];
208
+ const nested = [];
209
+ for (const [k, v] of Object.entries(decls))if (null !== v && 'object' == typeof v) nested.push([
210
+ k,
211
+ v
212
+ ]);
213
+ else props.push(`${indent} ${toKebab(k)}: ${v};`);
214
+ if (props.length) blocks.push(`${indent}${parents.join(', ')} {\n${props.join('\n')}\n${indent}}`);
215
+ for (const [selector, block] of nested){
216
+ if (selector.startsWith('@')) {
217
+ const inner = selector.startsWith('@keyframes') ? Object.entries(block).flatMap(([step, d])=>null !== d && 'object' == typeof d ? compile([
218
+ step
219
+ ], d, `${indent} `) : []) : compile(parents, block, `${indent} `);
220
+ if (inner.length) blocks.push(`${indent}${selector} {\n${inner.join('\n')}\n${indent}}`);
221
+ continue;
222
+ }
223
+ blocks.push(...compile(resolve(parents, selector), block, indent));
224
+ }
225
+ return blocks;
226
+ }
227
+ function css(selector, style) {
228
+ return compile(splitSelectors(selector), style).join('\n');
229
+ }
230
+ function registry() {
231
+ const doc = document;
232
+ if (!doc.__corvidSheets) doc.__corvidSheets = new Map();
233
+ return doc.__corvidSheets;
234
+ }
235
+ function adoptable() {
236
+ return 'undefined' != typeof CSSStyleSheet && 'replaceSync' in CSSStyleSheet.prototype && 'undefined' != typeof Document && 'adoptedStyleSheets' in Document.prototype;
237
+ }
238
+ function styleTag(key) {
239
+ const tagged = Array.from(document.head.querySelectorAll('style[data-corvid]'));
240
+ for (const node of tagged)if (node.dataset.corvid === key) return node;
241
+ const node = document.createElement('style');
242
+ node.dataset.corvid = key;
243
+ document.head.appendChild(node);
244
+ return node;
245
+ }
246
+ function inject(selector, style, { key = selector } = {}) {
247
+ const rules = css(selector, style);
248
+ const sheets = registry();
249
+ const existing = sheets.get(key);
250
+ if (existing) {
251
+ if ('replaceSync' in existing) existing.replaceSync(rules);
252
+ else existing.textContent = rules;
253
+ return rules;
254
+ }
255
+ if (adoptable()) {
256
+ const sheet = new CSSStyleSheet();
257
+ sheet.replaceSync(rules);
258
+ document.adoptedStyleSheets = [
259
+ ...document.adoptedStyleSheets,
260
+ sheet
261
+ ];
262
+ sheets.set(key, sheet);
263
+ return rules;
264
+ }
265
+ const node = styleTag(key);
266
+ node.textContent = rules;
267
+ sheets.set(key, node);
268
+ return rules;
269
+ }
270
+ function shadowSheet(key, style) {
271
+ const rules = css(':host', style);
272
+ if ('undefined' == typeof CSSStyleSheet || !('replaceSync' in CSSStyleSheet.prototype) || 'undefined' == typeof ShadowRoot || !('adoptedStyleSheets' in ShadowRoot.prototype)) return rules;
273
+ const sheets = registry();
274
+ const existing = sheets.get(key);
275
+ if (existing && 'replaceSync' in existing) {
276
+ existing.replaceSync(rules);
277
+ return existing;
278
+ }
279
+ const sheet = new CSSStyleSheet();
280
+ sheet.replaceSync(rules);
281
+ sheets.set(key, sheet);
282
+ return sheet;
283
+ }
284
+ function eject(key) {
285
+ const sheets = registry();
286
+ const sheet = sheets.get(key);
287
+ if (!sheet) return;
288
+ if ('replaceSync' in sheet) document.adoptedStyleSheets = document.adoptedStyleSheets.filter((s)=>s !== sheet);
289
+ else sheet.remove();
290
+ sheets.delete(key);
140
291
  }
141
292
  function isDarkMode() {
142
293
  return window.matchMedia('(prefers-color-scheme: dark)').matches;
@@ -272,6 +423,37 @@ class logger {
272
423
  });
273
424
  }
274
425
  }
426
+ function _check_private_redeclaration(obj, privateCollection) {
427
+ if (privateCollection.has(obj)) throw new TypeError("Cannot initialize the same private elements twice on an object");
428
+ }
429
+ function _class_apply_descriptor_get(receiver, descriptor) {
430
+ if (descriptor.get) return descriptor.get.call(receiver);
431
+ return descriptor.value;
432
+ }
433
+ function _class_apply_descriptor_set(receiver, descriptor, value) {
434
+ if (descriptor.set) descriptor.set.call(receiver, value);
435
+ else {
436
+ if (!descriptor.writable) throw new TypeError("attempted to set read only private field");
437
+ descriptor.value = value;
438
+ }
439
+ }
440
+ function _class_extract_field_descriptor(receiver, privateMap, action) {
441
+ if (!privateMap.has(receiver)) throw new TypeError("attempted to " + action + " private field on non-instance");
442
+ return privateMap.get(receiver);
443
+ }
444
+ function _class_private_field_get(receiver, privateMap) {
445
+ var descriptor = _class_extract_field_descriptor(receiver, privateMap, "get");
446
+ return _class_apply_descriptor_get(receiver, descriptor);
447
+ }
448
+ function _class_private_field_init(obj, privateMap, value) {
449
+ _check_private_redeclaration(obj, privateMap);
450
+ privateMap.set(obj, value);
451
+ }
452
+ function _class_private_field_set(receiver, privateMap, value) {
453
+ var descriptor = _class_extract_field_descriptor(receiver, privateMap, "set");
454
+ _class_apply_descriptor_set(receiver, descriptor, value);
455
+ return value;
456
+ }
275
457
  function dom_define_property(obj, key, value) {
276
458
  if (key in obj) Object.defineProperty(obj, key, {
277
459
  value: value,
@@ -321,6 +503,14 @@ function onKey(key, cb, verbose = false) {
321
503
  function els(query, verbose = false) {
322
504
  return Array.from(document.querySelectorAll(query)).map((n)=>new dom_el(n, verbose));
323
505
  }
506
+ function registerElement(name, ctor) {
507
+ const existing = customElements.get(name);
508
+ if (existing) {
509
+ if (existing !== ctor) throw new Error(`custom element ${name} is already registered by ${existing.name}`);
510
+ return;
511
+ }
512
+ customElements.define(name, ctor);
513
+ }
324
514
  class dom_el {
325
515
  static query(query, verbose = false) {
326
516
  return new dom_el(query, verbose);
@@ -378,7 +568,11 @@ class dom_el {
378
568
  }
379
569
  html(content) {
380
570
  if (!this.el) throw new Error(`no element from query: ${this.query}`);
381
- this.el.innerHTML = content;
571
+ if ('string' == typeof content) this.el.innerHTML = content;
572
+ else if (content instanceof dom_el) {
573
+ if (content.el) this.el.replaceChildren(content.el);
574
+ } else this.el.replaceChildren(content);
575
+ return this;
382
576
  }
383
577
  src(url) {
384
578
  if (this.el && 'src' in this.el) this.el.src = url;
@@ -405,7 +599,7 @@ class dom_el {
405
599
  else if ('object' == typeof update) {
406
600
  if (!stringify) {
407
601
  for (const [k, v] of Object.entries(update))this.el.style[k] = v;
408
- return;
602
+ return this;
409
603
  }
410
604
  const s = render(update);
411
605
  this.log.debug(`set style: ${this.el.style} -> ${s}`);
@@ -418,6 +612,12 @@ class dom_el {
418
612
  if (!this.el) throw new Error(`no element from query: ${this.query}`);
419
613
  return this.el.classList.contains(className);
420
614
  }
615
+ toggleClass(className) {
616
+ if (!this.el) throw new Error(`no element from query: ${this.query}`);
617
+ if (this.el.classList.contains(className)) this.el.classList.remove(className);
618
+ else this.el.classList.add(className);
619
+ return this;
620
+ }
421
621
  addClass(className) {
422
622
  if (!this.el) throw new Error(`no element from query: ${this.query}`);
423
623
  if ('string' == typeof className) this.el.classList.add(className);
@@ -508,6 +708,82 @@ class dom_el {
508
708
  }
509
709
  }
510
710
  }
711
+ function create(opts, verbose = false) {
712
+ const node = new dom_el(opts, verbose).el;
713
+ if (!node) throw new Error(`could not create element: ${opts.tag ?? opts.query ?? '?'}`);
714
+ return node;
715
+ }
716
+ function registerComponents(components, verbose = false) {
717
+ for (const c of components)c.register(void 0, verbose);
718
+ }
719
+ const dom_sheets = new WeakMap();
720
+ var _mounted = /*#__PURE__*/ new WeakMap(), _root = /*#__PURE__*/ new WeakMap(), _pendingAttrs = /*#__PURE__*/ new WeakMap();
721
+ class component extends HTMLElement {
722
+ get root() {
723
+ return _class_private_field_get(this, _root) ?? this;
724
+ }
725
+ static register(tag, verbose = false) {
726
+ const name = tag ?? this.tag;
727
+ if (!name) throw new Error(`${this.name}: nothing to register as, set \`static tag = 'x-...'\``);
728
+ if (!name.includes('-')) throw new Error(`${this.name}: '${name}' is not a valid custom element name, it needs a hyphen`);
729
+ if (this.styles) if (this.shadow) dom_sheets.set(this, shadowSheet(`shadow:${name}`, this.styles));
730
+ else inject(name, this.styles);
731
+ if (verbose) console.log(`registering ${name}`);
732
+ registerElement(name, this);
733
+ }
734
+ mount() {}
735
+ unmount() {}
736
+ onAttr(_name, _value, _prev) {}
737
+ connectedCallback() {
738
+ if (!_class_private_field_get(this, _mounted)) {
739
+ _class_private_field_set(this, _mounted, true);
740
+ this.mount();
741
+ const queued = _class_private_field_get(this, _pendingAttrs);
742
+ _class_private_field_set(this, _pendingAttrs, []);
743
+ for (const [name, value, prev] of queued)this.onAttr(name, value, prev);
744
+ }
745
+ }
746
+ disconnectedCallback() {
747
+ this.unmount();
748
+ }
749
+ attributeChangedCallback(name, prev, value) {
750
+ if (prev === value) return;
751
+ if (!_class_private_field_get(this, _mounted)) return void _class_private_field_get(this, _pendingAttrs).push([
752
+ name,
753
+ value,
754
+ prev
755
+ ]);
756
+ this.onAttr(name, value, prev);
757
+ }
758
+ constructor(){
759
+ super(), _class_private_field_init(this, _mounted, {
760
+ writable: true,
761
+ value: false
762
+ }), _class_private_field_init(this, _root, {
763
+ writable: true,
764
+ value: null
765
+ }), _class_private_field_init(this, _pendingAttrs, {
766
+ writable: true,
767
+ value: []
768
+ });
769
+ const ctor = this.constructor;
770
+ if (!ctor.shadow) return;
771
+ _class_private_field_set(this, _root, this.attachShadow(ctor.shadow));
772
+ const sheet = dom_sheets.get(ctor);
773
+ if (void 0 === sheet) return;
774
+ if ('string' == typeof sheet) {
775
+ const node = document.createElement('style');
776
+ node.textContent = sheet;
777
+ _class_private_field_get(this, _root).append(node);
778
+ } else _class_private_field_get(this, _root).adoptedStyleSheets = [
779
+ ..._class_private_field_get(this, _root).adoptedStyleSheets,
780
+ sheet
781
+ ];
782
+ }
783
+ }
784
+ dom_define_property(component, "tag", '');
785
+ dom_define_property(component, "styles", null);
786
+ dom_define_property(component, "shadow", null);
511
787
  function interpolate(str, params) {
512
788
  let names = Object.keys(params).map((k)=>`_${k}`);
513
789
  let vals = Object.values(params);
@@ -516,6 +792,9 @@ function interpolate(str, params) {
516
792
  const dom = {
517
793
  el: dom_el,
518
794
  els,
795
+ create,
796
+ component,
797
+ registerElement,
519
798
  ready,
520
799
  on,
521
800
  onKey