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
Live Demo & Documentation | GitHub | npm
- 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
| 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 |
npm install nasjsyarn add nasjs<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nasjs@1.5.0/dist/nasjs.min.css">
<script src="https://cdn.jsdelivr.net/npm/nasjs@1.5.0/dist/nasjs.min.js"></script><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><!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nasjs@1.5.0/dist/nasjs.min.css">
</head>
<body>
<input type="text" class="datepicker" placeholder="Select date">
<script src="https://cdn.jsdelivr.net/npm/nasjs@1.5.0/dist/nasjs.min.js"></script>
<script>
NASjs.datePicker({ selector: '.datepicker' });
</script>
</body>
</html>A beautiful, lightweight datepicker with advanced features.
NASjs.datePicker({
selector: '.datepicker-input',
format: 'YYYY-MM-DD',
onSelect: (date, input) => {
console.log('Selected:', date);
}
});NASjs.datePicker({
selector: '.booking-date',
blockPastDates: true, // Only future dates available
format: 'YYYY-MM-DD'
});NASjs.datePicker({
selector: '.history-date',
blockFutureDates: true, // Only past dates available
format: 'YYYY-MM-DD'
});NASjs.datePicker({
selector: '.appointment-date',
minDate: '+0', // Today
maxDate: '+30', // 30 days from today
format: 'YYYY-MM-DD'
});NASjs.datePicker({
selector: '.business-date',
blockPastDates: true,
disabledDaysOfWeek: [0, 6], // Sunday=0, Saturday=6
format: 'YYYY-MM-DD'
});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'
});// 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'
});| 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 |
Simple, elegant time selection.
NASjs.timePicker({
selector: '.timepicker-input',
format: '12', // '12' or '24' hour format
interval: 30, // Minutes between options
onSelect: (time, input) => {
console.log('Selected:', time);
}
});| 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 |
Powerful dropdown with search, remote data, add button, and rich item templates. Full RTL/Arabic support.
// 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)
});// 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" }] }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);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)
}
]
});// 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: 'الخيار الثاني' }
]
});| 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 |
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 dropdownFull-featured calendar with event display.
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'
}
]
});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);
}
});NASjs.eventCalendar({
selector: '#calendar',
events: myEvents,
popupFields: [
{ key: 'title', label: 'Event' },
{ key: 'date', label: 'Date' },
{ key: 'location', label: 'Location' },
{ key: 'attendees', label: 'Attendees' }
]
});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>
`;
}
});{
"events": [
{
"id": 1,
"title": "Meeting",
"date": "2024-12-15",
"description": "Team sync",
"color": "#3b82f6"
}
]
}| 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 |
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();Beautiful image gallery with thumbnails and zoom.
<!-- 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><!-- 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>| 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 |
| 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 |
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();nasjs-modal-btn-primary- Blue primary buttonnasjs-modal-btn-secondary- Gray secondary buttonnasjs-modal-btn-danger- Red danger button
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');
}
});| 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 |
const clock = NASjs.liveClock('#clock-container', {
format: '12', // '12' or '24'
showSeconds: true,
showDate: true
});
// Control the clock
clock.stop();
clock.start();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;
}
}NASjs works seamlessly with all modern frameworks. Here's how to use it:
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" />;
}<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>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)
});
}
}- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
- Opera (latest)
- Full keyboard navigation (Tab, Enter, Escape, Arrow keys)
- ARIA labels and roles
- Screen reader friendly
- Focus management
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
MIT License - see the LICENSE file for details.
Developed by Naseem Fasal Palappetty
- GitHub: @naseemfasal
- Demo: https://naseemfasal.github.io/NASjs/
- Issues: GitHub Issues
- Documentation: Live Demo
Made with care for developers who want beautiful UI without the bloat.