defaultPlugins = ({
type: {
before(item, options) {
if(item.type == null) return item;
const {node, type} = item;
if(item.node) throw Error(`Cannot create type "${type}", node is already set\nItem: ${dumpJSON(item)}`);
if(!options.types[type]) throw Error(`Type "${type}" is not defined\nItem: ${dumpJSON(item)}`);
return options.types[item.type](item);
}
},
id: {
after(collection, {node}) {
if(node instanceof Element && !node.hasAttribute('id') && node.hasAttribute('name')) {
node.setAttribute('id', DOM.uid(node.getAttribute('name')).id);
}
return collection;
}
},
data: {
after(collection, item) {
if(item.data != null) {
requireElement(item, 'data');
Object.assign(item.node.dataset, item.data);
}
return collection;
}
},
label: {
after(collection, item) {
if(item.label != null) {
const {label, node} = item;
const l = html`<label>${label instanceof Node ? label : DOM.text(label)}`;
if(node instanceof Element && node.hasAttribute('id')) {
l.setAttribute('for', node.getAttribute('id'));
}
node.parentNode.insertBefore(l, node);
}
return collection;
}
},
// Addds and links an output element.
output: {
after(collection, item) {
if(item.output == null) return collection;
requireElement(item, 'output');
const {output: fn, node} = item, o = DOM.element('output');
if(node.hasAttribute('id')) {
o.setAttribute('for', node.getAttribute('id'));
}
o.value = fn(node.value);
node.addEventListener('input', e => {
if(e.target === node) o.value = fn(node.value);
});
return fragment(html`${collection} ${o}`);
}
},
submit: {
after(collection, item) {
if(item.submit != null) {
requireElement(item, 'submit');
// TODO
}
return collection;
}
},
// TODO: Alternative solution?
rearrange: {
after(collection, item) {
if(item.rearrange != null) {
const {node, rearrange} = item;
const nodes = new Set;
rearrange.forEach(selector => {
if(selector instanceof Node) return nodes.set(selector);
for(let n of node.children) {
if(n.matches(selector) && !nodes.has(n)) return nodes.set(n);
}
// TODO
});
}
return collection;
}
},
wrap: {
before(item) {
if(item.wrapChildren != null && item.children) {
for(let c of item.children) c.wrap = item.wrapChildren;
}
return item;
},
after(collection, item) {
return item.wrap == null ? collection : html`<${item.wrap}>${collection}`;
}
},
theme: {
after(collection, item, {themes = {}}) {
if(item.theme != null) {
requireElement(item, 'theme');
const {theme, node} = item;
if(!themes[item.theme]) throw TypeError(`Theme "${item.theme}" is not defined`);
const id = node.dataset.themeScope = DOM.uid(`theme-${theme}`).id;
const scope = `[data-theme-scope="${id}"]`;
const css = themes[theme].replace(/:scope\b/g, scope);
collection.appendChild(html`<style>${css}`);
}
return collection;
}
}
})