@trunkjs/browser-utils
v1.0.56
Published
A small collection of browser-focused, framework-agnostic utilities that make common DOM and timing tasks easier. All utilities are written in TypeScript and ship as ES modules.
Readme
@trunkjs/browser-utils
A small collection of browser-focused, framework-agnostic utilities that make common DOM and timing tasks easier. All utilities are written in TypeScript and ship as ES modules.
Exports:
create_element: Minimal DOM element factory
FormDataAccessor: Dynamic named form values and element/value entries
Debouncer: Debounce helper with optional max-delay
Stopwatch: Lightweight performance timer with lap logging
waitFor, waitForDomContentLoaded, waitForLoad, sleep, waitForAnimationEnd: Promise-based event and timing helpers
LoggingMixin: Lightweight logging mixin for Custom Elements
Installation
Within this monorepo, the package is consumed via path aliases. If you publish or consume it externally, import from the package name:
import { } from '@trunkjs/browser-utils';Quick start
class FormDataAccessor: Read and write named controls
import { FormDataAccessor } from '@trunkjs/browser-utils';
const accessor = new FormDataAccessor(document.querySelector('#profile')!);
accessor.data = { name: 'Erika', topics: ['docs'] };
console.log(accessor.data);
console.log(accessor.formData);
accessor.entries.forEach(({ name, value, element }) => {
console.log(name, value, element);
});The control list is queried again on every access, so later DOM changes are reflected automatically. Use entries
when state such as validated, invalid, or disabled must be applied directly to the original elements.
function create_element(): Create and append an element
import { create_element } from '@trunkjs/browser-utils';
const card = create_element('section', { class: 'card', 'aria-live': 'polite' }, [
create_element('h2', {}, 'Title'),
create_element('p', {}, 'This is a paragraph.'),
create_element('button', { disabled: true }, 'Disabled'),
]);
document.body.appendChild(card);Notes:
- Attributes with value true create boolean attributes (e.g. disabled becomes disabled="").
- Attributes with null or undefined are omitted.
class Debouncer:Debounce input handling
import { Debouncer } from '@trunkjs/browser-utils';
const debouncer = new Debouncer(300, 2000); // 300ms debounce, 2s max delay
const input = document.querySelector('input[type="search"]')!;
input.addEventListener('input', async () => {
await debouncer.wait(); // resets while typing; fires within 2s max
// Trigger the expensive operation here
console.log('Searching for:', input.value);
});Alternatively, execute a function directly:
const saveDebouncer = new Debouncer(500);
window.addEventListener('resize', () => {
saveDebouncer.debounce(() => {
console.log('Resized!');
});
});class Stopwatch: Measure performance with Stopwatch
import { Stopwatch } from '@trunkjs/browser-utils';
const sw = new Stopwatch('Render');
// ... do stuff
sw.lap('after step 1');
// ... do more stuff
sw.lap('after step 2');
console.debug('Total ms:', sw.stop());class LoggingMixin: Enable conditional logging in custom elements (LoggingMixin)
import { LoggingMixin } from '@trunkjs/browser-utils';
class MyEl extends LoggingMixin(HTMLElement) {
connectedCallback() {
// Only prints if the element has a truthy debug attribute
this.log('connected');
// Always prints
this.warn('Heads up');
this.error('Something went wrong?');
}
}
customElements.define('my-el', MyEl);
// <my-el debug></my-el> // enables debug logging
// <my-el debug="false"></my-el> // disables debug logging
// <my-el></my-el> // debug logging disabled by defaultTip:
- If you toggle the debug attribute at runtime, call el.invalidateDebugCache() so the mixin re-evaluates the attribute on the next log/warn/error call.
class EventBindingsMixin: Auto-bind event listeners in custom elements
This mixin handles automatic registration and removal of event listeners in custom elements. It uses the @Listen decorator to bind class methods to events on specified targets.
It will register the events in connectedCallback and remove them in disconnectedCallback.
import { EventBindingsMixin } from '@trunkjs/browser-utils';
import { Listen } from '@trunkjs/browser-utils';
class MyEl extends EventBindingsMixin(HTMLElement) {
@Listen('click', { target: 'this' }) // listens to clicks on the element itself
onClick(event: MouseEvent) {
this.log('Element clicked', event);
}
@Listen('resize', { target: 'window' }) // listens to window resize events
onResize(event: UIEvent) {
this.log('Window resized', event);
}
}Target options:
- 'host': the custom element itself
- 'window': the global window object
- 'document': the global document object
- 'shadowRoot': the shadow root of the element (if any)
(element) => EventTarget: a function returning any EventTarget (e.g. another DOM element)
async function waitForXYZ: Promise-based event helpers
import { waitFor, waitForDomContentLoaded, waitForLoad, sleep, waitForAnimationEnd } from '@trunkjs/browser-utils';
await waitForDomContentLoaded(); // resolves when DOM is ready
await waitForLoad(); // resolves when all resources are loaded
// Wait for a specific event
const clickEvent = await waitFor<MouseEvent>(document.getElementById('btn')!, 'click');
// Pause execution
await sleep(250);
// Wait for CSS animation to finish
await waitForAnimationEnd(document.querySelector('.animate')!);BreakPointMixin: Responsive behavior for custom elements
Evaluates the css variable --breakpoint and adds corresponding and adds a desktop attribute to the host element when the breakpoint is above the defined threshold.
