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

@magik_io/mote

v1.6.10

Published

A lightweight, TypeScript-first DOM manipulation library with a jQuery-like API for modern web applications. Small, self-contained, and reusable pieces of code that can be composed to build larger applications.

Readme

Mote

So mote it be

A lightweight, TypeScript-first DOM manipulation library that provides a jQuery-like API for modern web applications. The name "mote" refers to small, self-contained, reusable pieces of code that can be composed to build larger applications.

Version License

Features

  • TypeScript-First: Fully typed with generic support and strict mode options
  • Fluent API: Chainable methods for expressive, readable code
  • Lightweight: Zero dependencies, small footprint
  • Modern: Built for ES6+ environments
  • Type-Safe Events: Custom event typing with TagEventMap
  • Multiple Export Formats: ESM, CommonJS, and TypeScript declarations
  • jQuery-like: Familiar API for developers who know jQuery

Installation

npm install @magik_io/mote
pnpm add @magik_io/mote
yarn add @magik_io/mote

Quick Start

import { Mote, El, All } from '@magik_io/mote';

// Create and append a new element
new Mote('div#container')
  .addClass('wrapper')
  .text('Hello World')
  .on('click', (e) => console.log(e))
  .appendTo('#app');

// Manipulate an existing element
new El('#myElement')
  .addClass('active')
  .html('<p>Updated content</p>')
  .on('click', () => console.log('Clicked!'));

// Work with multiple elements
new All('.items')
  .addClass('highlighted')
  .on('click', (e) => console.log('Item clicked:', e));

Table of Contents

Core Classes

Mote - Element Creation

The Mote class extends El and is used for creating new DOM elements and appending them to the document.

import { Mote, mote } from '@magik_io/mote';

// Create element with id using tagName#id syntax
const container = new Mote('div#myContainer')
  .addClass('container')
  .appendTo('#app');

// Using factory function
mote('button#submitBtn', '#form', (id) => {
  // Nested creation with access to parent ID
  mote('span', id).text('Submit');
});

El - Single Element Manipulation

The El class is for manipulating existing DOM elements.

import { El, el } from '@magik_io/mote';

// Select and manipulate an element
const input = new El('#username')
  .addClass('form-control')
  .set({ placeholder: 'Enter username' })
  .on('input', (e) => console.log(e.target.value));

// Using factory function
el<'input'>('#email').val('[email protected]');

All - Multiple Element Manipulation

The All class allows you to manipulate multiple elements at once.

import { All, all } from '@magik_io/mote';

// Select and manipulate multiple elements
new All<'button'>('.btn')
  .addClass('btn-primary')
  .on('click', (e) => console.log('Button clicked'));

// Iterate over elements
all('.items').each((element, index) => {
  console.log(`Item ${index}:`, element);
});

API Reference

Mote API

Constructor

new Mote<ElementName>(tagName: ElementName)

Creates a new element. Supports tagName#id syntax.

Examples:

new Mote('div')                    // Creates a div
new Mote('div#container')          // Creates a div with id="container"
new Mote('button#submitBtn')       // Creates a button with id="submitBtn"

Append Methods

  • appendTo(selector) - Append element to specified target

    new Mote('div').appendTo('#app');
    new Mote('span').appendTo(document.body);
  • appendToBody() - Append element to document.body

    new Mote('div#modal').appendToBody();
  • appendToHead() - Append element to document.head

    new Mote('script').appendToHead();
  • appendToRoot() - Append element to document.documentElement

    new Mote('div').appendToRoot();
  • appendWithin(callback) - Execute callback with element's ID

    new Mote('div#parent').appendWithin((id) => {
      new Mote('span').text('Child').appendTo(id);
    });

Factory Function

mote<ElementName>(tagName, appendTo, callback?)

Example:

mote('div#container', '#app', (id) => {
  mote('h1', id).text('Title');
  mote('p', id).text('Content');
});

El API

Constructor

new El<ElementName, StrictTypes>(selector)

Accepts:

  • CSS selector string
  • HTML element
  • Function returning element or selector

Examples:

new El('#myElement')
new El(document.getElementById('myElement'))
new El(() => document.querySelector('.active'))

Selection & Navigation

  • self() - Get the underlying HTML element

    const element = new El('#myDiv').self();
  • parent() - Get parent element

    new El('#child').parent().addClass('parent-class');
  • firstChild<E>() - Get first child element

    const first = new El('#parent').firstChild<HTMLDivElement>();
  • children() - Get all child nodes

    const nodes = new El('#parent').children();
  • find(selector) - Find elements within current element

    const buttons = new El('#form').find('button');

Class Management

  • addClass(className) - Add class(es)

    el.addClass('active');
    el.addClass(['active', 'highlight']);
    el.addClass(() => 'dynamic-class');
  • removeClass(className) - Remove class(es)

    el.removeClass('active');
    el.removeClass(['active', 'highlight']);
  • toggleClass(className) - Toggle class(es)

    el.toggleClass('active');
    el.toggleClass(['active', 'visible']);
  • hasClass(className) - Check if element has class

    if (el.hasClass('active')) { /* ... */ }

Content Manipulation

  • html(content) - Set inner HTML

    el.html('<p>Hello World</p>');
  • text(content) - Set text content

    el.text('Hello World');
    el.text(123);
    el.text(true);
  • textContent(content?) - Get or set text content

    const text = el.textContent();
    el.textContent('New text');
  • textChild(text) - Append text node as child

    el.textChild('Additional text');
  • empty() - Empty inner HTML

    el.empty();
  • clear() - Clear inner HTML (alias for empty)

    el.clear();

Attributes

  • set(attributes) - Set attributes

    el.set({
      id: 'myId',
      'data-value': '123',
      disabled: true
    });
  • unset(attributes) - Remove attributes

    el.unset(['disabled', 'readonly']);
    el.unset('disabled');
  • id(value?) - Get or set id

    const id = el.id();
    el.id('newId');
  • data(suffix) - Get data attribute

    const value = el.data('user-id'); // Gets data-user-id
  • dataset() - Get dataset object

    const dataset = el.dataset();
    console.log(dataset.userId);

Form Elements

  • val(value?) - Get or set value

    const value = el.val();
    el.val('new value');
    el.val(123);
  • check(boolean) - Check or uncheck input

    el.check(true);
    el.check(false);
  • checked() - Get checked state

    if (el.checked()) { /* ... */ }
  • type(type) - Set input type

    el.type('password');
  • name(name) - Set name attribute

    el.name('username');
  • input(type) - Set name to id and type

    el.input('email'); // Sets name=id and type=email
  • htmlFor(elementId) - Set label's for attribute

    new El('label').htmlFor('myInput');

Images

  • src(url) - Set image source

    new El<'img'>('#myImage').src('/images/photo.jpg');
  • alt(text) - Set image alt text

    new El<'img'>('#myImage').alt('Photo description');

DOM Operations

  • child(child, position?) - Append or prepend child

    el.child('<span>Text</span>');
    el.child(document.createElement('div'), 'prepend');
    el.child('<p>First</p>', 'prepend');
  • wrap(className) - Wrap element in div

    el.wrap('wrapper');
  • remove() - Remove element from DOM

    el.remove();
  • replaceWith(html) - Replace with HTML string

    el.replaceWith('<div>New content</div>');
  • replaceWithElement(tagName, id?) - Replace with new element

    const newEl = el.replaceWithElement('div', 'newId');

Event Handling

  • on(event, listener, options?) - Add event listener

    el.on('click', (e) => console.log(e));
    el.on<{ userId: string }>('custom', (e) => {
      console.log(e.detail.userId);
    });
  • once(event, listener) - Add one-time event listener

    el.once('click', (e) => console.log('Clicked once'));
  • off(event, listener, options?) - Remove event listener

    el.off('click', myHandler);
  • trigger(event, options?) - Trigger custom event

    el.trigger('change');
    el.trigger('custom', { detail: { data: 'value' } });
  • now(eventName, detail) - Dispatch custom event

    el.now('dataUpdated', { userId: '123' });
  • click() - Dispatch click event

    el.click();
  • triggerChange() - Trigger change event (select elements)

    new El<'select'>('#mySelect').triggerChange();
  • dispatchEvent(eventName) - Dispatch event

    el.dispatchEvent('input');

CSS Manipulation

  • css(property) - Get computed CSS property value

    const color = el.css('color');
  • css(property, value) - Set single CSS property

    el.css('color', 'red');
    el.css('font-size', 16);
  • css(properties) - Set multiple CSS properties

    el.css({
      color: 'red',
      'font-size': '16px',
      'background-color': '#f0f0f0'
    });

Visibility & Display

  • show() - Show element

    el.show();
  • hide() - Hide element

    el.hide();
  • toggle() - Toggle visibility

    el.toggle();
  • isVisible() - Check if element is visible

    if (el.isVisible()) { /* ... */ }

Dimensions & Position

  • width() - Get width

    const w = el.width(); // Returns number
  • width(value) - Set width

    el.width(100);      // Sets to 100px
    el.width('50%');    // Sets to 50%
  • height() / height(value) - Get or set height

    const h = el.height();
    el.height(200);
    el.height('auto');
  • offset() - Get offset position relative to document

    const { top, left } = el.offset();
  • position() - Get position relative to offset parent

    const { top, left } = el.position();

Animations

  • animate(keyframes, options) - Animate element using Web Animations API

    el.animate([
      { opacity: 0, transform: 'translateY(-20px)' },
      { opacity: 1, transform: 'translateY(0)' }
    ], {
      duration: 300,
      easing: 'ease-out'
    });
  • fadeIn(duration?) - Fade in element (returns Promise)

    await el.fadeIn(300);
  • fadeOut(duration?) - Fade out element (returns Promise)

    await el.fadeOut(300);
  • fadeTo(opacity, duration?) - Fade to specific opacity (returns Promise)

    await el.fadeTo(0.5, 300);
  • slideDown(duration?) - Slide down element (returns Promise)

    await el.slideDown(300);
  • slideUp(duration?) - Slide up element (returns Promise)

    await el.slideUp(300);

Utilities

  • if(expression) - Conditional chaining

    el.if(condition)?.addClass('active');
  • nestFrom(callback) - Execute callback with element id

    el.nestFrom((id) => {
      new Mote('span').text('Child').appendTo(id);
    });

Factory Function

el<ElementName, StrictTypes>(selector)

Example:

const myEl = el<'div'>('#container');

All API

Constructor

new All<ElementType>(selector)

Example:

new All<'button'>('.btn');

Iteration

  • each(callback) - Iterate over elements

    new All('.items').each((element, index) => {
      console.log(`Item ${index}:`, element.textContent);
    });
  • log(treeView?) - Debug log elements

    new All('.items').log();
    new All('.items').log(true); // Tree view
  • self() - Get NodeList of elements

    const elements = new All('.items').self();

Class Management

  • addClass(className) - Add class to all elements

    new All('.items').addClass('active');
    new All('.items').addClass(['active', 'highlight']);
  • removeClass(className) - Remove class from all elements

    new All('.items').removeClass('active');
  • toggleClass(className) - Toggle class on all elements

    new All('.items').toggleClass('visible');

Content & Attributes

  • html(content) - Set inner HTML for all elements

    new All('.items').html('<p>Same content</p>');
  • text(content) - Set text content for all elements

    new All('.items').text('Same text');
  • textChild(text) - Append text node to all elements

    new All('.items').textChild(' - updated');
  • empty() / clear() - Empty all elements

    new All('.items').empty();
  • set(attributes) - Set attributes on all elements

    new All('.items').set({ 'data-active': 'true' });
  • unset(attributes) - Remove attributes from all elements

    new All('.items').unset(['disabled', 'readonly']);
  • attr(attribute, value) - Set attribute on all elements

    new All('.items').attr('data-value', '123');
  • data(name, value) - Set data attribute on all elements

    new All('.items').data('userId', '123');

Form Elements

  • val(value?) - Set value on all elements

    new All<'input'>('.inputs').val('same value');
  • type(type) - Set type on all elements

    new All<'input'>('.inputs').type('text');
  • name(name) - Set name on all elements

    new All<'input'>('.inputs').name('fieldName');
  • input(type) - Set name to id and type on all elements

    new All<'input'>('.inputs').input('email');
  • htmlFor(elementId) - Set htmlFor on all label elements

    new All<'label'>('.labels').htmlFor('targetInput');

DOM Operations

  • child(element, position?) - Append/prepend child to all elements

    const span = document.createElement('span');
    new All('.items').child(span);
    new All('.items').child(span, 'prepend');
  • wrap(className) - Wrap all elements in div

    new All('.items').wrap('item-wrapper');
  • remove() - Remove all elements from DOM

    new All('.items').remove();
  • replaceWith(html) - Replace all elements with HTML

    new All('.items').replaceWith('<div>Replacement</div>');
  • src(url) - Set src on all elements

    new All<'img'>('.images').src('/images/placeholder.jpg');

Events

  • on(event, listener, options?) - Add event listener to all elements

    new All('.btns').on('click', (e) => console.log('Clicked'));
  • once(event, listener, options?) - Add one-time listener to all elements

    new All('.btns').once('click', (e) => console.log('First click'));
  • off(event, listener) - Remove event listener from all elements

    new All('.btns').off('click', myHandler);
  • now(eventName, detail) - Dispatch custom event on all elements

    new All('.items').now('refresh', { timestamp: Date.now() });
  • click() - Dispatch click event on all elements

    new All('.btns').click();

CSS Manipulation

  • css(property, value) - Set single CSS property on all elements

    new All('.items').css('color', 'red');
  • css(properties) - Set multiple CSS properties on all elements

    new All('.items').css({
      color: 'red',
      'font-size': '16px'
    });

Visibility & Dimensions

  • show() - Show all elements

    new All('.items').show();
  • hide() - Hide all elements

    new All('.items').hide();
  • toggle() - Toggle visibility of all elements

    new All('.items').toggle();
  • width(value) - Set width on all elements

    new All('.items').width(100);
    new All('.items').width('50%');
  • height(value) - Set height on all elements

    new All('.items').height(200);

Animations

  • fadeIn(duration?) - Fade in all elements (returns Promise)

    await new All('.items').fadeIn(300);
  • fadeOut(duration?) - Fade out all elements (returns Promise)

    await new All('.items').fadeOut(300);

Factory Function

all<ElementType>(selector)

Example:

const buttons = all<'button'>('.btn');

Examples

Creating a Form

import { mote } from '@magik_io/mote';

mote('form#loginForm', '#app', (formId) => {
  // Username field
  mote('div.form-group', formId, (groupId) => {
    mote('label', groupId).text('Username').htmlFor('username');
    mote('input#username', groupId)
      .addClass('form-control')
      .set({ type: 'text', placeholder: 'Enter username' });
  });

  // Password field
  mote('div.form-group', formId, (groupId) => {
    mote('label', groupId).text('Password').htmlFor('password');
    mote('input#password', groupId)
      .addClass('form-control')
      .set({ type: 'password', placeholder: 'Enter password' });
  });

  // Submit button
  mote('button#submitBtn', formId)
    .addClass('btn btn-primary')
    .text('Login')
    .on('click', async (e) => {
      e.preventDefault();
      const username = el<'input'>('#username').val();
      const password = el<'input'>('#password').val();
      console.log({ username, password });
    });
});

Dynamic List

import { Mote, All } from '@magik_io/mote';

const items = ['Apple', 'Banana', 'Cherry', 'Date'];

const list = new Mote('ul#fruitList')
  .addClass('list-unstyled')
  .appendTo('#app');

items.forEach((fruit, index) => {
  new Mote('li')
    .addClass('list-item')
    .text(fruit)
    .set({ 'data-index': index.toString() })
    .on('click', (e) => {
      new All('.list-item').removeClass('active');
      e.currentTarget.classList.add('active');
    })
    .appendTo('#fruitList');
});

Modal Dialog

import { Mote } from '@magik_io/mote';

function createModal(title: string, content: string) {
  const modal = new Mote('div#modal')
    .addClass('modal')
    .appendToBody();

  mote('div.modal-content', '#modal', (contentId) => {
    mote('div.modal-header', contentId, (headerId) => {
      mote('h2', headerId).text(title);
      mote('button.close', headerId)
        .text('×')
        .on('click', () => modal.remove());
    });

    mote('div.modal-body', contentId)
      .html(content);

    mote('div.modal-footer', contentId, (footerId) => {
      mote('button', footerId)
        .addClass('btn-primary')
        .text('Close')
        .on('click', () => modal.remove());
    });
  });

  return modal;
}

// Usage
createModal('Welcome', '<p>Welcome to our application!</p>');

Event Delegation

import { El, Mote } from '@magik_io/mote';

const container = new Mote('div#container')
  .appendToBody();

// Add event listener to container
new El('#container').on('click', (e) => {
  const target = e.target as HTMLElement;
  if (target.classList.contains('item')) {
    console.log('Item clicked:', target.textContent);
  }
});

// Dynamically add items
for (let i = 0; i < 10; i++) {
  new Mote('div')
    .addClass('item')
    .text(`Item ${i}`)
    .appendTo('#container');
}

Animations and Transitions

import { El, Mote } from '@magik_io/mote';

// Fade in elements on page load
const notification = new Mote('div#notification')
  .addClass('alert')
  .text('Welcome back!')
  .hide()
  .appendToBody();

// Fade in after a delay
setTimeout(async () => {
  await notification.fadeIn(300);

  // Auto-hide after 3 seconds
  setTimeout(async () => {
    await notification.fadeOut(300);
    notification.remove();
  }, 3000);
}, 500);

// Slide toggle for accordion
const toggleButton = new El('#accordion-toggle');
const content = new El('#accordion-content');

toggleButton.on('click', async () => {
  if (content.isVisible()) {
    await content.slideUp(300);
  } else {
    await content.slideDown(300);
  }
});

// Custom animations with Web Animations API
new El('#animatedBox').animate([
  { transform: 'translateX(0px)', opacity: 1 },
  { transform: 'translateX(100px)', opacity: 0.5 },
  { transform: 'translateX(0px)', opacity: 1 }
], {
  duration: 2000,
  iterations: Infinity,
  easing: 'ease-in-out'
});

// CSS manipulation with animations
new El('#styledElement')
  .css({
    'background-color': '#3498db',
    'transition': 'all 0.3s ease',
    'transform': 'scale(1)'
  })
  .on('mouseenter', (e) => {
    new El(e.currentTarget as HTMLElement).css({
      'background-color': '#2980b9',
      'transform': 'scale(1.05)'
    });
  })
  .on('mouseleave', (e) => {
    new El(e.currentTarget as HTMLElement).css({
      'background-color': '#3498db',
      'transform': 'scale(1)'
    });
  });

TypeScript Generic Types

import { El, Mote } from '@magik_io/mote';

// Specify element type for better type safety
const input = new El<'input'>('#username');
const value = input.val(); // TypeScript knows this returns string

// Strict mode for type-safe event handlers
const button = new El<'button', true>('#submitBtn');
button.on('click', (e) => {
  // e is typed as MouseEvent specifically for button elements
  console.log(e.currentTarget.type);
});

// Create typed elements
const image = new Mote<'img'>('img#logo')
  .src('/logo.png')
  .alt('Company Logo')
  .appendTo('#header');

// Custom event data
interface UserData {
  userId: string;
  username: string;
}

new El('#userProfile').on<UserData>('userUpdated', (e) => {
  console.log(e.detail.userId, e.detail.username);
});

TypeScript Support

Mote is built with TypeScript and provides comprehensive type definitions.

Generic Parameters

El<ElementName, StrictTypes>
Mote<ElementName, StrictMode>
All<ElementType>

Type Definitions

The library exports several useful types:

import type {
  htmlTags,           // Union of all HTML tag names
  htmlElements,       // Union of all HTML element types
  selectorString,     // CSS selector string
  idString,           // ID selector (#id)
  classString,        // Class selector (.class)
  GenericEvent,       // Generic event type with custom data
  TagEventMap,        // Event map for specific element types
} from '@magik_io/mote/types';

Custom Elements

Extend Mote to support custom HTML elements:

// In your types file
declare module '@magik_io/mote' {
  interface CustomHTMLElements {
    'my-component': HTMLElement;
    'custom-button': HTMLButtonElement;
  }
}

// Usage
new Mote<'my-component'>('my-component').appendTo('#app');

Strict Type Mode

Enable strict typing for more precise type checking:

// Without strict mode (default)
const el = new El<'button'>('#myBtn');
el.on('click', (e) => {
  // e is GenericEvent
});

// With strict mode
const strictEl = new El<'button', true>('#myBtn');
strictEl.on('click', (e) => {
  // e is MouseEvent from TagEventMap
  console.log(e.button); // Typed correctly
});

Contributing

Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.

Development

# Install dependencies
pnpm install

# Start development server
pnpm dev

# Run linter
pnpm lint

# Run tests
pnpm test

# Build library
pnpm build

License

MIT © Antonio B.

Links


So mote it be