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 🙏

© 2026 – Pkg Stats / Ryan Hefner

nasjs

v1.5.0

Published

Modern DatePicker (jQuery UI alternative), TimePicker, Event Calendar, Image Gallery, Modal & Confirmation Popup (SweetAlert alternative) - Zero dependencies, lightweight UI components for vanilla JS, React, Vue, Angular

Readme

NASjs

Modern DatePicker (jQuery UI Alternative), TimePicker, Event Calendar, Image Gallery, Modal & Confirmation Popup (SweetAlert Alternative) - Zero Dependencies, Lightweight UI Components for React, Vue, Angular & Vanilla JS

License: MIT Version Size No Dependencies GitHub stars

Live Demo & Documentation | GitHub | npm


Why NASjs?

  • jQuery UI DatePicker Alternative - Modern, lightweight datepicker without jQuery dependency
  • SweetAlert Alternative - Beautiful confirmation dialogs without the bloat
  • Zero Dependencies - Pure vanilla JavaScript, no jQuery or frameworks required
  • Lightweight - Only ~8KB gzipped, perfect for performance
  • Framework Agnostic - Works with React, Vue, Angular, or plain HTML
  • Modern Design - Beautiful, clean UI with smooth animations
  • Dark Mode - Automatic dark mode support based on system preferences
  • Fully Accessible - Keyboard navigation, ARIA labels, screen reader support

Components

| Component | Description | |-----------|-------------| | DatePicker | Modern date selection with min/max dates, disabled days, available dates from API | | TimePicker | Time selection with 12/24 hour format and customizable intervals | | Dropdown | Searchable dropdown with remote JSON, add button, rich templates, RTL support | | Event Calendar | Full calendar view with events, popups, and API integration | | Image Gallery | Lightbox gallery with thumbnails, zoom, and keyboard navigation | | Modal | Customizable modal dialogs with animations | | Confirm | SweetAlert-style confirmation dialogs | | Popup | Form popups for dropdown add functionality | | Live Clock | Real-time clock display |


Installation

NPM

npm install nasjs

Yarn

yarn add nasjs

CDN (jsDelivr - Recommended)

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/nasjs.min.css">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/nasjs.min.js"></script>

CDN (GitHub Pages)

<link rel="stylesheet" href="https://naseemfasal.github.io/NASjs/dist/nasjs.min.css">
<script src="https://naseemfasal.github.io/NASjs/dist/nasjs.min.js"></script>

Quick Start

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/nasjs.min.css">
</head>
<body>
  <input type="text" class="datepicker" placeholder="Select date">

  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/nasjs.min.js"></script>
  <script>
    NASjs.datePicker({ selector: '.datepicker' });
  </script>
</body>
</html>

1. DatePicker - Modern jQuery UI Alternative

A beautiful, lightweight datepicker with advanced features.

Basic Usage

NASjs.datePicker({
  selector: '.datepicker-input',
  format: 'YYYY-MM-DD',
  onSelect: (date, input) => {
    console.log('Selected:', date);
  }
});

Block Past Dates (Booking Systems)

NASjs.datePicker({
  selector: '.booking-date',
  blockPastDates: true,  // Only future dates available
  format: 'YYYY-MM-DD'
});

Block Future Dates (Historical Data)

NASjs.datePicker({
  selector: '.history-date',
  blockFutureDates: true,  // Only past dates available
  format: 'YYYY-MM-DD'
});

Date Range (Next 30 Days)

NASjs.datePicker({
  selector: '.appointment-date',
  minDate: '+0',    // Today
  maxDate: '+30',   // 30 days from today
  format: 'YYYY-MM-DD'
});

Disable Weekends (Business Days Only)

NASjs.datePicker({
  selector: '.business-date',
  blockPastDates: true,
  disabledDaysOfWeek: [0, 6],  // Sunday=0, Saturday=6
  format: 'YYYY-MM-DD'
});

Disable Specific Dates (Holidays)

NASjs.datePicker({
  selector: '.holiday-aware-date',
  disabledDates: [
    '2024-12-25',  // Christmas
    '2024-12-31',  // New Year's Eve
    '2025-01-01'   // New Year's Day
  ],
  format: 'YYYY-MM-DD'
});

Available Dates Only (Hotel Booking)

// Hardcoded available dates
NASjs.datePicker({
  selector: '.room-availability',
  availableDates: [
    '2024-12-20', '2024-12-21', '2024-12-22',
    '2024-12-27', '2024-12-28', '2024-12-29'
  ],
  format: 'YYYY-MM-DD'
});

// Load from API
NASjs.datePicker({
  selector: '.room-availability',
  availableDatesUrl: '/api/available-dates',
  format: 'YYYY-MM-DD'
});

DatePicker Parameters

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | selector | string | '.datepicker-input' | CSS selector for inputs | | format | string | 'YYYY-MM-DD' | Date format (YYYY-MM-DD, DD-MM-YYYY, DD/MM/YYYY) | | minDate | string/Date | null | Minimum date: '2024-01-01', '+0', '-30' | | maxDate | string/Date | null | Maximum date: '2024-12-31', '+365' | | blockPastDates | boolean | false | Block all dates before today | | blockFutureDates | boolean | false | Block all dates after today | | availableDates | array | null | Only these dates are selectable | | availableDatesUrl | string | null | API URL to fetch available dates | | disabledDates | array | [] | Specific dates to disable | | disabledDaysOfWeek | array | [] | Days to disable [0-6] (0=Sunday) | | readonly | boolean | true | Prevent manual typing | | onSelect | function | null | Callback: (date, input) => {} | | onDateCheck | function | null | Custom validation: (date) => boolean |


2. TimePicker

Simple, elegant time selection.

Basic Usage

NASjs.timePicker({
  selector: '.timepicker-input',
  format: '12',     // '12' or '24' hour format
  interval: 30,     // Minutes between options
  onSelect: (time, input) => {
    console.log('Selected:', time);
  }
});

TimePicker Parameters

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | selector | string | '.timepicker-input' | CSS selector | | format | string | '12' | Time format: '12' or '24' | | interval | number | 30 | Minutes: 15, 30, 60, 120 | | onSelect | function | null | Callback when time selected |


3. Searchable Dropdown

Powerful dropdown with search, remote data, add button, and rich item templates. Full RTL/Arabic support.

Basic Usage

// Static data
const dropdown = NASjs.dropdown({
  selector: '#my-dropdown',
  placeholder: 'Select an item...',
  data: [
    { id: 1, name: 'Option 1' },
    { id: 2, name: 'Option 2' },
    { id: 3, name: 'Option 3' }
  ],
  onSelect: (item) => console.log('Selected:', item)
});

Remote JSON Data

// Load from API with search
NASjs.dropdown({
  selector: '#users-dropdown',
  remoteUrl: '/api/users',
  remoteSearchParam: 'search',  // Query param: /api/users?search=john
  remoteDataKey: 'data',        // Response key containing array
  valueKey: 'id',
  labelKey: 'name',
  minSearchLength: 2,           // Start searching after 2 characters
  debounceDelay: 300            // Wait 300ms before API call
});

// Expected JSON response:
// { "data": [{ "id": 1, "name": "John" }, { "id": 2, "name": "Jane" }] }

With Add Button & Popup

let dropdown = NASjs.dropdown({
  selector: '#customer-dropdown',
  data: [...],
  addButton: true,
  addButtonLabel: 'Add Customer',
  addButtonIcon: '+',
  onAddClick: (instance) => {
    // Show popup form
    NASjs.popup({
      title: 'Add New Customer',
      content: `
        <form id="customer-form">
          <input type="text" id="name" placeholder="Customer Name" style="width:100%;padding:10px;margin-bottom:10px;">
          <input type="email" id="email" placeholder="Email" style="width:100%;padding:10px;">
        </form>
      `,
      confirmText: 'Add',
      onConfirm: () => {
        const name = document.getElementById('name').value;
        const email = document.getElementById('email').value;

        // Add to dropdown and select
        const newItem = { id: Date.now(), name: name, email: email };
        instance.addItem(newItem, true); // true = auto-select
      }
    });
  }
});

// Programmatically set value after adding
dropdown.setValue(123);

Rich Template (Title + Subtitle + Status)

NASjs.dropdown({
  selector: '#projects-dropdown',
  template: 'rich',
  titleKey: 'name',
  subtitleKey: 'description',
  statusKey: 'status',
  imageKey: 'avatar',   // Optional image
  data: [
    {
      id: 1,
      name: 'Project Alpha',
      description: 'Main development project',
      status: 'Active',
      avatar: '/images/project1.png'
    },
    {
      id: 2,
      name: 'مشروع بيتا',  // Arabic support
      description: 'مشروع التطوير الثاني',
      status: 'معلق'       // Arabic status (Pending)
    }
  ]
});

RTL / Arabic Support

// Auto-detect RTL from document/element direction
NASjs.dropdown({
  selector: '#arabic-dropdown',
  rtl: 'auto',  // or true/false
  placeholder: 'اختر عنصر...',
  searchPlaceholder: 'بحث...',
  noResultsText: 'لا توجد نتائج',
  data: [
    { id: 1, name: 'الخيار الأول' },
    { id: 2, name: 'الخيار الثاني' }
  ]
});

Dropdown Parameters

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | selector | string | '.nasjs-dropdown' | CSS selector or element | | placeholder | string | 'Select an option...' | Placeholder text | | searchPlaceholder | string | 'Search...' | Search input placeholder | | data | array | [] | Static data array | | valueKey | string | 'id' | Object key for value | | labelKey | string | 'name' | Object key for label | | remoteUrl | string | null | URL to fetch data | | remoteSearchParam | string | 'search' | Search query parameter | | remoteDataKey | string | 'data' | Response key (null for root array) | | minSearchLength | number | 0 | Min chars to trigger search | | addButton | boolean | false | Show add button | | addButtonLabel | string | 'Add New' | Add button text | | onAddClick | function | null | Add button callback | | template | string | 'default' | 'default' or 'rich' | | titleKey | string | 'name' | Rich template title key | | subtitleKey | string | 'subtitle' | Rich template subtitle key | | statusKey | string | 'status' | Rich template status key | | rtl | string/bool | 'auto' | RTL mode: 'auto', true, false | | styles.theme | string | 'light' | 'light' or 'dark' | | onSelect | function | null | Selection callback | | onChange | function | null | Value change callback |

Dropdown Methods

const dropdown = NASjs.dropdown({ ... });

dropdown.setValue(123);        // Set value programmatically
dropdown.getValue();           // Get current value
dropdown.getSelectedItem();    // Get full selected object
dropdown.setData(newData);     // Replace all data
dropdown.addItem(item, true);  // Add item, optionally select it
dropdown.clear();              // Clear selection
dropdown.refresh();            // Reload remote data
dropdown.openDropdown();       // Open programmatically
dropdown.closeDropdown();      // Close programmatically
dropdown.destroy();            // Remove dropdown

4. Event Calendar

Full-featured calendar with event display.

Basic Usage

const calendar = NASjs.eventCalendar({
  selector: '#my-calendar',
  events: [
    {
      id: 1,
      title: 'Team Meeting',
      date: '2024-12-15',
      description: 'Weekly sync',
      color: '#3b82f6'
    },
    {
      id: 2,
      title: 'Product Launch',
      date: '2024-12-20',
      description: 'New feature release',
      color: '#10b981'
    }
  ]
});

Load Events from API

NASjs.eventCalendar({
  selector: '#calendar',
  eventsUrl: '/api/events',  // Returns JSON array of events
  onEventClick: (event, element) => {
    console.log('Event clicked:', event);
  },
  onDateClick: (date, events) => {
    console.log('Date clicked:', date, events);
  }
});

Custom Popup Fields

NASjs.eventCalendar({
  selector: '#calendar',
  events: myEvents,
  popupFields: [
    { key: 'title', label: 'Event' },
    { key: 'date', label: 'Date' },
    { key: 'location', label: 'Location' },
    { key: 'attendees', label: 'Attendees' }
  ]
});

Custom Popup Renderer

NASjs.eventCalendar({
  selector: '#calendar',
  events: myEvents,
  renderEventPopup: (event) => {
    return `
      <div class="my-custom-popup">
        <h3>${event.title}</h3>
        <p>${event.description}</p>
        <button onclick="editEvent(${event.id})">Edit</button>
      </div>
    `;
  }
});

Event Calendar API JSON Format

{
  "events": [
    {
      "id": 1,
      "title": "Meeting",
      "date": "2024-12-15",
      "description": "Team sync",
      "color": "#3b82f6"
    }
  ]
}

Event Calendar Parameters

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | selector | string | '#calendar' | Container selector | | events | array | [] | Array of event objects | | eventsUrl | string | null | API URL to fetch events | | dateField | string | 'date' | Event date field name | | titleField | string | 'title' | Event title field name | | descriptionField | string | 'description' | Event description field | | colorField | string | 'color' | Event color field | | defaultColor | string | '#3b82f6' | Default event color | | maxEventsPerDay | number | 3 | Max events shown per cell | | onEventClick | function | null | Event click callback | | onDateClick | function | null | Date click callback | | onMonthChange | function | null | Month navigation callback | | popupFields | array | null | Custom popup fields | | renderEventPopup | function | null | Custom popup renderer |

Calendar Methods

const calendar = NASjs.eventCalendar({ ... });

// Add event
calendar.addEvent({ id: 3, title: 'New Event', date: '2024-12-25' });

// Remove event
calendar.removeEvent(3);

// Set all events
calendar.setEvents(newEventsArray);

// Refresh from API
await calendar.refreshEvents();

// Navigate to date
calendar.goToDate('2024-06-01');

// Go to today
calendar.goToToday();

5. Image Gallery - Modern Lightbox

Beautiful image gallery with thumbnails and zoom.

Basic Usage

<!-- Add data-nasjs-gallery attribute to images -->
<img src="thumb1.jpg"
     data-nasjs-gallery
     data-image-url="full1.jpg"
     data-title="Beautiful Sunset"
     data-description="Captured at the beach">

<img src="thumb2.jpg"
     data-nasjs-gallery
     data-image-url="full2.jpg"
     data-title="Mountain View">

<script>
  NASjs.imageGallery();
</script>

Grouped Galleries

<!-- Gallery 1 -->
<img src="nature1.jpg" data-nasjs-gallery data-gallery="nature" data-image-url="nature1-full.jpg">
<img src="nature2.jpg" data-nasjs-gallery data-gallery="nature" data-image-url="nature2-full.jpg">

<!-- Gallery 2 -->
<img src="city1.jpg" data-nasjs-gallery data-gallery="city" data-image-url="city1-full.jpg">
<img src="city2.jpg" data-nasjs-gallery data-gallery="city" data-image-url="city2-full.jpg">

<script>
  NASjs.imageGallery();
</script>

Image Gallery Parameters

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | selector | string | '[data-nasjs-gallery]' | Image selector | | enableZoom | boolean | true | Enable zoom on click | | zoomLevel | number | 2 | Zoom magnification level | | enableKeyboard | boolean | true | Arrow keys navigation | | showThumbnails | boolean | true | Show thumbnail strip | | showCounter | boolean | true | Show image counter | | closeOnBackdrop | boolean | true | Close on backdrop click | | onOpen | function | null | Gallery open callback | | onClose | function | null | Gallery close callback | | onChange | function | null | Image change callback |

Image Data Attributes

| Attribute | Description | |-----------|-------------| | data-nasjs-gallery | Enable gallery for this image | | data-gallery | Group name for multiple galleries | | data-image-url | Full-size image URL | | data-title | Image title | | data-description | Image description |


6. Modal - Customizable Dialogs

const modal = NASjs.modal({
  title: 'Welcome!',
  content: '<p>This is a modal popup with custom content.</p>',
  buttons: [
    {
      text: 'Cancel',
      class: 'nasjs-modal-btn-secondary',
      onClick: () => console.log('Cancelled')
    },
    {
      text: 'Confirm',
      class: 'nasjs-modal-btn-primary',
      onClick: () => console.log('Confirmed')
    }
  ],
  closeOnBackdrop: true,
  closeOnEscape: true,
  onOpen: () => console.log('Modal opened'),
  onClose: () => console.log('Modal closed')
});

// Close programmatically
modal.close();

Modal Button Classes

  • nasjs-modal-btn-primary - Blue primary button
  • nasjs-modal-btn-secondary - Gray secondary button
  • nasjs-modal-btn-danger - Red danger button

7. Confirm - SweetAlert Alternative

Beautiful confirmation dialogs without dependencies.

NASjs.confirm({
  title: 'Delete Item?',
  message: 'This action cannot be undone. Are you sure?',
  confirmText: 'Yes, Delete',
  cancelText: 'Cancel',
  onConfirm: () => {
    // Delete the item
    console.log('Item deleted');
  },
  onCancel: () => {
    console.log('Cancelled');
  }
});

Confirm Parameters

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | title | string | 'Confirm' | Dialog title | | message | string | 'Are you sure?' | Confirmation message | | confirmText | string | 'Yes' | Confirm button text | | cancelText | string | 'No' | Cancel button text | | onConfirm | function | null | Confirm callback | | onCancel | function | null | Cancel callback |


8. Live Clock

const clock = NASjs.liveClock('#clock-container', {
  format: '12',        // '12' or '24'
  showSeconds: true,
  showDate: true
});

// Control the clock
clock.stop();
clock.start();

Dark Mode

NASjs automatically supports dark mode based on system preferences. No configuration needed!

/* Customize dark mode colors */
@media (prefers-color-scheme: dark) {
  .nasjs-datepicker {
    --nasjs-bg: #1f2937;
    --nasjs-text: #f9fafb;
  }
}

Framework Integration

NASjs works seamlessly with all modern frameworks. Here's how to use it:

React

import { useEffect, useRef } from 'react';
import 'nasjs/dist/nasjs.min.css';
import NASjs from 'nasjs';

function DatePickerComponent() {
  const inputRef = useRef(null);

  useEffect(() => {
    if (inputRef.current) {
      NASjs.datePicker({
        selector: inputRef.current,
        format: 'YYYY-MM-DD',
        onSelect: (date) => console.log('Selected:', date)
      });
    }
  }, []);

  return <input ref={inputRef} placeholder="Select date" />;
}

Vue 3

<template>
  <input ref="datepicker" placeholder="Select date" />
</template>

<script setup>
import { ref, onMounted } from 'vue';
import 'nasjs/dist/nasjs.min.css';
import NASjs from 'nasjs';

const datepicker = ref(null);

onMounted(() => {
  NASjs.datePicker({
    selector: datepicker.value,
    format: 'YYYY-MM-DD',
    onSelect: (date) => console.log('Selected:', date)
  });
});
</script>

Angular

import { Component, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
import NASjs from 'nasjs';

@Component({
  selector: 'app-datepicker',
  template: '<input #datepicker placeholder="Select date" />'
})
export class DatePickerComponent implements AfterViewInit {
  @ViewChild('datepicker') datepicker: ElementRef;

  ngAfterViewInit() {
    NASjs.datePicker({
      selector: this.datepicker.nativeElement,
      format: 'YYYY-MM-DD',
      onSelect: (date) => console.log('Selected:', date)
    });
  }
}

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)
  • Opera (latest)

Accessibility

  • Full keyboard navigation (Tab, Enter, Escape, Arrow keys)
  • ARIA labels and roles
  • Screen reader friendly
  • Focus management

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

MIT License - see the LICENSE file for details.


Author

Developed by Naseem Fasal Palappetty


Support


Made with care for developers who want beautiful UI without the bloat.