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

innocore-scheduler

v1.0.3

Published

Config-driven, data-source agnostic scheduler/calendar component built with pure HTML, CSS, and JavaScript

Readme

@innocore/scheduler

A config-driven, data-source agnostic scheduler/calendar component built with pure HTML, CSS, and JavaScript.

Features

  • 📅 Multiple Views: Day, Week, Month, and Agenda views
  • 🔧 Fully Configurable: Event fields, views, and behaviors are all configurable
  • 🌐 Timezone Support: Built-in timezone conversion and display
  • 🔁 Recurring Events: Support for daily, weekly, and monthly recurring events
  • 📱 Responsive: Works seamlessly across desktop and mobile devices
  • 🎨 Customizable: Easy to style and extend
  • 🔄 Two-Way Data Binding: Automatic synchronization between UI and data

Installation

npm install @innocore/scheduler

Basic Usage

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="node_modules/@innocore/scheduler/dist/scheduler.css">
</head>
<body>
  <div id="scheduler-container"></div>
  
  <script src="node_modules/@innocore/scheduler/dist/scheduler.min.js"></script>
  <script>
    const scheduler = new Scheduler.default({
      container: '#scheduler-container',
      view: 'week',
      startHour: 8,
      endHour: 18,
      events: [
        {
          id: '1',
          title: 'Team Meeting',
          startDate: '2026-01-22T10:00:00',
          endDate: '2026-01-22T11:00:00',
          location: 'Conference Room A'
        }
      ]
    });
    
    scheduler.render();
  </script>
</body>
</html>

Configuration

Core Configuration

const scheduler = new Scheduler.default({
  container: '#scheduler-container',    // Container selector or element
  view: 'week',                          // Initial view: 'day', 'week', 'month', 'agenda'
  currentDate: new Date(),               // Initial date
  startHour: 8,                          // Start hour for day/week views
  endHour: 18,                           // End hour for day/week views
  hourHeight: 60,                        // Height per hour in pixels
  timezone: 'local',                     // Display timezone
  slotClickEnabled: true,                // Enable click to create events
  events: []                             // Initial events array
});

UI Configurability

The scheduler provides complete control over which UI elements and interactions are available:

Configurable Views

Control which calendar views are available to users:

const scheduler = new Scheduler.default({
  container: '#scheduler-container',
  
  // Only show Week and Month views (hide Day and Agenda)
  enabledViews: ['week', 'month']
  
  // Or only show a single view
  // enabledViews: ['week']
  
  // Default: ['day', 'week', 'month', 'agenda']
});

Valid view names: 'day', 'week', 'month', 'agenda'

Read-Only Mode

Make the scheduler completely read-only (no editing or creating):

const scheduler = new Scheduler.default({
  container: '#scheduler-container',
  
  // Enable read-only mode
  readOnly: true
  
  // Default: false
});

When readOnly: true:

  • All event creation buttons are hidden
  • Clicking on time slots does nothing
  • Clicking on events does not open edit modal
  • Event tooltips show information but no Edit/Delete buttons
  • Perfect for displaying schedules that should not be modified

Timezone Selector Visibility

Control whether the timezone dropdown is visible:

const scheduler = new Scheduler.default({
  container: '#scheduler-container',
  
  // Hide the timezone selector
  showTimezoneSelector: false
  
  // Default: true
});

Export Buttons Configuration

Control which export format buttons are available in the toolbar:

const scheduler = new Scheduler.default({
  container: '#scheduler-container',
  
  // Option 1: Show all export formats
  showExportButtons: true
  
  // Option 2: Show specific formats only
  showExportButtons: ['json', 'csv']  // Only JSON and CSV
  
  // Option 3: Show no export buttons (default)
  showExportButtons: false
});

Available export formats: 'json', 'csv', 'excel', 'ical'

Examples:

// Only JSON and CSV exports
showExportButtons: ['json', 'csv']

// Only Excel export
showExportButtons: ['excel']

// All formats
showExportButtons: true  // or ['json', 'csv', 'excel', 'ical']

// No export buttons
showExportButtons: false

Configuration Examples

Example 1: Read-Only Schedule Display

const scheduler = new Scheduler.default({
  container: '#scheduler-container',
  enabledViews: ['week'],           // Only week view
  readOnly: true,                    // No editing or creating
  showTimezoneSelector: false,       // Hide timezone dropdown
  eventSources: [fetchScheduleData()] // Load events from API
});

Example 2: Minimal Configuration

const scheduler = new Scheduler.default({
  container: '#scheduler-container',
  enabledViews: ['month'],           // Month view only
  showTimezoneSelector: false        // Hide timezone selector
});

Example 3: Full Featured with Custom Fields

const scheduler = new Scheduler.default({
  container: '#scheduler-container',
  enabledViews: ['day', 'week', 'month'],
  showTimezoneSelector: true,        // Show timezone selector
  eventFormFields: customFields      // Custom event fields
});

Configurable Event Fields

One of the key features of @innocore/scheduler is fully configurable event fields. Event fields are not hardcoded - they are defined through configuration.

Field Configuration Structure

Each field configuration object supports the following properties:

| Property | Type | Required | Description | |----------|------|----------|-------------| | key | String | Yes | Data key for the field (maps to data source) | | label | String | Yes | Display label in the form | | control | String | Yes | Input control type (see below) | | dataType | String | No | Expected data type (for validation) | | required | Boolean | No | Whether field is mandatory | | placeholder | String | No | Placeholder text for input | | default | Any | No | Default value if not provided | | options | Array | No | Options for select/dropdown controls | | min | Number/String | No | Minimum value (for number/date inputs) | | max | Number/String | No | Maximum value (for number/date inputs) | | pattern | String | No | Regex pattern for validation | | rows | Number | No | Number of rows (for textarea) |

Supported Control Types

  • text - Single-line text input
  • textarea - Multi-line text input
  • date - Date picker
  • time - Time picker
  • datetime-local - Date and time picker
  • number - Number input
  • email - Email input
  • tel - Telephone input
  • url - URL input
  • checkbox - Checkbox
  • select - Dropdown select

Default Event Fields

If not specified, the scheduler uses these default fields:

[
  {
    key: 'title',
    label: 'Event Title',
    control: 'text',
    required: true,
    placeholder: 'Enter event title'
  },
  {
    key: 'startDate',
    label: 'Start Date & Time',
    control: 'datetime-local',
    required: true
  },
  {
    key: 'endDate',
    label: 'End Date & Time',
    control: 'datetime-local',
    required: true
  },
  {
    key: 'location',
    label: 'Location',
    control: 'text',
    placeholder: 'Add location'
  },
  {
    key: 'description',
    label: 'Description',
    control: 'textarea',
    placeholder: 'Add description',
    rows: 3
  }
]

Custom Event Fields Example

You can completely customize the event fields:

const scheduler = new Scheduler.default({
  container: '#scheduler-container',
  eventFormFields: [
    {
      key: 'title',
      label: 'Meeting Title',
      control: 'text',
      required: true,
      placeholder: 'Enter meeting title',
      maxLength: 100
    },
    {
      key: 'organizer',
      label: 'Organizer',
      control: 'text',
      required: true,
      placeholder: 'Enter organizer name'
    },
    {
      key: 'startDate',
      label: 'Start Time',
      control: 'datetime-local',
      required: true
    },
    {
      key: 'endDate',
      label: 'End Time',
      control: 'datetime-local',
      required: true
    },
    {
      key: 'meetingType',
      label: 'Meeting Type',
      control: 'select',
      required: true,
      options: [
        { value: 'internal', label: 'Internal Meeting' },
        { value: 'client', label: 'Client Meeting' },
        { value: 'review', label: 'Review Meeting' }
      ]
    },
    {
      key: 'location',
      label: 'Location',
      control: 'text',
      placeholder: 'Conference room or online link'
    },
    {
      key: 'attendees',
      label: 'Number of Attendees',
      control: 'number',
      min: 1,
      max: 100,
      default: 1
    },
    {
      key: 'isVirtual',
      label: 'Virtual Meeting',
      control: 'checkbox'
    },
    {
      key: 'notes',
      label: 'Meeting Notes',
      control: 'textarea',
      rows: 4,
      placeholder: 'Add meeting notes or agenda'
    },
    {
      key: 'priority',
      label: 'Priority',
      control: 'select',
      options: ['Low', 'Medium', 'High', 'Urgent']
    }
  ]
});

Two-Way Data Binding

The scheduler automatically maintains two-way data binding:

UI → Data: When users create or edit events through the form, the data is automatically updated.

Data → UI: When you update events programmatically, the UI automatically reflects the changes.

// Programmatic updates automatically reflect in UI
scheduler.addEvent({
  id: '123',
  title: 'New Event',
  startDate: '2026-01-23T14:00:00',
  endDate: '2026-01-23T15:00:00',
  organizer: 'John Doe',
  meetingType: 'client'
});

// Get current events (with all custom fields)
const events = scheduler.getEvents();

// Update event
scheduler.updateEvent('123', {
  title: 'Updated Event',
  priority: 'High'
});

// Delete event
scheduler.deleteEvent('123');

Data Source Mapping

Your event data can come from any source (REST API, GraphQL, Database, etc.) as long as it maps to the configured fields:

// Example: Fetch from API and map to scheduler
fetch('/api/meetings')
  .then(response => response.json())
  .then(apiData => {
    const events = apiData.map(meeting => ({
      id: meeting.meetingId,
      title: meeting.subject,
      startDate: meeting.startTime,
      endDate: meeting.endTime,
      organizer: meeting.createdBy,
      location: meeting.roomName,
      meetingType: meeting.type,
      isVirtual: meeting.hasOnlineLink
    }));
    
    scheduler.config.events = events;
    scheduler.refresh();
  });

Recurring Events

The scheduler supports recurring events with configurable patterns:

{
  id: '1',
  title: 'Daily Standup',
  startDate: '2026-01-22T09:00:00',
  endDate: '2026-01-22T09:15:00',
  isRecurring: true,
  recurrenceRule: 'FREQ=DAILY;INTERVAL=1;UNTIL=20260228T000000Z'
}

Recurrence patterns supported:

  • Daily: FREQ=DAILY;INTERVAL=1
  • Weekly: FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE,FR
  • Monthly: FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15

Timezone Support

The scheduler includes built-in timezone conversion:

const scheduler = new Scheduler.default({
  container: '#scheduler-container',
  timezone: 'America/New_York',  // Display in ET
  events: [
    {
      id: '1',
      title: 'Team Meeting',
      startDate: '2026-01-22T10:00:00Z',  // UTC time
      endDate: '2026-01-22T11:00:00Z'      // Displays as 5:00 AM ET
    }
  ]
});

Available timezones:

  • local - User's local timezone
  • UTC - Coordinated Universal Time
  • America/New_York - Eastern Time
  • America/Chicago - Central Time
  • America/Denver - Mountain Time
  • America/Los_Angeles - Pacific Time
  • Europe/London - GMT/BST
  • Europe/Paris - Central European Time
  • Asia/Tokyo - Japan Standard Time
  • Asia/Kolkata - India Standard Time

API Methods

Events Management

// Add event
scheduler.addEvent(eventData);

// Update event
scheduler.updateEvent(eventId, updatedData);

// Delete event
scheduler.deleteEvent(eventId);

// Get all events
const events = scheduler.getEvents();

// Get events in date range
const events = scheduler.getEventsInRange(startDate, endDate);

View Management

// Change view
scheduler.changeView('month');

// Navigate to specific date
scheduler.goToDate(new Date('2026-02-01'));

// Refresh display
scheduler.refresh();

Import/Export

// Export to iCalendar format
const icalData = scheduler.exportToICal();

// Import from iCalendar
scheduler.importFromICal(icalString);

// Export to JSON
const jsonData = JSON.stringify(scheduler.getEvents());

Event Callbacks

const scheduler = new Scheduler.default({
  container: '#scheduler-container',
  
  // Called when an event is created
  onEventCreate: (event) => {
    console.log('Event created:', event);
  },
  
  // Called when an event is updated
  onEventUpdate: (eventId, updatedData) => {
    console.log('Event updated:', eventId, updatedData);
  },
  
  // Called when an event is deleted
  onEventDelete: (eventId) => {
    console.log('Event deleted:', eventId);
  },
  
  // Called when view changes
  onViewChange: (view) => {
    console.log('View changed to:', view);
  },
  
  // Called when date changes
  onDateChange: (date) => {
    console.log('Date changed to:', date);
  },
  
  // Called when a time slot is clicked
  onSlotClick: (slotInfo) => {
    console.log('Slot clicked:', slotInfo);
  }
});

Styling

The scheduler uses CSS custom properties for easy theming:

:root {
  --sch-color-calendar: #4f46e5;
  --sch-color-event-normal: #716ae9;
  --sch-color-event-recurring: #c43081;
  --sch-color-bg-main: #fff;
  --sch-color-border: #e5e7eb;
  --sch-color-text: #111827;
}

Browser Support

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

License

ISC

Contributing

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