npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@trunkjs/browser-utils

v1.0.22

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

  • 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

  • Event Bindings for WebComponents

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

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 default

Tip:

  • 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.

API Reference