├── .travis.yml
├── src
├── .babelrc
├── config
│ └── defaults.js
├── index.js
├── mixins
│ └── i18n.js
├── utils
│ ├── language-validator.js
│ ├── languages.js
│ └── calendar.js
└── components
│ ├── events-box.vue
│ ├── calendar.vue
│ ├── calendar-header.vue
│ └── calendar-body.vue
├── config
├── dev.env.js
└── prod.env.js
├── .editorconfig
├── index.dev.html
├── .gitignore
├── dev
├── index.js
├── data
│ ├── language-nl.js
│ └── data-generator.js
└── App.vue
├── index.html
├── docs
├── config.md
├── languages.md
├── properties.md
└── events.md
├── dist
├── event-calendar.css
└── vue-calendar.js
├── test
└── language-validator.test.js
├── package.json
└── README.md
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "6"
4 | - "6.1"
5 | - "5.11"
6 |
--------------------------------------------------------------------------------
/src/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env"],
4 | "stage-2"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/config/dev.env.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | dev: {
3 | entry: './dev/index.js',
4 | env: {
5 | NODE_ENV: '"development"'
6 | },
7 | server: {
8 | port: 8080
9 | }
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/src/config/defaults.js:
--------------------------------------------------------------------------------
1 | export default {
2 | firstDay: 0,
3 | showLimit: 3,
4 | locale: 'en',
5 | fullDayNames: false,
6 | fullMonthNames: false,
7 | class: 'vue-calendar',
8 | componentName: 'vue-calendar'
9 | };
10 |
--------------------------------------------------------------------------------
/config/prod.env.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | prod: {
3 | entry: './src/index.js',
4 | lib: 'vue-calendar.js',
5 | extensions: ['.js', '.vue', '.json'],
6 | env: {
7 | NODE_ENV: '"development"'
8 | }
9 | }
10 | };
11 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | ; top-most EditorConfig file
2 | root = true
3 |
4 | ; Unix-style newlines
5 | [*]
6 | end_of_line = LF
7 |
8 | [*.{yml}]
9 | indent_style = space
10 | indent_size = 4
11 |
12 | [*.{html,js,vue}]
13 | indent_style = space
14 | indent_size = 2
15 |
--------------------------------------------------------------------------------
/index.dev.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | development page
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | npm-debug.log*
3 | yarn-debug.log*
4 | yarn-error.log*
5 |
6 | # Editor directories and files
7 | .idea
8 | .vscode
9 | *.suo
10 | *.ntvs*
11 | *.njsproj
12 | *.sln
13 |
14 | ### Sass ###
15 | *.sass-cache/
16 | *.css.map
17 |
18 | ## npm ##
19 | node_modules/
20 |
21 | ## Jest ##
22 | coverage/
23 |
--------------------------------------------------------------------------------
/dev/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import App from './App.vue';
3 | import calendar from '../src/index';
4 | import nl from './data/language-nl';
5 |
6 | Vue.config.productionTip = false;
7 |
8 | Vue.use(calendar, {
9 | firstDay: 1,
10 | locale: 'en',
11 | languages: { nl }
12 | });
13 |
14 | /* eslint-disable no-new */
15 | new Vue({
16 | el: '#app',
17 | render: h => h(App),
18 | template: '',
19 | components: {
20 | App
21 | }
22 | });
23 |
--------------------------------------------------------------------------------
/dev/data/language-nl.js:
--------------------------------------------------------------------------------
1 | export default {
2 | showMore: 'Toon meer',
3 | dayNameShort: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
4 | dayNameLong: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
5 | monthNameShort: ['jan', 'feb', 'mrt.', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
6 | monthNameLong: ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december']
7 | };
8 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Vue2 Calendar demo
5 |
6 |
7 |
8 |
11 |
12 |
13 |
14 |
15 |
16 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import defaults from './config/defaults';
4 | import languages from './utils/languages';
5 | import calendarComponent from './components/calendar.vue';
6 |
7 | function install(Vue, options = {}) {
8 | const calendarOptions = Object.assign(defaults, options);
9 |
10 | if (options.languages) {
11 | languages.addLanguage(options.languages);
12 | }
13 |
14 | const calendar = {
15 | eventBus: new Vue(),
16 | translations: languages.getTranslation(calendarOptions.locale)
17 | };
18 |
19 | Vue.prototype.$calendar = Object.assign(calendar, calendarOptions);
20 |
21 | Vue.component(calendarOptions.componentName, calendarComponent);
22 | }
23 |
24 | export default install;
25 |
26 | if (typeof module === 'object' && module.exports) {
27 | module.exports.install = install;
28 | }
29 |
--------------------------------------------------------------------------------
/src/mixins/i18n.js:
--------------------------------------------------------------------------------
1 | export default {
2 | data() {
3 | return {
4 | translations: this.$calendar.translations
5 | };
6 | },
7 | computed: {
8 | locale() {
9 | return this.$calendar.locale;
10 | },
11 | dayOffset() {
12 | return this.$calendar.firstDay;
13 | },
14 | showMoreLabel() {
15 | return this.translations.showMore;
16 | }
17 | },
18 | methods: {
19 | printDay(day) {
20 | let field = this.$calendar.fullDayNames ? 'dayNameLong' : 'dayNameShort';
21 | let dayIndex = parseInt(day + this.dayOffset) % 7;
22 |
23 | return this.translations[field][dayIndex];
24 | },
25 | printMonth(month) {
26 | let field = this.$calendar.fullMonthNames ? 'monthNameLong' : 'monthNameShort';
27 | return this.translations[field][month];
28 | }
29 | }
30 | };
31 |
--------------------------------------------------------------------------------
/dev/data/data-generator.js:
--------------------------------------------------------------------------------
1 | export default {
2 | mockDays(monthStart, monthEnd) {
3 | const dates = mapRandomDates(monthStart, (date) => { return date; });
4 |
5 | return { dates };
6 | },
7 | mockEvents: (monthStart, monthEnd) =>
8 | mapRandomDates(monthStart, (date) => newEvent('testEvent', date))
9 | };
10 |
11 | const mapRandomDates = (date, fn, limit = 15) => {
12 | let result = [];
13 | const month = date.getMonth();
14 | const year = date.getFullYear();
15 |
16 | let amount = getRandomNumber(limit);
17 | while (amount--) {
18 | const day = getRandomNumber(28);
19 | result.push(fn(new Date(year, month, day)));
20 | }
21 |
22 | return result;
23 | };
24 |
25 | const newEvent = (title, start = null, end = null) => ({
26 | title,
27 | start: start ? start.toString() : null,
28 | end: end ? end.toString() : null
29 | });
30 |
31 | const getRandomNumber = (upper) =>
32 | Math.floor(Math.random() * (upper - 1 + 1)) + 1;
33 |
--------------------------------------------------------------------------------
/docs/config.md:
--------------------------------------------------------------------------------
1 | # Configuration
2 |
3 | The component allows for the `app level` config to be overwritten on initialization. The config object is
4 | passed on initialization --> `Vue.use(calendar, { //config here })`.
5 |
6 | This is a example of the config object with all default values
7 | ```javascript
8 | {
9 | firstDay: 0,
10 | showLimit: 3,
11 | locale: 'en',
12 | fullDayNames: false,
13 | fullMonthNames: false,
14 | componentName: 'vue-calendar',
15 | languages: {}
16 | }
17 | ```
18 |
19 | * ***firstDay***: controls the with day is printed first, default is 0 = sunday and can be any number up to 6.
20 |
21 | * ***showLimit***: controls the maximum amount of events shown on a day.
22 |
23 | * ***locale***: calendar language, default available `en`, `ru`, `nl`, `zh`.
24 |
25 | * ***fullDayNames***: Display full day names instead of abbreviation.
26 |
27 | * ***fullMonthNames***: Display full month names instead of abbreviation.
28 |
29 | * ***componentName***: The name of the calendar component, incase of conflict it can be changed to you needs.
30 |
31 | * ***languages***: Add extra languages sets, see [languages](./languages.md) for more info.
32 |
--------------------------------------------------------------------------------
/dist/event-calendar.css:
--------------------------------------------------------------------------------
1 | .vue-calendar{display:grid;grid-template-rows:10% 90%;background:#fff;margin:0 auto}.calendar-header{align-items:center}.header-left,.header-right{flex:1}.header-center{flex:3;text-align:center}.title{margin:0 5px}.next-month,.prev-month{cursor:pointer}.calendar-body{display:grid;grid-template-rows:5% 95%}.days-header{display:grid;grid-auto-columns:14.25%;grid-template-areas:"a a a a a a a";border-top:1px solid #e0e0e0;border-left:1px solid #e0e0e0;border-bottom:1px solid #e0e0e0}.days-body{display:grid;grid-template-rows:auto}.day-number{text-align:right;margin-right:10px}.day-label{text-align:center;border-right:1px solid #e0e0e0}.week-row{display:grid;grid-template-areas:"a a a a a a a";grid-row-gap:5px;grid-auto-columns:14.25%;border-left:1px solid #e0e0e0}.week-day{padding:4px;border-right:1px solid #e0e0e0;border-bottom:1px solid #e0e0e0}.week-day.disabled{background-color:#f5f5f5}.week-day.not-current>.day-number{color:#c3c3c3}.week-day.today>.day-number{font-weight:700;color:red}.events{font-size:12px;cursor:pointer;padding:0 0 0 4px}.events .event{height:18px;line-height:18px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin:0 4px 2px 0;color:rgba(0,0,0,.87);background-color:#d4dcec}.events .more-link{color:rgba(0,0,0,.38)}
--------------------------------------------------------------------------------
/docs/languages.md:
--------------------------------------------------------------------------------
1 | # Languages
2 |
3 | The default plugin provides only 4 languages out of the box. But there is the possibility to add languages yourself.
4 | This is done through the config object on component initialization.
5 |
6 | ### Add language
7 |
8 | The component will check the `languages` property on the config object, and if it is set the languages will be added
9 | to the available languages.
10 |
11 | If the lang object is not in the correct format it will not be added so make sure to follow the shown format.
12 |
13 | ```javascript
14 | import vueCalendar from 'vue2-simple-calendar';
15 |
16 | // config object
17 | const config = {
18 | languages:
19 | nl: {
20 | showMore: 'Toon meer',
21 | dayNameShort: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
22 | dayNameLong: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
23 | monthNameShort: ['jan', 'feb', 'mrt.', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
24 | monthNameLong: ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december']
25 | }
26 | };
27 |
28 | // use the config with languages
29 | Vue.use(vueCalendar, config);
30 |
31 | ```
32 |
--------------------------------------------------------------------------------
/test/language-validator.test.js:
--------------------------------------------------------------------------------
1 | const validator = require('../src/utils/language-validator').default;
2 |
3 | /* eslint-disable */
4 |
5 | describe('When no parameters passes', () => {
6 | it('a empty array should be returned', () => {
7 | expect(validator()).toEqual([]);
8 | });
9 | });
10 |
11 | describe('When an empty object passed', () => {
12 | it('a empty array should be returned', () => {
13 | expect(validator({})).toEqual([]);
14 | });
15 | });
16 |
17 | describe('When passed empty language object', () => {
18 | it('should return an empty array since the en obj is invalid', () => {
19 | expect(validator({
20 | en: {
21 | // No further lang data
22 | }
23 | })).toEqual([]);
24 | });
25 | });
26 |
27 | describe('When a correct language object is passes', () => {
28 | it('should not return any error messages', () => {
29 | expect(validator({
30 | en: {
31 | showMore: 'Show more',
32 | dayNameShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
33 | dayNameLong: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
34 | monthNameShort: ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'June', 'July', 'Aug.', 'Sept.', 'Oct.', 'Nov.', 'Dec.'],
35 | monthNameLong: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
36 | }
37 | })).toEqual(['en']);
38 | });
39 | })
40 |
--------------------------------------------------------------------------------
/src/utils/language-validator.js:
--------------------------------------------------------------------------------
1 | const isArray = v => (Object.prototype.toString.call(v) === '[object Array]');
2 | const isObject = v => (Object.prototype.toString.call(v) === '[object Object]');
3 |
4 | /**
5 | * Validates a object against a passed schema
6 | */
7 | const validateScheme = (object, schema) =>
8 | Object.keys(schema).map(prop =>
9 | [prop, schema[prop](object[prop])]
10 | ).reduce((errors, pair) => {
11 | (!pair[1]) && errors.push(`${pair[0]} is invalid`);
12 | return errors;
13 | }, []);
14 |
15 | /**
16 | * Schema containing the rules for a lang object
17 | */
18 | const languageSchema = {
19 | showMore: val => (typeof val === 'string'),
20 |
21 | dayNameLong: val => (isArray(val) && val.length > 6),
22 | dayNameShort: val => (isArray(val) && val.length > 6),
23 |
24 | monthNameLong: val => (isArray(val) && val.length > 11),
25 | monthNameShort: val => (isArray(val) && val.length > 11)
26 | };
27 |
28 | /**
29 | * Validates a set of language objects and returns a list containing the keys
30 | * of valid objects.
31 | */
32 | export default (langObjects) => {
33 | if (!isObject(langObjects) || !Object.keys(langObjects).length) {
34 | return [];
35 | }
36 |
37 | return Object.keys(langObjects).map(key => [
38 | key,
39 | validateScheme(langObjects[key], languageSchema)
40 | ]).reduce((valid, pair) => {
41 | (pair[1].length === 0) && valid.push(pair[0]);
42 | return valid;
43 | }, []);
44 | };
45 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "license": "MIT",
3 | "version": "1.0.8",
4 | "author": "Trekels Vincent",
5 | "name": "vue2-simple-calendar",
6 | "main": "dist/vue-calendar.js",
7 | "description": "A simple event calendar component",
8 | "repository": "https://github.com/Trekels/vue2-calendar",
9 | "bugs": "https://github.com/Trekels/vue2-calendar/issues",
10 | "files": [
11 | "src",
12 | "dist/vue-calendar.js"
13 | ],
14 | "scripts": {
15 | "test": "jest --coverage",
16 | "build": "node build/build.js",
17 | "dev": "node build/dev-server.js"
18 | },
19 | "keywords": [
20 | "vue",
21 | "vuejs",
22 | "events",
23 | "calendar"
24 | ],
25 | "devDependencies": {
26 | "babel-core": "^6.26.0",
27 | "babel-jest": "^22.0.4",
28 | "babel-loader": "^7.1.2",
29 | "babel-preset-env": "^1.6.0",
30 | "babel-preset-stage-2": "^6.24.1",
31 | "chalk": "^2.1.0",
32 | "connect-history-api-fallback": "^1.3.0",
33 | "css-loader": "^0.28.6",
34 | "express": "^4.15.4",
35 | "extract-text-webpack-plugin": "^3.0.2",
36 | "friendly-errors-webpack-plugin": "^1.6.1",
37 | "html-webpack-plugin": "^2.30.1",
38 | "http-proxy-middleware": "^0.17.4",
39 | "jest": "^21.2.1",
40 | "node-sass": "^4.7.2",
41 | "ora": "^1.3.0",
42 | "sass-loader": "^6.0.6",
43 | "vue-loader": "^13.0.4",
44 | "vue-template-compiler": "^2.4.2",
45 | "webpack": "^3.10.0",
46 | "webpack-dev-middleware": "^1.12.0",
47 | "webpack-hot-middleware": "^2.18.2",
48 | "webpack-merge": "^4.1.0"
49 | },
50 | "dependencies": {
51 | "vue": "^2.4.2"
52 | },
53 | "jest": {
54 | "transform": {
55 | "^.+\\.js$": "babel-jest"
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/dev/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
69 |
--------------------------------------------------------------------------------
/src/components/events-box.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 | {{ event.title }}
12 |
13 |
14 |
15 | {{ showMoreCount }}
16 | {{ showMoreLabel }}
17 |
18 |
19 |
20 |
21 |
65 |
66 |
87 |
--------------------------------------------------------------------------------
/docs/properties.md:
--------------------------------------------------------------------------------
1 | # Properties
2 |
3 | Data can be passed to the component through properties on the root component.
4 |
5 | ## Component properties
6 |
7 | | Prop | Type | Default | Description |
8 | |-----------------------|-----------------|-------------|---------------------------------------------------------------|
9 | | events | Array | [] | Set of events to be displayed |
10 | | height | String | '500px' | Height of the calendar |
11 | | disabled | Object | {} | View the [disabled](#disabled) settings obj |
12 | | highlighted | Object | {} | View the [highlighted](#highlighted) settings obj |
13 | | displayShowMoreCount | Boolean | false | Weather the count of remaining events should be displayed |
14 |
15 | ## Config properties
16 |
17 | ### Events
18 |
19 | Events to be displayed on the calendar.
20 |
21 | ```javascript
22 | [
23 | {
24 | start : Date,
25 | end : Date,
26 | title : 'FooEvent',
27 | classes : ['testClass']
28 | },
29 | ]
30 | ```
31 |
32 | ### Disabled
33 | Days that have to get the disabled class.
34 |
35 | ```javascript
36 | disabled: {
37 | to: new Date(2017, 9, 5), // Disable all dates up to specific date
38 | from: new Date(2017, 11, 26), // Disable all dates after specific date
39 | days: [6, 0], // Disable Saturday's and Sunday's
40 | dates: [ // Disable an array of dates
41 | new Date(2017, 9, 16),
42 | new Date(2017, 9, 17),
43 | new Date(2017, 9, 18)
44 | ]
45 | }
46 | ```
47 |
48 | ### Highlighted
49 | Days that have to get the Highlighted class.
50 |
51 | ```javascript
52 | highlight: {
53 | to: new Date(2017, 9, 5), // Highlight all dates up to specific date
54 | from: new Date(2017, 11, 26), // Highlight all dates after specific date
55 | days: [6, 0], // Highlight Saturday's and Sunday's
56 | dates: [ // Highlight an array of dates
57 | new Date(2017, 9, 16),
58 | new Date(2017, 9, 17),
59 | new Date(2017, 9, 18)
60 | ]
61 | }
62 | ```
63 |
64 | ### displayShowMoreCount
65 | Displays the number of events above the `showLimit` before the showMore link.
66 |
--------------------------------------------------------------------------------
/src/components/calendar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
14 |
15 |
16 |
17 |
18 |
89 |
90 |
98 |
--------------------------------------------------------------------------------
/docs/events.md:
--------------------------------------------------------------------------------
1 | # Events
2 |
3 | There are 2 event types exposed by the component. Internally the component relies on a `eventBus` to notify sibling components.
4 | These events can also be intercepted/used through out your application. All events are emitted by the root component as wll so they can be bound directly for ease of use.
5 |
6 | | Event name | Type | Description | Payload |
7 | |-----------------------|----------|---------------------------------------------------------------|-----------------|
8 | | `event-clicked` | EventBus | When a single event clicked | eventObj |
9 | | `month-changed` | EventBus | When the month is changed in the calendar header | month start/end |
10 | | `day-clicked` | EventBus | When day tile is clicked | dayObj |
11 | | `show-all` | EventBus | `Show more` link clicked, all events of that day are passed | eventObj[] |
12 | | | | | |
13 | | `event-clicked` | Emitted | See bus event | |
14 | | `month-changed` | Emitted | See bus event | |
15 | | `day-clicked` | Emitted | See bus event | |
16 | | `show-all` | Emitted | See bus event | |
17 |
18 |
19 | ### Payload examples
20 |
21 | #### event-clicked
22 | ```javascript
23 | // Single calendar event
24 | {
25 | title: 'event title'
26 | start: Date
27 | end: Date | null
28 | }
29 | ```
30 |
31 | #### month-changed
32 | ```javascript
33 | // Returns the first and last date of the month
34 | {
35 | start: Date
36 | end: Date
37 | }
38 | ```
39 |
40 | #### day-clicked
41 | ```javascript
42 | // Returns a calendar day object containing info on the day self
43 | {
44 | date: Date
45 | isCurrentMonth: true
46 | isSaturday: false
47 | isSunday: false
48 | isToday: false
49 | isWeekend: false
50 | monthDay: 25
51 | weekDay: 3
52 | }
53 | ```
54 |
55 | #### show-all
56 |
57 | ```javascript
58 | // Returns a list of all events for a day
59 | [
60 | {
61 | title: 'event title'
62 | start: Date
63 | end: Date | null
64 | },
65 | // more events ...
66 | ]
67 |
68 | ```
69 |
70 | ### EventBus usage
71 |
72 | The event bus is available through your application as shown below
73 |
74 | ```
75 | this.$calendar.eventBus.$on('{event-name}', (...args) => { //Do stuff... });
76 | ```
77 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue2-calendar
2 |
3 | []() []()
4 |
5 | Check out the demo here on Code Sandbox:
6 | [](https://codesandbox.io/s/93pjr734r4)
7 |
8 | ### Introduction
9 | This is a simple and small event calendar component for Vue js. It is very lightweight and does not depend on external libraries apart from Vue2 obviously.
10 |
11 | ### Table of contents
12 | * [Installation](#Installation)
13 | * [Usage](#Usage)
14 | * [Configuration](./docs/config.md)
15 | * [Properties](./docs/properties.md)
16 | * [Events](./docs/events.md#events)
17 | * [Event payload](./docs/events.md#payload-examples)
18 | * [EventBus usage](./docs/events.md#eventbus-usage)
19 | * [Languages](./docs/languages.md)
20 | * [Add languages](./docs/languages.md#add-languages)
21 |
22 | ### Installation
23 | Add the package to your project.
24 |
25 | ```bash
26 | npm install vue2-simple-calendar
27 |
28 | yarn add vue2-simple-calendar
29 | ```
30 |
31 | `require` or `import` the component in your project index file *(or where you instantiate Vue)* and install as shown below. You can add a configuration object to tweak the calendar to your needs but it is not required.
32 |
33 | ```javascript
34 | import vueCalendar from 'vue2-simple-calendar';
35 |
36 | Vue.use(vueCalendar, {
37 | // configuration goes here.
38 | });
39 | ```
40 |
41 | Now all is in place to use the component.
42 |
43 | ### Usage
44 |
45 | The component is used as shown below. Page specific config and data is passed through properties, the app level config such as `locale`, `firstDay`, ... can be configured on initialization through the config object. All events can be bound to the parent but are available through the complete application through an event bus.
46 |
47 | ```html
48 |
49 |
60 |
61 |
62 |
87 | ```
88 |
--------------------------------------------------------------------------------
/src/utils/languages.js:
--------------------------------------------------------------------------------
1 | import validateLanguage from './language-validator';
2 |
3 | export default {
4 | getTranslation(locale) {
5 | return this.languages.hasOwnProperty(locale) ? this.languages[locale] : this.languages.en;
6 | },
7 | addLanguage(languages) {
8 | // validate the passed lang objects (returns list with valid keys)
9 | const valid = validateLanguage(languages);
10 |
11 | // Add valid languages to the lang set.
12 | this.languages = Object.assign(
13 | this.languages,
14 | Object.keys(languages)
15 | .filter(key => valid.indexOf(key) !== -1)
16 | .reduce((obj, key) => {
17 | obj[key] = languages[key];
18 | return obj;
19 | }, {})
20 | );
21 | },
22 |
23 | // Default app languages
24 | languages: {
25 | en: {
26 | showMore: 'Show more',
27 | dayNameShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
28 | dayNameLong: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
29 | monthNameShort: ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'June', 'July', 'Aug.', 'Sept.', 'Oct.', 'Nov.', 'Dec.'],
30 | monthNameLong: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
31 | },
32 | ru: {
33 | showMore: 'Показать больше',
34 | dayNameShort: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
35 | dayNameLong: ['Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота'],
36 | monthNameShort: ['Янв.', 'Фев.', 'Март.', 'Апр.', 'Май', 'Июнь', 'Июль', 'Авг.', 'Сент.', 'Окт.', 'Ноя.', 'Дек.'],
37 | monthNameLong: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь']
38 | },
39 | zh: {
40 | showMore: '展示更多',
41 | dayNameShort: ['日', '一', '二', '三', '四', '五', '六'],
42 | dayNameLong: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
43 | monthNameShort: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
44 | monthNameLong: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月']
45 | },
46 | fr: {
47 | showMore: 'Afficher plus',
48 | dayNameShort: ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'],
49 | dayNameLong: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'],
50 | monthNameShort: ['Jan.', 'Fév.', 'Mar.', 'Avr.', 'Mai', 'Juin', 'Juil', 'Aou.', 'Sep.', 'Oct.', 'Nov.', 'Déc.'],
51 | monthNameLong: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre']
52 | },
53 | de: {
54 | showMore: 'Weitere anzeigen',
55 | dayNameShort: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
56 | dayNameLong: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
57 | monthNameShort: ['Jan', 'Feb', 'Mrz', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
58 | monthNameLong: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
59 | }
60 | }
61 | };
62 |
--------------------------------------------------------------------------------
/src/components/calendar-header.vue:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
97 |
98 |
116 |
--------------------------------------------------------------------------------
/src/utils/calendar.js:
--------------------------------------------------------------------------------
1 | const mapForeach = (arr, fn) => {
2 | const length = arr.length;
3 | for (let i = 0; i < length; i++) { fn(arr[i], i); }
4 | };
5 |
6 | const firstDateOfMonth = (date) => {
7 | if (!date) date = new Date();
8 | return new Date(date.getFullYear(), date.getMonth(), 1);
9 | };
10 |
11 | const lastDateOfMonth = (date) => {
12 | if (!date) date = new Date();
13 | return new Date(date.getFullYear(), date.getMonth() + 1, 0);
14 | };
15 |
16 | const startOfWeek = (date, firstDay = 0) => {
17 | firstDay = (firstDay < 0 || firstDay > 6) ? 0 : firstDay;
18 |
19 | let day = date.getDay();
20 | // Create a new date instance because we don't want to edit the original object
21 | let calendarStart = new Date(date);
22 |
23 | // Get the difference till the first day of the week plus the offset to start the week at the given day
24 | let diff = (calendarStart.getDate() - day + ((day === 0 ? -7 : 0) + firstDay));
25 | calendarStart.setDate(diff);
26 |
27 | // In case the start date is further then the start of the month, set back with a week.
28 | return (calendarStart > date) ? calendarStart.setDate(calendarStart.getDate() - 7) : calendarStart;
29 | };
30 |
31 | const shiftMonth = (date, shift) => {
32 | return new Date(date.setMonth(date.getMonth() - shift));
33 | };
34 |
35 | const buildCalendar = (startDate, firstDay = 1) => {
36 | let calendar = [];
37 | let today = (new Date()).setHours(0, 0, 0, 0);
38 | let calendarDate = startOfWeek(startDate, firstDay);
39 |
40 | for (let weekNr = 0; weekNr < 6; weekNr++) {
41 | let week = [];
42 |
43 | for (let day = 0; day < 7; day++) {
44 | week.push({
45 | weekDay: day,
46 | date: calendarDate,
47 | isSunday: day === 0,
48 | isSaturday: day === 6,
49 | isWeekend: day === 0 || day === 6,
50 | monthDay: calendarDate.getDate(),
51 | isToday: (calendarDate.getTime() === today),
52 | isCurrentMonth: (calendarDate.getMonth() === startDate.getMonth())
53 | });
54 |
55 | let nextDay = calendarDate.getDate() + 1;
56 | calendarDate = new Date(calendarDate.getFullYear(), calendarDate.getMonth(), nextDay, 0, 0, 0);
57 | }
58 |
59 | calendar.push(week);
60 | }
61 |
62 | return calendar;
63 | };
64 |
65 | const filterEventsForDate = (date, events) => {
66 | let result = [];
67 |
68 | mapForeach(events, (event) => {
69 | const start = new Date(event.start);
70 | const end = event.end ? new Date(event.end) : start;
71 |
72 | const dateStart = (new Date(date.getTime())).setHours(0,0,0,0);
73 | const dateEnd = (new Date(date.getTime())).setHours(23,59,59,999);
74 |
75 | if (start.getTime() >= dateStart && end.getTime() <= dateEnd) {
76 | result.push(event);
77 | }
78 | });
79 |
80 | return result.length ? result : false;
81 | };
82 |
83 | const dateOccursIn = (date, daysObj) => {
84 | if (daysObj.dates) {
85 | return daysObj.dates.some(d => date.toDateString() === d.toDateString());
86 | }
87 |
88 | if (daysObj.to && date < daysObj.to) return true;
89 | if (daysObj.from && date > daysObj.from) return true;
90 | if (daysObj.days && daysObj.days.indexOf(date.getDay) !== -1) return true;
91 | };
92 |
93 | export default {
94 | shiftMonth,
95 | startOfWeek,
96 | dateOccursIn,
97 | buildCalendar,
98 | lastDateOfMonth,
99 | firstDateOfMonth,
100 | filterEventsForDate
101 | };
102 |
--------------------------------------------------------------------------------
/src/components/calendar-body.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
18 |
19 | {{ day.monthDay }}
20 |
21 |
22 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
122 |
123 |
185 |
186 |
--------------------------------------------------------------------------------
/dist/vue-calendar.js:
--------------------------------------------------------------------------------
1 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.vueCalendar=e():t.vueCalendar=e()}("undefined"!=typeof self?self:this,function(){return function(t){function e(a){if(n[a])return n[a].exports;var r=n[a]={i:a,l:!1,exports:{}};return t[a].call(r.exports,r,r.exports,e),r.l=!0,r.exports}var n={};return e.m=t,e.c=n,e.d=function(t,n,a){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:a})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="/",e(e.s=7)}([function(t,e){t.exports=function(t,e,n,a,r,i){var o,s=t=t||{},u=typeof t.default;"object"!==u&&"function"!==u||(o=t,s=t.default);var l="function"==typeof s?s.options:s;e&&(l.render=e.render,l.staticRenderFns=e.staticRenderFns,l._compiled=!0),n&&(l.functional=!0),r&&(l._scopeId=r);var d;if(i?(d=function(t){t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,t||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),a&&a.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(i)},l._ssrRegister=d):a&&(d=a),d){var c=l.functional,h=c?l.render:l.beforeCreate;c?(l._injectStyles=d,l.render=function(t,e){return d.call(e),h(t,e)}):l.beforeCreate=h?[].concat(h,d):[d]}return{esModule:o,exports:s,options:l}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default={data:function(){return{translations:this.$calendar.translations}},computed:{locale:function(){return this.$calendar.locale},dayOffset:function(){return this.$calendar.firstDay},showMoreLabel:function(){return this.translations.showMore}},methods:{printDay:function(t){var e=this.$calendar.fullDayNames?"dayNameLong":"dayNameShort",n=parseInt(t+this.dayOffset)%7;return this.translations[e][n]},printMonth:function(t){var e=this.$calendar.fullMonthNames?"monthNameLong":"monthNameShort";return this.translations[e][t]}}}},function(t,e,n){"use strict";function a(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var r=function(){function t(t,e){var n=[],a=!0,r=!1,i=void 0;try{for(var o,s=t[Symbol.iterator]();!(a=(o=s.next()).done)&&(n.push(o.value),!e||n.length!==e);a=!0);}catch(t){r=!0,i=t}finally{try{!a&&s.return&&s.return()}finally{if(r)throw i}}return n}return function(e,n){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),i=n(14),o=a(i),s=n(17),u=a(s);e.default={name:"vue-calendar",props:{events:{type:Array,default:function(){return[]}},disable:{type:Object,default:function(){return{}}},highlight:{type:Object,default:function(){return{}}},height:{type:String,default:"500px"},displayShowMoreCount:{type:Boolean,default:!1}},data:function(){return{calendarEvents:this.events,disabledDays:this.disable,highlightedDays:this.highlight,wrapperClass:this.$calendar.class}},watch:{events:function(t){this.calendarEvents=t},disable:function(t){this.disabledDays=t},highlight:function(t){this.highlightedDays=t},height:function(t){this.height=t,this.updateHeight()}},methods:{updateHeight:function(){var t=document.getElementsByClassName(this.wrapperClass),e=r(t,1),n=e[0];n&&(n.style.height=this.height)}},components:{"calendar-body":u.default,"calendar-header":o.default},mounted:function(){var t=this;this.updateHeight(),this.$calendar.eventBus.$on("show-all",function(e){return t.$emit("show-all",e)}),this.$calendar.eventBus.$on("day-clicked",function(e){return t.$emit("day-clicked",e)}),this.$calendar.eventBus.$on("event-clicked",function(e){return t.$emit("event-clicked",e)}),this.$calendar.eventBus.$on("month-changed",function(e,n){return t.$emit("month-changed",e,n)})}}},function(t,e,n){"use strict";function a(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var r=n(1),i=a(r),o=n(4),s=a(o);e.default={name:"calendar-header",mixins:[i.default],props:{disable:{type:Object,required:!0}},data:function(){return{monthStart:null}},computed:{year:function(){return this.monthStart.getFullYear()},month:function(){return this.printMonth(this.monthStart.getMonth())},hasDisabledPeriod:function(){return!Object.keys(this.disable).length},isPrevMonthDisabled:function(){return!(this.hasDisabledPeriod||!this.disable.hasOwnProperty("to"))&&(this.disable.to.getMonth()>=this.monthStart.getMonth()&&this.disable.to.getFullYear()>=this.monthStart.getFullYear())},isNextMonthDisabled:function(){return!(this.hasDisabledPeriod||!this.disable.hasOwnProperty("from"))&&(this.disable.from.getMonth()<=this.monthStart.getMonth()&&this.disable.from.getFullYear()<=this.monthStart.getFullYear())}},methods:{goPrev:function(){this.previousMonthDisabled||(this.monthStart=s.default.shiftMonth(this.monthStart,1))},goNext:function(){this.nextMonthDisabled||(this.monthStart=s.default.shiftMonth(this.monthStart,-1))},goToDate:function(t){this.monthStart=s.default.firstDateOfMonth(t)}},watch:{monthStart:function(t){var e=s.default.lastDateOfMonth(t);this.$calendar.eventBus.$emit("month-changed",t,e)}},created:function(){var t=this;this.monthStart=s.default.firstDateOfMonth(),this.$calendar.eventBus.$on("go-to-date",function(e){return t.goToDate(e)})}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=function(t,e){for(var n=t.length,a=0;a1&&void 0!==arguments[1]?arguments[1]:0;e=e<0||e>6?0:e;var n=t.getDay(),a=new Date(t),r=a.getDate()-n+((0===n?-7:0)+e);return a.setDate(r),a>t?a.setDate(a.getDate()-7):a},s=function(t,e){return new Date(t.setMonth(t.getMonth()-e))},u=function(t){for(var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,n=[],a=(new Date).setHours(0,0,0,0),r=o(t,e),i=0;i<6;i++){for(var s=[],u=0;u<7;u++){s.push({weekDay:u,date:r,isSunday:0===u,isSaturday:6===u,isWeekend:0===u||6===u,monthDay:r.getDate(),isToday:r.getTime()===a,isCurrentMonth:r.getMonth()===t.getMonth()});var l=r.getDate()+1;r=new Date(r.getFullYear(),r.getMonth(),l,0,0,0)}n.push(s)}return n},l=function(t,e){var n=[];return a(e,function(e){var a=new Date(e.start),r=e.end?new Date(e.end):a,i=new Date(t.getTime()).setHours(0,0,0,0),o=new Date(t.getTime()).setHours(23,59,59,999);a.getTime()>=i&&r.getTime()<=o&&n.push(e)}),!!n.length&&n},d=function(t,e){return e.dates?e.dates.some(function(e){return t.toDateString()===e.toDateString()}):!!(e.to&&te.from)||(!(!e.days||-1===e.days.indexOf(t.getDay))||void 0))};e.default={shiftMonth:s,startOfWeek:o,dateOccursIn:d,buildCalendar:u,lastDateOfMonth:i,firstDateOfMonth:r,filterEventsForDate:l}},function(t,e,n){"use strict";function a(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var r=n(19),i=a(r),o=n(1),s=a(o),u=n(4),l=a(u);e.default={name:"calendar-body",mixins:[s.default],props:{events:{type:Array,required:!0},disable:{type:Object,required:!0},highlight:{type:Object,required:!0},displayShowMoreCount:{type:Boolean,default:!1}},data:function(){return{monthStart:null,disabledDays:this.disable,highlightedDays:this.highlight}},computed:{firstDay:function(){return this.$calendar.firstDay},showLimit:function(){return this.$calendar.showLimit},calendar:function(){if(this.monthStart)return l.default.buildCalendar(this.monthStart,this.firstDay)}},methods:{dayClasses:function(t){var e={today:t.isToday,sunday:t.isSunday,weekend:t.isWeekend,saturday:t.isSaturday,"not-current":!t.isCurrentMonth,disabled:this.isDayDisabled(t),highlighted:this.isDayHighlighted(t)};return Object.keys(e).filter(function(t){return!0===e[t]})},dayClicked:function(t){this.$calendar.eventBus.$emit("day-clicked",t)},getEventsForDay:function(t){return l.default.filterEventsForDate(t,this.events)},isDayDisabled:function(t){return l.default.dateOccursIn(t.date,this.disabledDays)},isDayHighlighted:function(t){return l.default.dateOccursIn(t.date,this.highlightedDays)}},watch:{disable:function(t){this.disabledDays=t},highlight:function(t){this.highlightedDays=t}},components:{"events-box":i.default},mounted:function(){var t=this;this.$calendar.eventBus.$on("month-changed",function(e){return t.monthStart=e})}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n(1),r=function(t){return t&&t.__esModule?t:{default:t}}(a);e.default={name:"events-box",mixins:[r.default],props:{events:{type:Array,required:!0},displayShowMoreCount:{type:Boolean,default:!1}},computed:{showLimit:function(){return this.$calendar.showLimit},eventList:function(){return this.events.slice(0,this.showLimit)},more:function(){return this.events.length>this.showLimit},showMoreCount:function(){return this.events.length-this.showLimit}},methods:{eventClicked:function(t){this.$calendar.eventBus.$emit("event-clicked",t)},showAll:function(){this.$calendar.eventBus.$emit("show-all",this.events)}}}},function(t,e,n){"use strict";(function(t){function a(t){return t&&t.__esModule?t:{default:t}}function r(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=Object.assign(s.default,e);e.languages&&l.default.addLanguage(e.languages);var a={eventBus:new t,translations:l.default.getTranslation(n.locale)};t.prototype.$calendar=Object.assign(a,n),t.component(n.componentName,c.default)}Object.defineProperty(e,"__esModule",{value:!0});var i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},o=n(9),s=a(o),u=n(10),l=a(u),d=n(12),c=a(d);e.default=r,"object"===i(t)&&t.exports&&(t.exports.install=r)}).call(e,n(8)(t))},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),t.webpackPolyfill=1),t}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default={firstDay:0,showLimit:3,locale:"en",fullDayNames:!1,fullMonthNames:!1,class:"vue-calendar",componentName:"vue-calendar"}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n(11),r=function(t){return t&&t.__esModule?t:{default:t}}(a);e.default={getTranslation:function(t){return this.languages.hasOwnProperty(t)?this.languages[t]:this.languages.en},addLanguage:function(t){var e=(0,r.default)(t);this.languages=Object.assign(this.languages,Object.keys(t).filter(function(t){return-1!==e.indexOf(t)}).reduce(function(e,n){return e[n]=t[n],e},{}))},languages:{en:{showMore:"Show more",dayNameShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNameLong:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNameShort:["Jan.","Feb.","Mar.","Apr.","May","June","July","Aug.","Sept.","Oct.","Nov.","Dec."],monthNameLong:["January","February","March","April","May","June","July","August","September","October","November","December"]},ru:{showMore:"Показать больше",dayNameShort:["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],dayNameLong:["Воскресенье","Понедельник","Вторник","Среда","Четверг","Пятница","Суббота"],monthNameShort:["Янв.","Фев.","Март.","Апр.","Май","Июнь","Июль","Авг.","Сент.","Окт.","Ноя.","Дек."],monthNameLong:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"]},zh:{showMore:"展示更多",dayNameShort:["日","一","二","三","四","五","六"],dayNameLong:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],monthNameShort:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthNameLong:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"]},fr:{showMore:"Afficher plus",dayNameShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],dayNameLong:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],monthNameShort:["Jan.","Fév.","Mar.","Avr.","Mai","Juin","Juil","Aou.","Sep.","Oct.","Nov.","Déc."],monthNameLong:["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"]},de:{showMore:"Weitere anzeigen",dayNameShort:["So","Mo","Di","Mi","Do","Fr","Sa"],dayNameLong:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],monthNameShort:["Jan","Feb","Mrz","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],monthNameLong:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"]}}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=function(t){return"[object Array]"===Object.prototype.toString.call(t)},r=function(t){return"[object Object]"===Object.prototype.toString.call(t)},i=function(t,e){return Object.keys(e).map(function(n){return[n,e[n](t[n])]}).reduce(function(t,e){return!e[1]&&t.push(e[0]+" is invalid"),t},[])},o={showMore:function(t){return"string"==typeof t},dayNameLong:function(t){return a(t)&&t.length>6},dayNameShort:function(t){return a(t)&&t.length>6},monthNameLong:function(t){return a(t)&&t.length>11},monthNameShort:function(t){return a(t)&&t.length>11}};e.default=function(t){return r(t)&&Object.keys(t).length?Object.keys(t).map(function(e){return[e,i(t[e],o)]}).reduce(function(t,e){return 0===e[1].length&&t.push(e[0]),t},[]):[]}},function(t,e,n){"use strict";function a(t){n(13)}Object.defineProperty(e,"__esModule",{value:!0});var r=n(2),i=n.n(r);for(var o in r)"default"!==o&&function(t){n.d(e,t,function(){return r[t]})}(o);var s=n(23),u=n(0),l=a,d=u(i.a,s.a,!1,l,null,null);e.default=d.exports},function(t,e){},function(t,e,n){"use strict";function a(t){n(15)}Object.defineProperty(e,"__esModule",{value:!0});var r=n(3),i=n.n(r);for(var o in r)"default"!==o&&function(t){n.d(e,t,function(){return r[t]})}(o);var s=n(16),u=n(0),l=a,d=u(i.a,s.a,!1,l,null,null);e.default=d.exports},function(t,e){},function(t,e,n){"use strict";var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"calendar-header"},[n("div",{staticClass:"header-left"},[t._t("header-left")],2),t._v(" "),n("div",{staticClass:"header-center"},[t.isPrevMonthDisabled?t._e():n("span",{staticClass:"prev-month",on:{click:function(e){return e.stopPropagation(),t.goPrev(e)}}},[t._v(" < ")]),t._v(" "),n("span",{staticClass:"title"},[t._v(" "+t._s(t.month)+" "+t._s(t.year)+" ")]),t._v(" "),t.isNextMonthDisabled?t._e():n("span",{staticClass:"next-month",on:{click:function(e){return e.stopPropagation(),t.goNext(e)}}},[t._v(" > ")])]),t._v(" "),n("div",{staticClass:"header-right"},[t._t("header-right")],2)])},r=[],i={render:a,staticRenderFns:r};e.a=i},function(t,e,n){"use strict";function a(t){n(18)}Object.defineProperty(e,"__esModule",{value:!0});var r=n(5),i=n.n(r);for(var o in r)"default"!==o&&function(t){n.d(e,t,function(){return r[t]})}(o);var s=n(22),u=n(0),l=a,d=u(i.a,s.a,!1,l,null,null);e.default=d.exports},function(t,e){},function(t,e,n){"use strict";function a(t){n(20)}Object.defineProperty(e,"__esModule",{value:!0});var r=n(6),i=n.n(r);for(var o in r)"default"!==o&&function(t){n.d(e,t,function(){return r[t]})}(o);var s=n(21),u=n(0),l=a,d=u(i.a,s.a,!1,l,null,null);e.default=d.exports},function(t,e){},function(t,e,n){"use strict";var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"events"},[t._l(t.eventList,function(e,a){return n("div",{key:a,staticClass:"event",class:e.classes,on:{click:function(n){n.stopPropagation(),t.eventClicked(e)}}},[n("div",{staticClass:"event-title"},[t._v("\n "+t._s(e.title)+"\n ")])])}),t._v(" "),t.more?n("span",{staticClass:"more-link",on:{click:function(e){e.stopPropagation(),t.showAll()}}},[t.displayShowMoreCount?[t._v(t._s(t.showMoreCount))]:t._e(),t._v("\n "+t._s(t.showMoreLabel)+"\n ")],2):t._e()],2)},r=[],i={render:a,staticRenderFns:r};e.a=i},function(t,e,n){"use strict";var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"calendar-body"},[n("div",{staticClass:"days-header"},t._l(7,function(e){return n("div",{key:e,staticClass:"day-label"},[t._v("\n "+t._s(t.printDay(e-1))+"\n ")])})),t._v(" "),n("div",{staticClass:"days-body"},t._l(t.calendar,function(e,a){return n("div",{key:a,staticClass:"week-row"},t._l(e,function(e,a){return n("div",{key:a,staticClass:"week-day",class:t.dayClasses(e),on:{click:function(n){n.stopPropagation(),t.dayClicked(e)}}},[n("div",{staticClass:"day-number"},[t._v("\n "+t._s(e.monthDay)+"\n ")]),t._v(" "),(t.dayEvents=t.getEventsForDay(e.date))?n("events-box",{attrs:{events:t.dayEvents,"display-show-more-count":t.displayShowMoreCount}}):t._e()],1)}))}))])},r=[],i={render:a,staticRenderFns:r};e.a=i},function(t,e,n){"use strict";var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{class:t.wrapperClass},[n("calendar-header",{attrs:{disable:t.disabledDays}}),t._v(" "),n("calendar-body",{attrs:{events:t.calendarEvents,disable:t.disabledDays,highlight:t.highlightedDays,"display-show-more-count":t.displayShowMoreCount}})],1)},r=[],i={render:a,staticRenderFns:r};e.a=i}])});
--------------------------------------------------------------------------------