DOM
import { createElement, selectorFor } from '@studiometa/js-toolkit/utils';createElement
createElement(tag?, children?): HTMLElement
createElement(tag?, attributes?, children?): HTMLElementimport { createElement } from '@studiometa/js-toolkit/utils';
createElement('div');
createElement('p', 'Hello');
createElement('ul', [createElement('li', 'One'), createElement('li', 'Two')]);
createElement('button', { class: 'btn', data: { component: 'Action' } }, 'Send');Parameters
tag— defaults to'div', and the return type follows it:createElement('input')gives anHTMLInputElement.attributes— plain attributes, plus adataobject whose keys becomedata-*.children— a string, aNode, or an array of either.
The data key is why this exists rather than three lines of document.createElement: building an element that carries data-component and a few data-option-* is the common case, and spelling each setAttribute() out loses the shape.
selectorFor
selectorFor(name: string): stringimport { selectorFor } from '@studiometa/js-toolkit/utils';
selectorFor('Dialog');The CSS selector that matches every element declaring a component name — including the responsive data-component:<breakpoint> spellings.
It is the one place that writes the name-to-selector contract, which is why it is public: a consumer that queries for components must match what the registry matches, and a hand-written [data-component="X"] misses the scoped declarations.
It over-matches on purpose
A responsive declaration that is not active still matches the selector. That is why the four instance lookups read the element's instance map afterwards: a matching element with no instance is skipped, and that is the whole narrowing.