0.0.24 • Published 10 months ago

@kunukn/vue-2-datepicker v0.0.24

Weekly downloads
-
License
MIT
Repository
github
Last release
10 months ago

Vue 2 DatePicker

npm version npm downloads gzip license

A date picker Vue component. Compatible with Vue 2.x

About

A date picker Vue component that can pick from days, from months or years. Compatible with Vue 2.x.

Vue 3 is out of scope in this repo. I needed a 2.6+ version and this repo is based on https://github.com/charliekassel/vuejs-datepicker#readme

This repo has been modified to use Vite and Vitest and the goal is to support Vue 2.6+ with pretty default styling.

See the strategy for more info about what will likely happen with this repo.

Table of contents

Demo

Codesandbox

date-picker

The click-able areas are: the arrows, the date headline and the date numbers.

To view a demo online:

Storybook

The github pages contains Storybook examples.

https://kunukn.github.io/vue-2-datepicker

Locally

To view demo examples locally clone the repo and run yarn install && yarn dev

Install

CSS required

:warning: ️You need to add the CSS file.

import "@kunukn/vue-2-datepicker/dist/date-picker.css"

or CDN

<link
  rel="stylesheet"
  href="https://unpkg.com/@kunukn/vue-2-datepicker/dist/date-picker.css"
/>

Add package

yarn add -D @kunukn/vue-2-datepicker
import { DatePicker } from '@kunukn/vue-2-datepicker'
import '@kunukn/vue-2-datepicker/dist/date-picker.css'

export default {
  // ...
  components: {
    DatePicker,
  },
  // ...
}

Directly from a CDN

<link
  rel="stylesheet"
  href="https://unpkg.com/@kunukn/vue-2-datepicker/dist/date-picker.css"
/>
<div id="app">
  <date-picker></date-picker>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.min.js"></script>
<script src="https://unpkg.com/@kunukn/vue-2-datepicker/dist/date-picker.umd.cjs"></script>
<script>
  const app = new Vue({
    el: '#app',
    components: {
      DatePicker,
    },
  })
</script>

Size

namesizegzip
date-picker.css~5 kB~1.2 kB
date-picker.js~53 kB~11 kB
date-picker.umd.cjs~34 kB~8 kB

Usage

Formatting and localization patterns

You can either try to handle all the formatting yourself using these props with a day utility like dayjs.

useRtl = true | false
mondayFirst = true | false

// index will be from 0 to 6 representing the weekdays index
dayFormatter = (value, index) => 'something'

// index will be from 0 to 11 representing the month index
monthFormatter = (value, index) => 'something'

// value will be the year number option
yearFormatter = (value) => 'something'

headlineDayFormatter = ({ pageDate, selectedDate }) =>
  dayjs(pageDate).format('MMM YYYY')

// pageYearName is the year number
headlineMonthFormatter = ({ pageDate, selectedDate, pageYearName }) =>
  myCustomYearConverter(pageYearName)

// getPageDecade is the year range
headlineYearFormatter = ({ pageDate, selectedDate, getPageDecade }) =>
  myCustomYearDecadeConverter(getPageDecade)

Or you can let the library do the formatting and localization using the loaded language.

Code snippets

<date-picker></date-picker>

value prop if passed should be a Date object

<script>
  let state = {
    date: new Date(2023, 6, 27),
  }
</script>
<date-picker :value="state.date"></date-picker>

support name attribute for normal html form submission

<date-picker :value="state.date" name="uniquename"></date-picker>

Using v-model

<date-picker v-model="state.date" name="uniquename"></date-picker>

Emits events

<date-picker
  @selected="doSomethingInParentComponentFunction"
  @opened="datepickerOpenedFunction"
  @closed="datepickerClosedFunction"
></date-picker>

always Inline open version

<date-picker inline></date-picker>

Custom styling

Look in the file @kunukn/vue-2-datepicker/dist/date-picker.css to see what exists.

Override the CSS custom properties to set the desired size.

.vdp-datepicker {
  --vdp-cell-size: 40px;
  --vdp-color-theme: #4bd;
  --vdp-color-selected: hotpink;

  @media (min-width: 768px) {
    --vdp-cell-size: 56px;
  }
}

Override the CSS classnames

.vdp-datepicker {
  .vdp-datepicker__picker {
    padding: 1rem;
    margin-inline: auto;
  }
}

.vdp-datepicker__header {
  :nth-child(2) {
    font-weight: bold;
  }
}

Default CSS custom property values.

These can be overriden.

.vdp-datepicker {
  --vdp-cell-size: 44px;
  --vdp-cell-gap: 4px;
  --vdp-header-gap: 4px;
  --vdp-cell-border-radius-square: 50%;
  --vdp-cell-border-radius-rectangle: 8px;
  --vdp-color-theme-bg: #fff;
  --vdp-color-theme: #007da0;
  --vdp-color-selected: #fff;
  --vdp-color-border: #ccc;
  --vdp-color-disabled: #ddd;
  --vdp-color-button-disabled: #999;
  --vdp-color-header-button-hover: #f2f2f2;
  --vdp-color-header-bg: #fff;
  --vdp-color-highlighted-bg: #cae5ed;
  --vdp-color-highlighted-disabled-fg: #a3a3a3;
  --vdp-color-grey: #a3a3a3;
  --vdp-font-size-day-header: 14px;
}

Available props

PropTypeDefaultDescription
valueDate|StringDate value of the datepicker
nameStringInput name property
idStringInput id
formatString|Functiondd MMM yyyyDate formatting string or function
dayFormatterFunctionCustom day cell formatter
monthFormatterFunctionCustom month cell formatter
yearFormatterFunctionCustom year cell formatter
headlineDayFormatterFunctionCustom day headline formatter
headlineMonthFormatterFunctionCustom month headline formatter
headlineYearFormatterFunctionCustom year headline formatter
full-month-nameBooleanfalseTo show the full month name
languageObjectenTranslation for days and months
disabled-datesObjectSee below for configuration
placeholderStringInput placeholder text
inlineBooleanTo show the datepicker always open
calendar-classString|ObjectCSS class applied to the calendar el
input-classString|ObjectCSS class applied to the input el
wrapper-classString|ObjectCSS class applied to the outer div
monday-firstBooleanfalseTo start the week on Monday
ensure-min-heightBooleanfalseEnsure day picker view has same height
day-cell-contentFunctionUse to render custom content in day cell
bootstrap-stylingBooleanfalseOutput bootstrap v4 styling classes.
initial-viewStringminimumViewIf set, open on that view
disabledBooleanfalseIf true, disable Datepicker on-screen
requiredBooleanfalseSets html required attribute on input
typeableBooleanfalseIf true, allows the user to type the date
use-utcBooleanfalseuse UTC for time calculations
use-rtlBooleannullForce set the RTL language
days-custom-displayArraynullForce set day headlines
months-custom-displayArraynullForce set month headlines
open-dateDate|StringIf set, open on that date
minimum-viewString'day'If set, lower-level views won't show
maximum-viewString'year'If set, higher-level views won't show

Events

These events are emitted on actions in the date picker

EventOutputDescription
openedThe picker is opened
closedThe picker is closed
selectedDate|nullA date has been selected
selectedDisabledObjectA disabled date has been selected
inputDate|nullInput value has been modified
clearedSelected date has been cleared
changedMonthObjectMonth page has been changed
changedYearObjectYear page has been changed
changedDecadeObjectDecade page has been changed

Date formatting

String formatter

NB. This is not very robust at all - use at your own risk! Needs better implementation. EDIT: by new author. This feature will likely be revisited in newer versions.

TokenDescExample
dday1
dd0 prefixed day01
Dabbr dayMon
sudate suffixst, nd, rd
Mmonth number (1 based)1 (for Jan)
MM0 prefixed month01
MMMabbreviated month nameJan
MMMMmonth nameJanuary
yytwo digit year16
yyyyfour digit year2016

Function formatter

Delegates date formatting to provided function. The function will be called with date and it has to return formatted date as a string. This allow us to use dayjs, date-fns or any other library to format date.

<script>
  methods: {
    customFormatter(date) {
      return dayjs(date).format('ddd, DD MMM');
    }
  }
</script>
<date-picker :format="customFormatter"></date-picker>

Disabled Dates

Dates can be disabled in several ways.

<script>
  let state = {
    disabledDates: {
      to: new Date(2016, 0, 5), // Disable all dates up to specific date
      from: new Date(2016, 0, 26), // Disable all dates after specific date
      days: [6, 0], // Disable Saturday's and Sunday's
      daysOfMonth: [29, 30, 31], // Disable 29th, 30th and 31st of each month
      dates: [
        // Disable an array of dates
        new Date(2016, 9, 16),
        new Date(2016, 9, 17),
        new Date(2016, 9, 18),
      ],
      ranges: [
        {
          // Disable dates in given ranges (exclusive).
          from: new Date(2016, 11, 25),
          to: new Date(2016, 11, 30),
        },
        {
          from: new Date(2017, 1, 12),
          to: new Date(2017, 2, 25),
        },
      ],
      // A custom function that returns true if the date is disabled.
      // This can be used for wiring your own logic to disable a date if none
      // of the above conditions serve your purpose.
      // This function should accept a date and return true if is disabled
      customPredictor: function (date) {
        // disables the date if it is a multiple of 5
        if (date.getDate() % 5 == 0) {
          return true
        }
      },
    },
  }
</script>
<date-picker :disabled-dates="state.disabledDates"></date-picker>

Highlighted Dates

Dates can be highlighted (e.g. for marking an appointment) in a number of ways. Important: By default disabled dates are ignored, to highlight disabled dates set the includeDisabled property to true. Note: Both to and from properties are required to define a range of dates to highlight.

<script>
  var state = {
    highlighted: {
      to: new Date(2016, 0, 5), // Highlight all dates up to specific date
      from: new Date(2016, 0, 26), // Highlight all dates after specific date
      days: [6, 0], // Highlight Saturday's and Sunday's
      daysOfMonth: [15, 20, 31], // Highlight 15th, 20th and 31st of each month
      dates: [
        // Highlight an array of dates
        new Date(2016, 9, 16),
        new Date(2016, 9, 17),
        new Date(2016, 9, 18),
      ],
      // a custom function that returns true of the date is highlighted
      // this can be used for wiring you own logic to highlight a date if none
      // of the above conditions serve your purpose
      // this function should accept a date and return true if is highlighted
      customPredictor: function (date) {
        // highlights the date if it is a multiple of 4
        if (date.getDate() % 4 == 0) {
          return true
        }
      },
      includeDisabled: true, // Highlight disabled dates
    },
  }
</script>
<date-picker :highlighted="state.highlighted"></date-picker>

Slots

Slots will help you customize content.

beforeCalendarHeader

Sometimes you need to show custom content before the calendar header. For such cases, you can use the named slot beforeCalendarHeader.

An example would be to use bootstrap's input-group-prepend and input-group-append to show some custom text:

<date-picker :bootstrap-styling="true">
  <div slot="beforeCalendarHeader" class="calender-header">Choose a Date</div>
</date-picker>

afterDateInput

To implement some custom styling (for instance to add an animated placeholder) on DateInput, you might need to add elements as DateInput siblings. Slot named afterDateInput allows you to do that:

<date-picker>
  <span slot="afterDateInput" class="animated-placeholder">
    Choose a Date
  </span>
</date-picker>

prevButton and nextButton

Enables to apply custom prev and next button design.

<date-picker>
  <span slot="prevButton">👈</span>
  <span slot="nextButton">👉</span>
</date-picker>

Translations

Obs! This strategy is likely to be refactored over time where Intl.DateTimeFormat will be used.

list is used as the translation property.

  • Add your language as a module in the src/locale/translations dir.
  • Import and export it in the src/locale/all.js file
  • Add the Language to the available languages in the readme file.
  • Run yarn lint to make sure your code formatting is in line with the required code style.

How to apply language

Below script tag in a component. Beware! importing the all.js file will load all the existing languages in the memory and JS bundle.

import { en, es, de } from '@kunukn/vue-2-datepicker/src/locale/all.js'

In component data.

data() {
    return {
      en,
      es,
      de,
    }
}

html.

<date-picker :language="es"></date-picker>

Lazy loaded approach

<date-picker :language="language"></date-picker>
  props: {
    isoLanguage: { /* e.g. Spanish ISO code: 'es' */
      type: String,
      default: 'en'
    },
  },
  data() {
    return {
      language: null,
    }
  },
  async created() {
    let langObject = await import(
      `@kunukn/vue-2-datepicker/src/locale/translations/${isoLanguage}.js`
    )

    let newLang = langObject.default || langObject
    if (newLang) {
      this.language = newLang
    }
  },

Available languages

AbbrLanguage
afAfrikaans
arArabic
bgBulgarian
bsBosnian
caCatalan
csCzech
daDanish
deGerman
eeEstonian
elGreek
enEnglishDefault
esSpanish
faPersian (Farsi)
fiFinnish
foFaroese
frFrench
geGeorgia
glGalician
heHebrew
huHungarian
hrCroatian
idIndonesian
isIcelandic
itItalian
jaJapanese
kkKazakh
koKorean
lbLuxembourgish
ltLithuanian
lvLatvian
mkMacedonian
mnMongolian
nbNONorwegian Bokmål
nlDutch
plPolish
ptBRPortuguese-Brazil
roRomanian
ruRussian
skSlovak
slSISlovenian
svSwedish
srSerbian (Latin)
srCyrlSerbian (Cyrl)
thThai
trTurkish
ukUkrainian
urUrdu
viVietnamese
zhChinese
zhHKChinese_HK

Strategy for this project

This date-picker will over time be modified to focus on the date logic handling. The presentation and localization of how to display the dates will be refactored to injectable formatter props.

Modern browser API can do language date formatting. Intl.DateTimeFormat https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat

It has high Browser support 96+ %. https://caniuse.com/?search=Intl.DateTimeFormat

The text input field parsing will likely also be refactored.

Unpkg link

With this link you can navigate the existing resources.

https://unpkg.com/@kunukn/vue-2-datepicker/

0.0.20

10 months ago

0.0.21

10 months ago

0.0.22

10 months ago

0.0.23

10 months ago

0.0.24

10 months ago

0.0.13

11 months ago

0.0.14

11 months ago

0.0.15

11 months ago

0.0.16

11 months ago

0.0.17

11 months ago

0.0.18

11 months ago

0.0.19

10 months ago

0.0.12

11 months ago

0.0.11

11 months ago

0.0.10

11 months ago

0.0.9

11 months ago

0.0.8

11 months ago

0.0.7

11 months ago

0.0.5

11 months ago

0.0.4

11 months ago

0.0.3

11 months ago

0.0.2

11 months ago