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

@comperio/vue2-multi-select-calendar

v1.17.0

Published

A Vue2 calendar with event support and multiple selection

Readme

Vue2 Multi Select Calendar

Vue2 calendar with event support and multiple selection.

Table of Contents

Installation

npm install @comperio/vue2-multi-select-calendar

Basic Usage

/* Import both variables and styles */
import '@comperio/vue2-multi-select-calendar/dist/style.css';

/* Or define your own variables and import only the styles */
:root {
  /* your custom variables here */
}
import '@comperio/vue2-multi-select-calendar/dist/styles.css';
import { MultiDatePicker } from "@comperio/vue2-multi-select-calendar";

// As a component
export default {
  components: {
    MultiDatePicker,
  },
};

// As a plugin
import { VueCalendarPlugin } from "@comperio/vue2-multi-select-calendar";
Vue.use(VueCalendarPlugin);

// Usage Example
<template>
  <multi-date-picker
    :events="events"
    :pre-selected-dates="preSelectedDates"
    @update:busy="onBusyUpdate"
    @update:selected="onSelectionUpdate"
    @event-hover="onEventHover"
    @event-leave="onEventLeave"
  >
    <template #tooltip="{ data }">
      <div class="custom-tooltip">
        <strong>{{ data?.note }}</strong>
      </div>
    </template>
  </multi-date-picker>
</template>

<script>
export default {
  data() {
    return {
      events: [
        {
          date: new Date("2024-02-22"),
          data: { note: "Important meeting" },
        },
      ],
      preSelectedDates: [new Date("2024-02-22")],
      hoveredEvent: null,
    };
  },
  methods: {
    onBusyUpdate(selectedBusyDates) {
      console.log("Selected busy dates:", selectedBusyDates);
    },
    onSelectionUpdate(selectedFreeDates) {
      console.log("Selected free dates:", selectedFreeDates);
    },
    onEventHover(event) {
      this.hoveredEvent = event;
      // Lazy load additional data
      setTimeout(() => {
        if (this.hoveredEvent && this.hoveredEvent.date.getTime() === event.date.getTime()) {
          this.hoveredEvent.data.additionalInfo = "Lazy loaded data";
          this.hoveredEvent = { ...this.hoveredEvent };
        }
      }, 500);
    },
    onEventLeave() {
      this.hoveredEvent = null;
    },
  },
};
</script>

Props

Core Props

  • events: CalendarDate[] - Array of events to display in the calendar. Each event contains:

    • date: Date - Event date
    • data: any - Additional data associated with the event (e.g., notes, title) Events are displayed as "busy" days with a distinctive style.
  • preSelectedDates: Date[] - Array of pre-selected dates. Behavior varies based on the number of dates:

    • Single date: always selected
    • Multiple dates: only dates matching busy days (present in events) are selected
    • Empty array: no dates selected Note: setting this prop overrides any current selection.

Display Props

  • year: number | null - The year to initialize the calendar with. If provided, the calendar will start from January 1st of this year. If null, the calendar will start from the current date. (default: null)
  • years: number[] - An array of years to allow navigation between. If provided, the year navigator will only allow switching between these years. If empty, navigation is unrestricted. (default: [])
  • numberOfMonths: number - Number of months to display (default: 1). Valid values are between 1 and 12.
  • showNavigator: boolean - Show month navigator (default: true)
  • showYearNavigator: boolean - Show year navigator (default: true)
  • showMonthLabels: boolean - Show month labels (default: true)
  • showNextMonthDays: boolean - Show days from next month (default: true)
  • showPreviousMonthDays: boolean - Show days from previous month (default: true)

Internationalization (i18n) Props

  • i18n: I18n | null - An object containing translations for month names and weekday abbreviations. If null, default (Italian) translations are used. (default: null) The structure of the I18n object should be:
    interface I18n {
      months?: {
        [monthKey: string]: { [langKey: string]: string }; // e.g., january: { en: "January", it: "Gennaio" }
      };
      weekDaysShort?: {
        [dayKey: string]: { [langKey: string]: string }; // e.g., monday: { en: "Mon", it: "Lun" }
      };
    }
  • language: Language - A string specifying the current language (e.g., "en", "it", "de"). This key is used to pick the correct translation from the i18n object. (default: "it")

Move Restriction Props

  • enableMoveRestriction: boolean - Enables the move restriction feature (default: false). When true, and an event (a busy day) is selected, attempting to move it to a day outside the defined minMovableDate and maxMovableDate will be prevented.
  • minMovableDate: Date | null - The earliest date an event can be moved to (default: null). If null, there is no minimum date restriction for moving.
  • maxMovableDate: Date | null - The latest date an event can be moved to (default: null). If null, there is no maximum date restriction for moving.

Slots

  • tooltip - Custom tooltip content
<multi-date-picker>
  <template #tooltip="event">
    <div class="custom-tooltip">
      <strong>custom tooltip</strong>
      <p>
        <strong>{{ event?.data?.note }}</strong>
      </p>
    </div>
  </template>
</multi-date-picker>
  • year-navigator - Provides a custom UI for year navigation, replacing the default navigator. The slot is provided with the following properties:

    • currentYear (number): The currently displayed year.
    • previousYear (function): A function to navigate to the previous year.
    • nextYear (function): A function to navigate to the next year.
    <multi-date-picker>
      <template #year-navigator="{ currentYear, previousYear, nextYear }">
        <div class="custom-year-nav">
          <button @click="previousYear">&lt;&lt;</button>
          <span>Year: {{ currentYear }}</span>
          <button @click="nextYear">&gt;&gt;</button>
        </div>
      </template>
    </multi-date-picker>

Events

  • @update:busy - Emitted when busy days are selected
  • @update:selected - Emitted when free days are selected
  • @event-hover - Emitted when the mouse enters an event
  • @event-leave - Emitted when the mouse leaves an event
  • @month-change - Emitted when the visible month is changed via the navigator. The payload is the name of the new month (string).
  • @year-change - Emitted when the visible year is changed via the navigator. The payload is the new year (number).
  • @move-restricted - Emitted when enableMoveRestriction is true and an attempt is made to move an event to a date outside the minMovableDate or maxMovableDate. The payload includes { date: Date, day: CalendarDay } corresponding to the restricted target date.
  • @click-outside - Emitted when a click occurs outside the calendar component. The payload is the native MouseEvent.

Lazy Loading Event Details

The calendar provides hover events that allow you to implement lazy loading of event details:

<template>
  <div>
    <multi-date-picker
      :events="events"
      @event-hover="onEventHover"
      @event-leave="onEventLeave"
    />

    <div v-if="hoveredEvent" class="event-details">
      <h3>{{ hoveredEvent.data.note }}</h3>
      <p v-if="hoveredEvent.data.additionalInfo">
        {{ hoveredEvent.data.additionalInfo }}
      </p>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      events: [...],
      hoveredEvent: null
    }
  },
  methods: {
    onEventHover(event) {
      this.hoveredEvent = event;

      // Simulate API call to load additional data
      setTimeout(() => {
        if (this.hoveredEvent && this.hoveredEvent.date.getTime() === event.date.getTime()) {
          this.hoveredEvent.data.additionalInfo = "Loaded from API";
          // Force reactivity update
          this.hoveredEvent = { ...this.hoveredEvent };
        }
      }, 500);
    },
    onEventLeave() {
      this.hoveredEvent = null;
    }
  }
}
</script>

CSS Variables

--v-cal-font-family: Arial, sans-serif;
--v-cal-border-color: #ddd;
--v-cal-background: white;
--v-cal-text-color: #2c3e50;
--v-cal-past-color: #ddd;
--v-cal-other-month-color: #999;
--v-cal-selected-background: #4caf50;
--v-cal-selected-color: white;
--v-cal-selected-border-color: #81c784;
--v-cal-hover-background: #f0f0f0;
--v-cal-header-background: #f0f0f0;
--v-cal-year-nav-background: #e8e8e8;
--v-cal-weekday-background: #f8f8f8;
--v-cal-month-label-color: #666;
--v-cal-grid-gap: 1px;
--v-cal-padding: 10px;
--v-cal-month-width: 300px;
--v-cal-font-size: 0.9em;
--v-cal-button-hover: rgba(0, 0, 0, 0.05);
--v-cal-tooltip-background: rgba(0, 0, 0, 0.8);
--v-cal-tooltip-color: white;
--v-cal-unmovable-target-background: #eeeeee; /* Background color for days that are not valid move targets when move restriction is active. Applied to free days via the .v-cal-is-unmovable-target class. */

Types

interface CalendarDate<T = any> {
  date: Date;
  data: T;
}

interface CalendarDay {
  date: Date;
  dayNumber: number;
  isCurrentMonth: boolean;
}

interface I18n {
  months?: {
    [monthKey: string]: { [langKey: string]: string };
  };
  weekDaysShort?: {
    [dayKey: string]: { [langKey: string]: string };
  };
}

type Language = "it" | "en" | "de" | string; // Allow for other language codes

The CalendarDate interface is used for both the events prop and the emitted events. The generic type T allows you to specify the type of the data property. The I18n interface defines the structure for providing translations. The Language type is a string union for supported languages, but can also be any string if you provide corresponding translations in the i18n object.

Available Scripts

In the project directory, you can run the following scripts:

  • pnpm dev or npm run dev Runs the app in development mode using Vite. Open http://localhost:5173 (or the port shown in your terminal) to view it in the browser.

  • pnpm test or npm run test Executes the Playwright tests for the application.

  • pnpm type-check or npm run type-check Runs the TypeScript compiler (vue-tsc) to check for type errors in the project without emitting JavaScript files.

  • pnpm build or npm run build Builds the app for production to the dist folder. It first runs type-check and then uses Vite to bundle the library.

  • pnpm build:dev or npm run build:dev Creates a development build with source maps enabled for easier debugging. It sets KEEP_SOURCE_MAP=true before running the standard build process.

  • pnpm bump-version:patch or npm run bump-version:patch Increments the patch version of the package (e.g., 1.0.0 -> 1.0.1).

  • pnpm bump-version:minor or npm run bump-version:minor Increments the minor version of the package (e.g., 1.0.0 -> 1.1.0).

  • pnpm bump-version:major or npm run bump-version:major Increments the major version of the package (e.g., 1.0.0 -> 2.0.0).

  • pnpm serve or npm run serve Serves the production build locally using Vite's preview mode. This is useful for checking the production build before deployment.

  • pnpm publish:dry-run or npm run publish:dry-run Performs a dry run of the publishing process. It builds the project and then simulates publishing to npm without actually making changes to the registry.

  • pnpm publish:prod or npm run publish:prod Builds the project and then publishes it to npm.

  • pnpm release:patch or npm run release:patch Automates a patch release: bumps the patch version, commits, pushes the commit, and pushes the new tag.

  • pnpm release:minor or npm run release:minor Automates a minor release: bumps the minor version, commits, pushes the commit, and pushes the new tag.

  • pnpm release:major or npm run release:major Automates a major release: bumps the major version, commits, pushes the commit, and pushes the new tag.

(Note: The _commit-and-push-tag script is an internal helper for the release scripts and is not typically run directly.)