@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/dom.d.ts +96 -5
- package/dist/dom.js +281 -5
- package/dist/index.js +293 -14
- package/dist/ls.js +269 -4
- package/dist/qr.js +269 -4
- package/dist/style.d.ts +50 -1
- package/dist/style.js +156 -12
- package/dist/style.test.d.ts +1 -0
- package/package.json +1 -1
package/dist/dom.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as style from './style';
|
|
1
2
|
import { logger } from './utils';
|
|
2
3
|
/****************
|
|
3
4
|
* DOM *
|
|
@@ -17,8 +18,14 @@ export declare function onKey(key: string, cb: (ev: {
|
|
|
17
18
|
shift: boolean;
|
|
18
19
|
}) => void, verbose?: boolean): () => void;
|
|
19
20
|
export declare function els(query: string, verbose?: boolean): el[];
|
|
21
|
+
/**
|
|
22
|
+
* Define a custom element. Defining the same name with the same class again is a
|
|
23
|
+
* no-op rather than a `NotSupportedError`, so a double import or an HMR reload
|
|
24
|
+
* does not blow up; a *different* class on a taken name is still an error.
|
|
25
|
+
*/
|
|
26
|
+
export declare function registerElement(name: string, ctor: CustomElementConstructor): void;
|
|
20
27
|
/*** element ***/
|
|
21
|
-
type elOpts = {
|
|
28
|
+
export type elOpts = {
|
|
22
29
|
element?: HTMLElement;
|
|
23
30
|
query?: string;
|
|
24
31
|
tag?: string;
|
|
@@ -40,7 +47,7 @@ export declare class el {
|
|
|
40
47
|
constructor(opts: HTMLElement | string | elOpts, verbose?: boolean);
|
|
41
48
|
static query(query: string, verbose?: boolean): el;
|
|
42
49
|
/*** dom manipulation ***/
|
|
43
|
-
value(update?: string): string |
|
|
50
|
+
value(update?: string): string | this;
|
|
44
51
|
parent(parent: HTMLElement | el): this;
|
|
45
52
|
append(ch: HTMLElement | el | string): this;
|
|
46
53
|
appendChild(ch: HTMLElement | el): this;
|
|
@@ -51,22 +58,103 @@ export declare class el {
|
|
|
51
58
|
content(content: any, { text }?: {
|
|
52
59
|
text?: boolean;
|
|
53
60
|
}): this;
|
|
54
|
-
html(content: string):
|
|
61
|
+
html(content: string | HTMLElement | el): this;
|
|
55
62
|
src(url: string): this;
|
|
56
63
|
attrs(attrs: Object): this;
|
|
57
64
|
attr(key: string, val: string): this;
|
|
58
65
|
removeAttr(key: string): this;
|
|
59
66
|
/*** Style ***/
|
|
60
|
-
style(update: Object | string, stringify?: boolean): this
|
|
67
|
+
style(update: Object | string, stringify?: boolean): this;
|
|
61
68
|
hasClass(className: string): boolean;
|
|
69
|
+
toggleClass(className: string): this;
|
|
62
70
|
addClass(className: string | string[]): this;
|
|
63
71
|
removeClass(className: string | string[]): this;
|
|
64
|
-
/*** Templates ***/
|
|
65
72
|
/*** Events ***/
|
|
66
73
|
on(event: string, cb: (ev: Event) => void, options?: AddEventListenerOptions | boolean): this;
|
|
67
74
|
listen(event: string, cb: (ev: Event) => void, options?: AddEventListenerOptions | boolean): this;
|
|
68
75
|
removeListeners(event: string): this;
|
|
69
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Create an element and return the node itself, not an `el` wrapper. Takes the
|
|
79
|
+
* same options as `el`, so a custom element comes back ready to talk to:
|
|
80
|
+
*
|
|
81
|
+
* const form = create({ tag: 'x-search-form', parent: '#query-form' })
|
|
82
|
+
* form.onSubmit(...) // its own methods, no `.el` hop
|
|
83
|
+
*
|
|
84
|
+
* Wrap it later with `new el(node)` if you want the chainable helpers.
|
|
85
|
+
*/
|
|
86
|
+
export declare function create<T extends HTMLElement = HTMLElement>(opts: elOpts, verbose?: boolean): T;
|
|
87
|
+
/*** component ***/
|
|
88
|
+
export declare function registerComponents(components: (typeof component)[], verbose?: boolean): void;
|
|
89
|
+
export declare class component extends HTMLElement {
|
|
90
|
+
#private;
|
|
91
|
+
/** the name to register as; must contain a hyphen */
|
|
92
|
+
static tag: string;
|
|
93
|
+
/**
|
|
94
|
+
* Injected once at `register()`, scoped to the tag. Written *relative* to the
|
|
95
|
+
* component — no tag selector of its own — so it always matches whatever name
|
|
96
|
+
* the class actually registered under.
|
|
97
|
+
*/
|
|
98
|
+
static styles: style.declarations | null;
|
|
99
|
+
/**
|
|
100
|
+
* Opt in to a shadow root: `static shadow = { mode: 'open' }`.
|
|
101
|
+
*
|
|
102
|
+
* Without it a component's `styles` are injected at document level and
|
|
103
|
+
* compile to plain descendant selectors, so an outer component's `ul` or
|
|
104
|
+
* `.meta` rule reaches an inner component's markup — and only has to name a
|
|
105
|
+
* property the inner rule leaves unset to take effect. A shadow root ends
|
|
106
|
+
* that by construction, in both directions.
|
|
107
|
+
*
|
|
108
|
+
* What changes for the component: put children in `this.root`, not `this`.
|
|
109
|
+
* Two things to know before turning it on —
|
|
110
|
+
*
|
|
111
|
+
* - light-dom children are not rendered unless the root has a `<slot>`, so a
|
|
112
|
+
* component that takes `content` needs one
|
|
113
|
+
* - a nested custom element loses its document styles inside the root, so
|
|
114
|
+
* anything rendered in here has to be shadowed too
|
|
115
|
+
* DOCS: https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM
|
|
116
|
+
*/
|
|
117
|
+
static shadow: ShadowRootInit | null;
|
|
118
|
+
constructor();
|
|
119
|
+
/**
|
|
120
|
+
* Where this component's children belong: its shadow root when it has one,
|
|
121
|
+
* otherwise the element itself. Use it instead of `this` for `append`,
|
|
122
|
+
* `replaceChildren` and `querySelector`, and the component works either way.
|
|
123
|
+
*/
|
|
124
|
+
get root(): ShadowRoot | this;
|
|
125
|
+
/**
|
|
126
|
+
* Inject this component's styles and define it. Idempotent, so calling it
|
|
127
|
+
* twice (or after an HMR reload) is harmless.
|
|
128
|
+
* @param tag - overrides `static tag`
|
|
129
|
+
*/
|
|
130
|
+
static register(tag?: string, verbose?: boolean): void;
|
|
131
|
+
/**
|
|
132
|
+
* Called once, the first time the element is connected. Build the subtree and
|
|
133
|
+
* wire listeners here — a custom element cannot give itself children before
|
|
134
|
+
* it is connected, and `connectedCallback` runs again on every re-insertion.
|
|
135
|
+
*/
|
|
136
|
+
mount(): void;
|
|
137
|
+
/**
|
|
138
|
+
* Called every time the element is disconnected. Listeners on this element
|
|
139
|
+
* and on children it owns go away with it; undo document/window listeners
|
|
140
|
+
* here, using the removers `on()` and `onKey()` hand back.
|
|
141
|
+
*/
|
|
142
|
+
unmount(): void;
|
|
143
|
+
/**
|
|
144
|
+
* Called for every change to an attribute named in `static observedAttributes`,
|
|
145
|
+
* and never before `mount()` — changes that arrive earlier (anything set at
|
|
146
|
+
* creation or parse time, which the platform reports *before*
|
|
147
|
+
* `connectedCallback`) are held and delivered in order right after mount.
|
|
148
|
+
*
|
|
149
|
+
* Attributes are strings. For structured data use a property with a setter
|
|
150
|
+
* that re-renders; an object put through `setAttribute` becomes
|
|
151
|
+
* "[object Object]".
|
|
152
|
+
*/
|
|
153
|
+
onAttr(_name: string, _value: string | null, _prev: string | null): void;
|
|
154
|
+
connectedCallback(): void;
|
|
155
|
+
disconnectedCallback(): void;
|
|
156
|
+
attributeChangedCallback(name: string, prev: string | null, value: string | null): void;
|
|
157
|
+
}
|
|
70
158
|
/**
|
|
71
159
|
* Get a template from a string
|
|
72
160
|
* https://stackoverflow.com/a/41015840
|
|
@@ -78,6 +166,9 @@ export declare function interpolate(str: string, params: Object): string;
|
|
|
78
166
|
declare const _default: {
|
|
79
167
|
el: typeof el;
|
|
80
168
|
els: typeof els;
|
|
169
|
+
create: typeof create;
|
|
170
|
+
component: typeof component;
|
|
171
|
+
registerElement: typeof registerElement;
|
|
81
172
|
ready: typeof ready;
|
|
82
173
|
on: typeof on;
|
|
83
174
|
onKey: typeof onKey;
|
package/dist/dom.js
CHANGED
|
@@ -1,11 +1,159 @@
|
|
|
1
|
-
function
|
|
1
|
+
function toKebab(str) {
|
|
2
2
|
return str.replace(/[A-Z]+(?![a-z])|[A-Z]/g, (s, ofs)=>(ofs ? '-' : '') + s.toLowerCase());
|
|
3
3
|
}
|
|
4
4
|
function render(style) {
|
|
5
5
|
let s = '';
|
|
6
|
-
Object.entries(style).forEach(([k, v])=>s += `${
|
|
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 hostCompound(selector) {
|
|
31
|
+
if (!selector.startsWith(':host')) return selector;
|
|
32
|
+
let i = 5;
|
|
33
|
+
let inner = '';
|
|
34
|
+
if ('(' === selector[i]) {
|
|
35
|
+
const open = i;
|
|
36
|
+
let depth = 0;
|
|
37
|
+
let quote = '';
|
|
38
|
+
while(i < selector.length){
|
|
39
|
+
const ch = selector[i];
|
|
40
|
+
if (quote) {
|
|
41
|
+
if (ch === quote) quote = '';
|
|
42
|
+
} else if ('"' === ch || "'" === ch) quote = ch;
|
|
43
|
+
else if ('(' === ch) depth++;
|
|
44
|
+
else if (')' === ch) {
|
|
45
|
+
depth--;
|
|
46
|
+
if (0 === depth) {
|
|
47
|
+
i++;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
i++;
|
|
52
|
+
}
|
|
53
|
+
inner = selector.slice(open + 1, i - 1);
|
|
54
|
+
}
|
|
55
|
+
const start = i;
|
|
56
|
+
let depth = 0;
|
|
57
|
+
let quote = '';
|
|
58
|
+
while(i < selector.length){
|
|
59
|
+
const ch = selector[i];
|
|
60
|
+
if (quote) {
|
|
61
|
+
if (ch === quote) quote = '';
|
|
62
|
+
} else if ('"' === ch || "'" === ch) quote = ch;
|
|
63
|
+
else if (0 === depth && (' ' === ch || '>' === ch || '+' === ch || '~' === ch)) break;
|
|
64
|
+
else if (0 === depth && ':' === ch && ':' === selector[i + 1]) break;
|
|
65
|
+
else if ('(' === ch || '[' === ch) depth++;
|
|
66
|
+
else if (')' === ch || ']' === ch) depth--;
|
|
67
|
+
i++;
|
|
68
|
+
}
|
|
69
|
+
const compound = selector.slice(start, i);
|
|
70
|
+
if (!compound) return selector;
|
|
71
|
+
return `:host(${inner}${compound})${selector.slice(i)}`;
|
|
72
|
+
}
|
|
73
|
+
function resolve(parents, selector) {
|
|
74
|
+
const out = [];
|
|
75
|
+
for (const parent of parents)for (const part of splitSelectors(selector))out.push(hostCompound(part.includes('&') ? part.replaceAll('&', parent) : `${parent} ${part}`));
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
function compile(parents, decls, indent = '') {
|
|
79
|
+
const blocks = [];
|
|
80
|
+
const props = [];
|
|
81
|
+
const nested = [];
|
|
82
|
+
for (const [k, v] of Object.entries(decls))if (null !== v && 'object' == typeof v) nested.push([
|
|
83
|
+
k,
|
|
84
|
+
v
|
|
85
|
+
]);
|
|
86
|
+
else props.push(`${indent} ${toKebab(k)}: ${v};`);
|
|
87
|
+
if (props.length) blocks.push(`${indent}${parents.join(', ')} {\n${props.join('\n')}\n${indent}}`);
|
|
88
|
+
for (const [selector, block] of nested){
|
|
89
|
+
if (selector.startsWith('@')) {
|
|
90
|
+
const inner = selector.startsWith('@keyframes') ? Object.entries(block).flatMap(([step, d])=>null !== d && 'object' == typeof d ? compile([
|
|
91
|
+
step
|
|
92
|
+
], d, `${indent} `) : []) : compile(parents, block, `${indent} `);
|
|
93
|
+
if (inner.length) blocks.push(`${indent}${selector} {\n${inner.join('\n')}\n${indent}}`);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
blocks.push(...compile(resolve(parents, selector), block, indent));
|
|
97
|
+
}
|
|
98
|
+
return blocks;
|
|
99
|
+
}
|
|
100
|
+
function css(selector, style) {
|
|
101
|
+
return compile(splitSelectors(selector), style).join('\n');
|
|
102
|
+
}
|
|
103
|
+
function registry() {
|
|
104
|
+
const doc = document;
|
|
105
|
+
if (!doc.__corvidSheets) doc.__corvidSheets = new Map();
|
|
106
|
+
return doc.__corvidSheets;
|
|
107
|
+
}
|
|
108
|
+
function adoptable() {
|
|
109
|
+
return 'undefined' != typeof CSSStyleSheet && 'replaceSync' in CSSStyleSheet.prototype && 'undefined' != typeof Document && 'adoptedStyleSheets' in Document.prototype;
|
|
110
|
+
}
|
|
111
|
+
function styleTag(key) {
|
|
112
|
+
const tagged = Array.from(document.head.querySelectorAll('style[data-corvid]'));
|
|
113
|
+
for (const node of tagged)if (node.dataset.corvid === key) return node;
|
|
114
|
+
const node = document.createElement('style');
|
|
115
|
+
node.dataset.corvid = key;
|
|
116
|
+
document.head.appendChild(node);
|
|
117
|
+
return node;
|
|
118
|
+
}
|
|
119
|
+
function inject(selector, style, { key = selector } = {}) {
|
|
120
|
+
const rules = css(selector, style);
|
|
121
|
+
const sheets = registry();
|
|
122
|
+
const existing = sheets.get(key);
|
|
123
|
+
if (existing) {
|
|
124
|
+
if ('replaceSync' in existing) existing.replaceSync(rules);
|
|
125
|
+
else existing.textContent = rules;
|
|
126
|
+
return rules;
|
|
127
|
+
}
|
|
128
|
+
if (adoptable()) {
|
|
129
|
+
const sheet = new CSSStyleSheet();
|
|
130
|
+
sheet.replaceSync(rules);
|
|
131
|
+
document.adoptedStyleSheets = [
|
|
132
|
+
...document.adoptedStyleSheets,
|
|
133
|
+
sheet
|
|
134
|
+
];
|
|
135
|
+
sheets.set(key, sheet);
|
|
136
|
+
return rules;
|
|
137
|
+
}
|
|
138
|
+
const node = styleTag(key);
|
|
139
|
+
node.textContent = rules;
|
|
140
|
+
sheets.set(key, node);
|
|
141
|
+
return rules;
|
|
142
|
+
}
|
|
143
|
+
function shadowSheet(key, style) {
|
|
144
|
+
const rules = css(':host', style);
|
|
145
|
+
if ('undefined' == typeof CSSStyleSheet || !('replaceSync' in CSSStyleSheet.prototype) || 'undefined' == typeof ShadowRoot || !('adoptedStyleSheets' in ShadowRoot.prototype)) return rules;
|
|
146
|
+
const sheets = registry();
|
|
147
|
+
const existing = sheets.get(key);
|
|
148
|
+
if (existing && 'replaceSync' in existing) {
|
|
149
|
+
existing.replaceSync(rules);
|
|
150
|
+
return existing;
|
|
151
|
+
}
|
|
152
|
+
const sheet = new CSSStyleSheet();
|
|
153
|
+
sheet.replaceSync(rules);
|
|
154
|
+
sheets.set(key, sheet);
|
|
155
|
+
return sheet;
|
|
156
|
+
}
|
|
9
157
|
function _define_property(obj, key, value) {
|
|
10
158
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
11
159
|
value: value,
|
|
@@ -61,6 +209,37 @@ class logger {
|
|
|
61
209
|
});
|
|
62
210
|
}
|
|
63
211
|
}
|
|
212
|
+
function _check_private_redeclaration(obj, privateCollection) {
|
|
213
|
+
if (privateCollection.has(obj)) throw new TypeError("Cannot initialize the same private elements twice on an object");
|
|
214
|
+
}
|
|
215
|
+
function _class_apply_descriptor_get(receiver, descriptor) {
|
|
216
|
+
if (descriptor.get) return descriptor.get.call(receiver);
|
|
217
|
+
return descriptor.value;
|
|
218
|
+
}
|
|
219
|
+
function _class_apply_descriptor_set(receiver, descriptor, value) {
|
|
220
|
+
if (descriptor.set) descriptor.set.call(receiver, value);
|
|
221
|
+
else {
|
|
222
|
+
if (!descriptor.writable) throw new TypeError("attempted to set read only private field");
|
|
223
|
+
descriptor.value = value;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function _class_extract_field_descriptor(receiver, privateMap, action) {
|
|
227
|
+
if (!privateMap.has(receiver)) throw new TypeError("attempted to " + action + " private field on non-instance");
|
|
228
|
+
return privateMap.get(receiver);
|
|
229
|
+
}
|
|
230
|
+
function _class_private_field_get(receiver, privateMap) {
|
|
231
|
+
var descriptor = _class_extract_field_descriptor(receiver, privateMap, "get");
|
|
232
|
+
return _class_apply_descriptor_get(receiver, descriptor);
|
|
233
|
+
}
|
|
234
|
+
function _class_private_field_init(obj, privateMap, value) {
|
|
235
|
+
_check_private_redeclaration(obj, privateMap);
|
|
236
|
+
privateMap.set(obj, value);
|
|
237
|
+
}
|
|
238
|
+
function _class_private_field_set(receiver, privateMap, value) {
|
|
239
|
+
var descriptor = _class_extract_field_descriptor(receiver, privateMap, "set");
|
|
240
|
+
_class_apply_descriptor_set(receiver, descriptor, value);
|
|
241
|
+
return value;
|
|
242
|
+
}
|
|
64
243
|
function dom_define_property(obj, key, value) {
|
|
65
244
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
66
245
|
value: value,
|
|
@@ -110,6 +289,14 @@ function onKey(key, cb, verbose = false) {
|
|
|
110
289
|
function els(query, verbose = false) {
|
|
111
290
|
return Array.from(document.querySelectorAll(query)).map((n)=>new dom_el(n, verbose));
|
|
112
291
|
}
|
|
292
|
+
function registerElement(name, ctor) {
|
|
293
|
+
const existing = customElements.get(name);
|
|
294
|
+
if (existing) {
|
|
295
|
+
if (existing !== ctor) throw new Error(`custom element ${name} is already registered by ${existing.name}`);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
customElements.define(name, ctor);
|
|
299
|
+
}
|
|
113
300
|
class dom_el {
|
|
114
301
|
static query(query, verbose = false) {
|
|
115
302
|
return new dom_el(query, verbose);
|
|
@@ -167,7 +354,11 @@ class dom_el {
|
|
|
167
354
|
}
|
|
168
355
|
html(content) {
|
|
169
356
|
if (!this.el) throw new Error(`no element from query: ${this.query}`);
|
|
170
|
-
this.el.innerHTML = content;
|
|
357
|
+
if ('string' == typeof content) this.el.innerHTML = content;
|
|
358
|
+
else if (content instanceof dom_el) {
|
|
359
|
+
if (content.el) this.el.replaceChildren(content.el);
|
|
360
|
+
} else this.el.replaceChildren(content);
|
|
361
|
+
return this;
|
|
171
362
|
}
|
|
172
363
|
src(url) {
|
|
173
364
|
if (this.el && 'src' in this.el) this.el.src = url;
|
|
@@ -194,7 +385,7 @@ class dom_el {
|
|
|
194
385
|
else if ('object' == typeof update) {
|
|
195
386
|
if (!stringify) {
|
|
196
387
|
for (const [k, v] of Object.entries(update))this.el.style[k] = v;
|
|
197
|
-
return;
|
|
388
|
+
return this;
|
|
198
389
|
}
|
|
199
390
|
const s = render(update);
|
|
200
391
|
this.log.debug(`set style: ${this.el.style} -> ${s}`);
|
|
@@ -207,6 +398,12 @@ class dom_el {
|
|
|
207
398
|
if (!this.el) throw new Error(`no element from query: ${this.query}`);
|
|
208
399
|
return this.el.classList.contains(className);
|
|
209
400
|
}
|
|
401
|
+
toggleClass(className) {
|
|
402
|
+
if (!this.el) throw new Error(`no element from query: ${this.query}`);
|
|
403
|
+
if (this.el.classList.contains(className)) this.el.classList.remove(className);
|
|
404
|
+
else this.el.classList.add(className);
|
|
405
|
+
return this;
|
|
406
|
+
}
|
|
210
407
|
addClass(className) {
|
|
211
408
|
if (!this.el) throw new Error(`no element from query: ${this.query}`);
|
|
212
409
|
if ('string' == typeof className) this.el.classList.add(className);
|
|
@@ -297,6 +494,82 @@ class dom_el {
|
|
|
297
494
|
}
|
|
298
495
|
}
|
|
299
496
|
}
|
|
497
|
+
function create(opts, verbose = false) {
|
|
498
|
+
const node = new dom_el(opts, verbose).el;
|
|
499
|
+
if (!node) throw new Error(`could not create element: ${opts.tag ?? opts.query ?? '?'}`);
|
|
500
|
+
return node;
|
|
501
|
+
}
|
|
502
|
+
function registerComponents(components, verbose = false) {
|
|
503
|
+
for (const c of components)c.register(void 0, verbose);
|
|
504
|
+
}
|
|
505
|
+
const dom_sheets = new WeakMap();
|
|
506
|
+
var _mounted = /*#__PURE__*/ new WeakMap(), _root = /*#__PURE__*/ new WeakMap(), _pendingAttrs = /*#__PURE__*/ new WeakMap();
|
|
507
|
+
class component extends HTMLElement {
|
|
508
|
+
get root() {
|
|
509
|
+
return _class_private_field_get(this, _root) ?? this;
|
|
510
|
+
}
|
|
511
|
+
static register(tag, verbose = false) {
|
|
512
|
+
const name = tag ?? this.tag;
|
|
513
|
+
if (!name) throw new Error(`${this.name}: nothing to register as, set \`static tag = 'x-...'\``);
|
|
514
|
+
if (!name.includes('-')) throw new Error(`${this.name}: '${name}' is not a valid custom element name, it needs a hyphen`);
|
|
515
|
+
if (this.styles) if (this.shadow) dom_sheets.set(this, shadowSheet(`shadow:${name}`, this.styles));
|
|
516
|
+
else inject(name, this.styles);
|
|
517
|
+
if (verbose) console.log(`registering ${name}`);
|
|
518
|
+
registerElement(name, this);
|
|
519
|
+
}
|
|
520
|
+
mount() {}
|
|
521
|
+
unmount() {}
|
|
522
|
+
onAttr(_name, _value, _prev) {}
|
|
523
|
+
connectedCallback() {
|
|
524
|
+
if (!_class_private_field_get(this, _mounted)) {
|
|
525
|
+
_class_private_field_set(this, _mounted, true);
|
|
526
|
+
this.mount();
|
|
527
|
+
const queued = _class_private_field_get(this, _pendingAttrs);
|
|
528
|
+
_class_private_field_set(this, _pendingAttrs, []);
|
|
529
|
+
for (const [name, value, prev] of queued)this.onAttr(name, value, prev);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
disconnectedCallback() {
|
|
533
|
+
this.unmount();
|
|
534
|
+
}
|
|
535
|
+
attributeChangedCallback(name, prev, value) {
|
|
536
|
+
if (prev === value) return;
|
|
537
|
+
if (!_class_private_field_get(this, _mounted)) return void _class_private_field_get(this, _pendingAttrs).push([
|
|
538
|
+
name,
|
|
539
|
+
value,
|
|
540
|
+
prev
|
|
541
|
+
]);
|
|
542
|
+
this.onAttr(name, value, prev);
|
|
543
|
+
}
|
|
544
|
+
constructor(){
|
|
545
|
+
super(), _class_private_field_init(this, _mounted, {
|
|
546
|
+
writable: true,
|
|
547
|
+
value: false
|
|
548
|
+
}), _class_private_field_init(this, _root, {
|
|
549
|
+
writable: true,
|
|
550
|
+
value: null
|
|
551
|
+
}), _class_private_field_init(this, _pendingAttrs, {
|
|
552
|
+
writable: true,
|
|
553
|
+
value: []
|
|
554
|
+
});
|
|
555
|
+
const ctor = this.constructor;
|
|
556
|
+
if (!ctor.shadow) return;
|
|
557
|
+
_class_private_field_set(this, _root, this.attachShadow(ctor.shadow));
|
|
558
|
+
const sheet = dom_sheets.get(ctor);
|
|
559
|
+
if (void 0 === sheet) return;
|
|
560
|
+
if ('string' == typeof sheet) {
|
|
561
|
+
const node = document.createElement('style');
|
|
562
|
+
node.textContent = sheet;
|
|
563
|
+
_class_private_field_get(this, _root).append(node);
|
|
564
|
+
} else _class_private_field_get(this, _root).adoptedStyleSheets = [
|
|
565
|
+
..._class_private_field_get(this, _root).adoptedStyleSheets,
|
|
566
|
+
sheet
|
|
567
|
+
];
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
dom_define_property(component, "tag", '');
|
|
571
|
+
dom_define_property(component, "styles", null);
|
|
572
|
+
dom_define_property(component, "shadow", null);
|
|
300
573
|
function interpolate(str, params) {
|
|
301
574
|
let names = Object.keys(params).map((k)=>`_${k}`);
|
|
302
575
|
let vals = Object.values(params);
|
|
@@ -305,8 +578,11 @@ function interpolate(str, params) {
|
|
|
305
578
|
const dom = {
|
|
306
579
|
el: dom_el,
|
|
307
580
|
els,
|
|
581
|
+
create,
|
|
582
|
+
component,
|
|
583
|
+
registerElement,
|
|
308
584
|
ready,
|
|
309
585
|
on,
|
|
310
586
|
onKey
|
|
311
587
|
};
|
|
312
|
-
export { dom as default, dom_el as el, els, interpolate, on, onBlur, onFocus, onKey, ready };
|
|
588
|
+
export { component, create, dom as default, dom_el as el, els, interpolate, on, onBlur, onFocus, onKey, ready, registerComponents, registerElement };
|