@webreflection/element
v0.3.2
Published
A minimalistic DOM element creation library.
Maintainers
Readme
@webreflection/element
Social Media Photo by James Owen on Unsplash
A minimalistic DOM element creation library.
Installation
npm i @webreflection/elementUsage
import element from '@webreflection/element';The default export is a function that accepts a tag, an optional options object, and any number of childNodes to append:
(tag: string | Node, options?: object, ...childNodes: (Node | string)[])The tag
- If it is already an Element, the provided options enrich that element as described below.
- If it is a
stringand does not start with<, a new Element with that name is created.- If it starts with
svg:(followed by its name), or thetagvalue issvgitself, an SVGElement is created. - In every other case, an HTMLElement or CustomElement with that name is created. If
options.isexists, a built-in custom element extension is created.
- If it starts with
- If it is a
stringand starts with<, the rest of the string is used withdocument.querySelector. If no element is found,nullis returned.
The options
Each option key / value pair enriches the created or retrieved element in a library-friendly way.
The key
- If
keyischildrenand no extra arguments are passed andoptions.childrenis an array, it is compatible with latest React transformed JSX expectations and...childrenwill reflect that list of entries. - If
key in elementisfalse:- aria and data attach
aria-prefixed attributes (withroleas an exception) or update the elementdataset. - class, html, and text map to
className,innerHTML, andtextContent, so these properties can be set with shorter semantic names. - @type is treated as listener intent. If its value is an array, it is passed to
element.addEventListener(key.slice(1), ...value)so listener options can be provided. Otherwise, the listener is added without options. - ?name is treated as boolean attribute intent and, like @type, the first character is removed from the key.
- aria and data attach
- If
key in elementistrue:- classList adds all classes via
element.classList.add(...value). - style content is set via
element.style.cssText = valueor, for an SVG element, viaelement.setAttribute('style', value). - Everything else, including on... handlers, is attached directly via
element[key] = value.
- classList adds all classes via
The value
If key in element is false, the behavior is inferred by the value:
- A
booleanvalue that is not known in the element is handled viaelement.toggleAttribute(key, value). - A
functionor anobjectwithhandleEventis handled viaelement.addEventListener(key, value). - An
objectwithouthandleEventis serialized as JSON and set viaelement.setAttribute(key, JSON.stringify(value)). nullandundefinedare ignored.- Everything else is added via
element.setAttribute(key, value).
Read the example for a more complete look at how these features work together.
Example - Live Demo
// https://cdn.jsdelivr.net/npm/@webreflection/element/index.min.js for best compression
import element from 'https://esm.run/@webreflection/element';
// Direct node reference or `< css-selector` to enrich, i.e.:
// element(document.body, ...) or ...
element(
'< body',
{
// override body.style.cssText = ...
style: 'text-align: center',
// classList.add('some', 'container')
classList: ['some', 'container'],
// a custom listener as object.handleEvent pattern
['custom:event']: {
count: 0,
handleEvent({ type, currentTarget }) {
console.log(++this.count, type, currentTarget);
},
},
// listener with an extra { once: true } option
['@click']: [
({ type, currentTarget }) => {
console.log(type, currentTarget);
currentTarget.dispatchEvent(new Event('custom:event'));
},
{ once: true },
],
},
// body children / childNodes
element('h1', {
// className
class: 'name',
// textContent
text: '@webreflection/element',
style: 'color: purple',
// role="heading" aria-level="1"
aria: {
role: 'heading',
level: 1,
},
// dataset.test = 'ok'
data: {
test: 'ok',
},
// serialized as `json` attribute
json: { a: 1, b: 2 },
// direct listener
onclick: ({ type, currentTarget }) => {
console.log(type, currentTarget);
},
}),
element(
'svg',
{
width: 100,
height: 100,
},
// svg children / childNodes
element('svg:circle', {
cx: 50,
cy: 50,
r: 50,
fill: 'violet',
})
),
element('p', {
// innerHTML
html: 'made with ❤️ for the <strong>Web</strong>',
})
);