2.4.2 • Published 7 months ago

v-calendar v2.4.2

Weekly downloads
72,747
License
MIT
Repository
github
Last release
7 months ago

Welcome to V-Calendar

V-Calendar is a clean and lightweight plugin for displaying simple, attributed calendars in Vue.js. It uses attributes to decorate the calendar with various visual indicators including highlighted date regions, dots, bars, content styles and popovers for simple tooltips and even custom slot content.

Any single attribute may contain one of each object and can be displayed for single dates, date ranges and even complex date patterns like every other Friday, the 15th of every month or the last Friday of every other month.

It has date picker support out of the box with single date, multiple date and date range selection modes. Because v-date-picker is simply a wrapper for v-calendar, both can be extensively customized using props, slots and theme styling, just like v-calendar. And of course, V-Calendar is responsive and mobile friendly. For example, it supports touch swipes for month navigation.

Calendar

v-calendar is the core component. By default, it has a neutral design that should blend nicely within any web application, with various options for configuring the basic layout:

  • Single or double paned
  • Can be expanded to fill the width of its container
  • Header title can be left, right or center-aligned
  • Slot support for custom header and header subcomponents
  • Navigation transitions (horizontal slide, vertical slide, fade)

Along with the calendar panes, v-calendar employs a semantic-inspired navigation pane when the header title is hovered or focused by the user.

Attributes

Attributes are the most important concept to understand. They provide a powerful way to communicate visual information to your users quickly and effectively. Fortunately, they are also easy to specify.

What to display

The first thing to understand about attributes is what they are capable of displaying.

  • Highlights
  • Dot Indicators
  • Bar Indicators
  • Popovers
  • Content Styles

For now, let's just start by displaying a simple highlight on today's date.

<template>
  <v-calendar :attributes='attrs'>
  </v-calendar>
</template>
export default {
  data() {
    return {
      attrs: [
        {
          key: 'today',
          highlight: {
            backgroundColor: '#ff8080',
            // Other properties are available too, like `height` & `borderRadius`
          },
          dates: new Date(2018, 0, 1)
        }
      ],
    };
  },
};

To add some contrast to the highlighted date, we can use a content style, which is simply a style object that gets applied to the day content text.

export default {
  data() {
    return {
      attrs: [
        {
          key: 'today',
          highlight: {
            backgroundColor: '#ff8080',
          },
          // Just use a normal style
          contentStyle: {
            color: '#fafafa',
          },
          dates: new Date(2018, 0, 1)
        },
      ],
    };
  },
};

Finally, let's see how simple it is to add a popover label (or tooltip) to the calendar when this highlight is hovered over. To do that, we just need to add a popover section to our attribute.

export default {
  data() {
    return {
      attrs: [
        {
          key: 'today',
          dates: new Date(2018, 0, 1),
          highlight: {
            backgroundColor: '#ff8080',
          },
          // Just use a normal style
          contentStyle: {
            color: '#fafafa',
          },
          // Our new popover here
          popover: {
            label: 'You just hovered over today\'s date!',
          }
        },
      ],
    };
  },
};

Where to display

The second aspect of attributes is specifying where to display them. In the previous example, we saw that all we had to do was use a simple date object assigned to the dates property. Note that we aren't limited to using single date or date range objects. We can also use an array of dates.

  ...
  dates: [ new Date(2018, 0, 1), new Date(2018, 0, 15) ]
  ...

Or date ranges...

  ...
  dates: [
    { start: new Date(2018, 0, 1), end: new Date(2018, 0, 5) },
    { start: new Date(2018, 0, 15), span: 5 } // Span is number of days
  ]
  ...

Or date patterns.

  ...
  dates: { weekdays: [1, 7] } // On the weekends
  ...

Date Picker

The v-date-picker component is a flexible date picker component wrapper around v-calendar, which means it supports all props and events that v-calendar does. Using the mode prop, it is capable of 3 selection modes:

  • Single dates
  • Multiple dates
  • Date ranges

Date pickers can be displayed inline or as a popover for an input element which can be classed or styled.

<v-date-picker
  mode='range'
  v-model='selectedDate'
  show-caps>
</v-date-picker>
export default {
  data() {
    return {
      selectedDate: {
        start: new Date(2018, 0, 9),
        end: new Date(2018, 0, 18)
      }
    };
  },
};

Also, a custom slot element can be used to display your own input element. This example uses Buefy for a custom styled input component.

<v-date-picker
  mode='single'
  v-model='selectedDate'>
  <b-field :type='inputState.type' slot-scope='props'>
    <b-input
      type='text'
      icon='calendar'
      :value='props.inputValue'
      :placeholder='inputState.message'
      @change.native='props.updateValue($event.target.value)'
      expanded>
    </b-input>
    <p
      class='control'
      v-if='selectedValue'>
      <a
        :class='["button", inputState.type]'
        @click='selectedValue = null'>
        Clear
      </a>
    </p>
  </b-field>
</v-date-picker>
export default {
  data() {
    return {
      selectedDate: new Date(2018, 0, 10)
    };
  },
  computed: {
    inputState() {
      if (!this.selectedValue) {
        return {
          type: 'is-danger',
          message: 'Date required.',
        };
      }
      return {
        type: 'is-primary',
        message: '',
      };
    },
  },
};

You can disable dates, date ranges and date patterns using the following props:

  • Explicitly via min-date or max-date
    <!--Set minimum date-->
    <v-date-picker
      :min-date='new Date()'
      v-model='selectedDate'>
    </v-date-picker>
  • Explicitly via disabled-dates (still works with min-date or max-date).
    <!--Disable weekend selection-->
    <v-date-picker
      :disabled-dates='{ weekdays: [1, 7] }'
      v-model='selectedDate'>
    </v-date-picker>
  • Implicitly via available-dates. Any dates not included in available-dates are disabled.
    <!--Today is the minimum date (null denotes infinite date)-->
    <v-date-picker
      :available-dates='{ start: new Date(), end: null }'
      v-model='selectedDate'>
    </v-date-picker>

Formatting & Parsing

Dates are formatted and/or parsed for the following component sections:

Component(s)Target AreaDefault Mask
v-calendar v-date-pickerCalendar header titleMMMM YYYY
v-calendar v-date-pickerWeekday headersW
v-calendar v-date-pickerMonth labels in navigation dropdownMMM
v-date-pickerInput element when is-inline === falseL
v-date-pickerDay popover when user hovers selected dateWWW, MMM D, YYYY

By default, v-calendar uses Javascript's Internalization API (which is increasingly well supported) to derive the month and weekday names for the user's locale. This helps keep the package size to a minimum while utilizing an API that should only improve with time. It also uses the most appropriate long date mask (L) for that locale (derived from moment.js).

To use your own custom masks, configure and pass the masks object

  • As a prop to v-calendar or v-date-picker
<v-date-picker
  :masks='masks'
  v-model='myDate'>
</v-date-picker>
export default {
  data() {
    return {
      myDate: null,
      masks: {
        title: 'MMMM YYYY',
        weekdays: 'W',
        navMonths: 'MMM',
        input: ['L', 'YYYY-MM-DD', 'YYYY/MM/DD'], // Only for `v-date-picker`
        dayPopover: 'L', // Only for `v-date-picker`
      }
    }
  }
}
  • As a default when using VCalendar
import Vue from 'vue'
import VCalendar from 'v-calendar'

Vue.use(VCalendar, {
  masks: {
    title: 'MMMM YYYY',
    weekdays: 'W',
    navMonths: 'MMM',
    input: ['L', 'YYYY-MM-DD', 'YYYY/MM/DD'],
    dayPopover: 'L',
  }
})

Parsing dates for input element

You'll notice an array was used to specify the masks for v-date-picker's input element. This is because it uses the supplied format(s) to parse, as well as display, the selected date. The first supplied format is used to display the date selection, while all masks can be used to parse the date string. The first successfully parsed date is used as the selected date. This provides more flexibility for the user when manually typing in dates.

By default, v-date-picker will first try and use the localized long date format to parse the date, but will also try to parse masks that are globally unambiguous (YYYY-MM-DD and YYYY/MM/DD). Furthermore, because v-date-picker uses its own parsing logic (rather than relying on the browser's inconsistent Date.parse function), it can properly parse ISO-8601 dates to the user's local time zone instead of converting to UTC. If you plan on targeting browsers from multiple locales, it is probably best to defer to the default format settings.

Format Tokens

Use the following tokens to configure your custom masks:

CategoryTokenOutput
MonthM1, 2, ..., 12
MM01, 02, ..., 12
MMMJan, Feb, ..., Dec
MMMMJanuary, February, ..., December
Day of MonthD1, 2, ..., 31
DD01, 02, ..., 31
Do1st, 2nd, ..., 31st
Day of Weekd1, 2, ..., 7
d1, 2, ..., 7
dd01, 02, ..., 07
WS, M, ..., S
WWSu, Mo, ..., Sa
WWWSun, Mon, ..., Sat
WWWWSunday, Monday, ..., Saturday
YearYY70, 71, ... 69
YYYY1970, 1971, ..., 2069
Long DateL01/21/1983 (en-US), 21/01/1983 (en-GB), ..., 1983/01/21 (civilized)

I18n

VCalendar utilizes the well supported Internationalization API to derive month and weekday names and formatting. This helps keep the package size down, as well as supporting multiple locales in the most performant and isomorphic way.

At the moment, this API still cannot provide all recommended default settings per locale (such as 'first day of the week'), so those settings are provided out of the box for a reasonable number of locales, with a decent fallback for those locales that aren't included.

With all of this in mind, it is probably best that you rely on the the plugin's built-in methods for detecting the user's locale. However, if you would like to force a specific locale for all users, you may supply your own default locale using the language-region format.


Installation

Vue.js version 2.5+ is required.

1 Install via npm

npm install v-calendar

2 Import and use VCalendar

2A. Plugin Method (Recommended)

This is the most common use case.

import Vue from 'vue';
import VCalendar from 'v-calendar';
import 'v-calendar/lib/v-calendar.min.css';

// Use v-calendar, v-date-picker & v-popover components
Vue.use(VCalendar, {
  firstDayOfWeek: 2,  // Monday
  ...,                // ...other defaults
});

2B. Components Method

Or, you can just import and use the calendar if you don't need the v-date-picker or v-popover components. Keep in mind that setupCalendar still needs to be called (passing optional defaults) using this method.

import Vue from 'vue';
import { setupCalendar, Calendar} from 'v-calendar'
import 'v-calendar/lib/v-calendar.min.css';

// Remember to setup calendar (passing in defaults if needed)
setupCalendar({
  firstDayOfWeek: 2,  // Monday,
  ...,                // ...other defaults
});

// Register component(s)
Vue.component('v-calendar', Calendar);

3 Reference in your component templates

<template>
  <v-calendar>
  </v-calendar>
  <v-date-picker
    mode='single'
    v-model='selectedValue'>
  </v-date-picker>
</template>
<script>
export default {
  data() {
    return {
      selectedValue: new Date(),
    };
  },
};
</script>

Or use a CDN

<html>
  <head>
    <meta charset='utf-8'>
    <meta name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no'>
    <meta http-equiv='x-ua-compatible' content='ie=edge'>
    <!--1. Link VCalendar CSS-->
    <link rel='stylesheet' href='https://unpkg.com/v-calendar/lib/v-calendar.min.css'>
  </head>
  <body>
    <div id='app'>
      <v-calendar></v-calendar>
      <v-date-picker :mode='mode' v-model='selectedDate'></v-date-picker>
    </div>
    <!--2. Link Vue Javascript-->
    <script src='https://unpkg.com/vue/dist/vue.js'></script>
    <!--3. Link VCalendar Javascript (Plugin automatically installed)-->
    <script src='https://unpkg.com/v-calendar'></script>
    <!--4. Create the Vue instance-->
    <script>
      new Vue({
        el: '#app',
        data: {
          // Data used by the date picker
          mode: 'single',
          selectedDate: null,
        }
      })
    </script>
  </body>
</html>

Polyfill

v-calendar is transpiled for ES5, but it still needs a polyfill for Array.prototype.find (<= IE11) or even Intl (Javascript's internationalization object, <= IE10) if you wish to target older browsers. Two options for accomplishing this are: 1. Easy way: Insert the following script into your html before loading v-calendar. The polyfill will get loaded automatically only if the browser needs it.

<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=Array.prototype.find,Intl" />

  1. In Node/Browserify/Webpack environments, use babel-polyfill to insert the polyfill for you.

Custom Defaults

Custom defaults can be provided on initialization. Note that almost all of these defaults can be overridden by props on v-calendar or v-date-picker components.

Vue.use(VCalendar, {
  firstDayOfWeek: 2, // Set first day of week to Monday
  ...
})
Property NameTypeDescriptionDefault
localeStringLocale identification in language-region format. Not all regions supported.undefined
componentPrefixStringCustom prefix to use for plugin components. Replace if v-calendar and v-date-picker interfere with other component libraries."v"
firstDayOfWeekNumberDay number for the first day of the week (1: Sun - 7: Sat)1
masksObjectMasks to use when display and parsing dates for various calendar sectionsReference code
navVisibilityStringVisibility state for calendar navigation panel ("focus", "hover", "visible", "hidden")"focus"
titlePositionStringPosition of the title in the header ("left", "center", "right")"center"
transitionStringTransition type when navigating to a new page ("slide-h", "slide-v", "fade", "none")"slide-h"
popoverExpandedBooleanPopover wrapper for input or slot is expanded to the full width of its container.false
popoverDirectionStringDirection that popover displays relative to input or slot element ("bottom", "top", "left", "right")"bottom"
popoverAlignStringHow the popover is aligned relative to input or slot element ("left", "right", "top", "bottom"')"left"
popoverVisibilityStringVisibility state of the popover ("hover", "focus", "hidden", "visible")"hover"
popoverContentOffsetStringDistance that the popover content is offset from the input or slot element"10px
popoverKeepVisibleOnInputBooleanKeep the popover visible after a valid input has been selectedfalse
maxSwipeTimeNumberMaximum time in milliseconds allowed for a swipe gesture to complete300
minHorizontalSwipeDistanceNumberMinimum distance in pixels allowed for a horizontal swipe gesture60
maxVerticalSwipeDistanceNumberMaximum distance in pixels allowed for a horizontal swipe gesture80
maxTapToleranceNumberMaximum distance in pixels allowed for a tap between touchstart and touchend events0
maxTapDurationNumberMaximum time in milliseconds allowed for a tap between touchstart and touchend events200
@saviway/ui@kong/kongponents@leaflink/stashquasar-app-extension-q-date-filterlukitnolanpro-spark-screen-builderbooking-calendarvue-form-builder-fixedpegadaian-components@fanswoo/framework-front-core@prefix/studio-editornboard-ui@villageco/nebula@infinitebrahmanuniverse/nolb-v-c@troyanym/front-ui@willry/teste@everything-registry/sub-chunk-3036@felix-health/vue-components-vue2move-ui-vueembeded-vueestiavue-solydform-elementsvue-pro-calendarvue-query-datatablevue-test-demo-onewatchtower-benefits-shared-componentsoctopus-dash-componentsvuero@pequity/squirrel-poc@pequity/squirrel@ponypharmacist/atlas-components@ponypharmacist/atlas-ui-kitwcd-form-collection-vueoswedev@salthq/admin-component-lib@samk-dev/nuxt-vcalendar@poesial/hub-uiwebcc-componentswebcc-ui-components@processmaker/vue-form-builder@kurukururuu/ramen-adonis-pagination-component@mptw/skylens-ui@loophq/component-library@onereach/webformvue-cli-plugin-fence-vuevue-formulate-calendarvue-formulate-vcalendarvue-boothelpvue-agile-calendarmlh-kitmlh-ui-kitcdcd@evoltis/sigura3-common-uicavea-componentsmobiotics-dynamic-components-vuev-ferry-components@kongponents/kdatetimepicker@kobevantreek/calendar-injectdapp-ui-nuxt@netwatch-global/uicrs_layer@neon.id/field@ran-guin/timer@ran-guin/vue-components@rebilly/recomponentsplatforma-ui@ruvents/leader-id-uikit@pixelforcesystems/form-builder@phila/phila-ui@pergel/module-boxodd-ds@perevorot/shop@platforma/core@soft-stech/bootsman-ui-shadcnpiijt-components@kippsaude/components@lbgm/pro-calendar-vuecug-shopcw-componentcw-component-vue3@oragroup/andsons-uidiscovery-treevue-vi-uibw-materialmeidenfx-webuimektepplusclasscard-ui@felix-health/vue-components@felix-health/vue-components-vue3@internethic/oparedo-ui@ipscape/ips-calendarmsa-template-nuxt3titane@iflat.io/iflat-room-selection@jbmchd-vue/jb-bootstrapvue-extends@jbmchd-vue/jb-vuetify-extendsnboard-ui-ratanboard-ui-red@quentin.marechal/vue-davra-ui@roketin-library/frontend-kit
2.4.2

7 months ago

3.1.2

7 months ago

3.1.1

7 months ago

3.1.0

7 months ago

3.0.3

1 year ago

3.0.2

1 year ago

3.0.1

1 year ago

3.0.0

1 year ago

3.0.0-alpha.7

2 years ago

3.0.0-alpha.8

2 years ago

2.4.1

2 years ago

2.4.0

2 years ago

3.0.0-alpha.6

3 years ago

2.3.4

3 years ago

2.3.3

3 years ago

2.3.2

3 years ago

2.3.1

3 years ago

3.0.0-alpha.5

3 years ago

3.0.0-alpha.4

3 years ago

2.3.0

3 years ago

2.2.4

3 years ago

2.2.3

3 years ago

2.2.2

3 years ago

2.2.1

3 years ago

2.2.0

3 years ago

2.1.6

3 years ago

3.0.0-alpha.3

3 years ago

2.1.4

3 years ago

2.1.5

3 years ago

2.1.3

3 years ago

2.1.2

3 years ago

3.0.0-alpha.2

3 years ago

3.0.0-alpha.1

3 years ago

3.0.0-alpha.0

3 years ago

2.1.1

3 years ago

2.1.0

3 years ago

2.0.2

3 years ago

2.0.1

4 years ago

2.0.0

4 years ago

2.0.0-beta.0

4 years ago

1.1.0-beta.2

4 years ago

1.1.1

4 years ago

1.1.0

4 years ago

1.1.0-beta.1

4 years ago

1.1.0-beta.0

4 years ago

1.0.8

4 years ago

1.0.7

4 years ago

1.0.7-beta.0

4 years ago

1.0.6

4 years ago

1.0.5

4 years ago

1.0.4

4 years ago

1.0.3

4 years ago

1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago

1.0.0-beta.23

4 years ago

1.0.0-beta.22

5 years ago

1.0.0-beta.21

5 years ago

1.0.0-beta.20

5 years ago

1.0.0-beta.19

5 years ago

1.0.0-beta.18

5 years ago

1.0.0-beta.17

5 years ago

1.0.0-beta.16

5 years ago

1.0.0-beta.15

5 years ago

1.0.0-beta.14

5 years ago

1.0.0-beta.13

5 years ago

1.0.0-beta.12

5 years ago

1.0.0-beta.11

5 years ago

1.0.0-beta.10

5 years ago

1.0.0-beta.9

5 years ago

1.0.0-beta.8

5 years ago

1.0.0-beta.7

5 years ago

1.0.0-beta.6

5 years ago

1.0.0-beta.5

5 years ago

1.0.0-beta.4

5 years ago

1.0.0-beta.3

5 years ago

1.0.0-beta.2

5 years ago

1.0.0-beta.1

5 years ago

1.0.0-beta.0

5 years ago

0.9.7

6 years ago

0.9.6

6 years ago

0.9.5

6 years ago

0.9.4

6 years ago

0.9.3

6 years ago

0.9.2

6 years ago

0.9.1

6 years ago

0.9.0

6 years ago

0.8.0

6 years ago

0.7.5

6 years ago

0.7.4

6 years ago

0.7.3

6 years ago

0.7.2

6 years ago

0.7.1

6 years ago

0.7.0

6 years ago

0.6.3

6 years ago

0.6.2

6 years ago

0.6.1

6 years ago

0.6.0

6 years ago

0.5.5

6 years ago

0.5.4

6 years ago

0.5.3

6 years ago

0.5.2

6 years ago

0.5.1

6 years ago

0.5.0

6 years ago

0.4.3

6 years ago

0.4.2

6 years ago

0.4.1

6 years ago

0.4.0

6 years ago

0.3.2

6 years ago

0.3.1

6 years ago

0.3.0

6 years ago

0.2.2

6 years ago

0.2.1

6 years ago

0.2.0

6 years ago

0.1.1

6 years ago

0.1.0

6 years ago

0.0.9

6 years ago

0.0.8

6 years ago

0.0.7

6 years ago

0.0.6

7 years ago

0.0.5

7 years ago

0.0.4

7 years ago

0.0.3

7 years ago

0.0.2

7 years ago

0.0.1

7 years ago