mirror of
https://github.com/tenrok/vue2-datepicker.git
synced 2026-06-10 11:12:27 +03:00
vue3 base
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
|
||||
dist
|
||||
lib
|
||||
es
|
||||
node_modules
|
||||
/locale
|
||||
/index.*
|
||||
@@ -0,0 +1,46 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint',
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
jest: true,
|
||||
es6: true,
|
||||
},
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
node: {
|
||||
extensions: ['.js', '.jsx', '.vue'],
|
||||
},
|
||||
},
|
||||
'import/extensions': ['.js', '.jsx', '.vue'],
|
||||
},
|
||||
extends: ['airbnb-base', 'plugin:vue/recommended', 'prettier', 'prettier/vue'],
|
||||
|
||||
plugins: ['vue'],
|
||||
|
||||
rules: {
|
||||
// allow debugger during development
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
'no-console': ['error', { allow: ['warn', 'error'] }],
|
||||
'no-plusplus': 'off',
|
||||
'no-underscore-dangle': 'off',
|
||||
'no-param-reassign': 'off',
|
||||
'no-restricted-globals': 'off',
|
||||
'import/prefer-default-export': 'off',
|
||||
'import/no-unresolved': [2, { ignore: ['vue2-datepicker'] }],
|
||||
'import/no-extraneous-dependencies': 'off',
|
||||
'import/extensions': [
|
||||
'error',
|
||||
'always',
|
||||
{
|
||||
js: 'never',
|
||||
vue: 'never',
|
||||
},
|
||||
],
|
||||
'vue/require-default-prop': 'off',
|
||||
'vue/require-prop-types': 'off',
|
||||
'vue/no-v-html': 'off',
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
custom: https://www.paypal.me/mengxiong10
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[Bug]"
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Vue2-datepicker version**:
|
||||
**Vue version**:
|
||||
**Browser**:
|
||||
|
||||
**Steps to reproduce**
|
||||
|
||||
|
||||
**Reproduction Link or Source Code**
|
||||
|
||||
|
||||
**Expected behavior**
|
||||
|
||||
|
||||
**Actual behavior**
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: "[Feature request]"
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**What problem does this feature solve?**
|
||||
|
||||
|
||||
**What does the proposed API look like?**
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
.vscode
|
||||
.cache
|
||||
|
||||
_site
|
||||
|
||||
node_modules
|
||||
|
||||
/dist
|
||||
|
||||
/locale
|
||||
|
||||
/index.*
|
||||
|
||||
/scss
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 2,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"printWidth": 100,
|
||||
"arrowParens": "always",
|
||||
"jsxBracketSameLine": true
|
||||
}
|
||||
@@ -0,0 +1,321 @@
|
||||
# vue2-datepicker
|
||||
|
||||
[中文版](https://github.com/mengxiong10/vue2-datepicker/blob/master/README.zh-CN.md)
|
||||
|
||||
> A Datepicker Component For Vue2
|
||||
|
||||
<a href="https://travis-ci.org/mengxiong10/vue2-datepicker">
|
||||
<img src="https://travis-ci.org/mengxiong10/vue2-datepicker.svg?branch=master" alt="build:passed">
|
||||
</a>
|
||||
<a href="https://coveralls.io/github/mengxiong10/vue2-datepicker">
|
||||
<img src="https://coveralls.io/repos/github/mengxiong10/vue2-datepicker/badge.svg?branch=master&service=github" alt="Badge">
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/package/vue2-datepicker">
|
||||
<img src="https://img.shields.io/npm/v/vue2-datepicker.svg" alt="npm">
|
||||
</a>
|
||||
<a href="LICENSE">
|
||||
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="MIT">
|
||||
</a>
|
||||
|
||||
## Demo
|
||||
|
||||
<https://mengxiong10.github.io/vue2-datepicker/index.html>
|
||||
|
||||

|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
$ npm install vue2-datepicker@next --save
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```html
|
||||
<script>
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import 'vue2-datepicker/index.css';
|
||||
|
||||
export default {
|
||||
components: { DatePicker },
|
||||
data() {
|
||||
return {
|
||||
time1: null,
|
||||
time2: null,
|
||||
time3: null,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<date-picker v-model="time1" valueType="format"></date-picker>
|
||||
<date-picker v-model="time2" type="datetime"></date-picker>
|
||||
<date-picker v-model="time3" range></date-picker>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
## Theme
|
||||
|
||||
If your project uses SCSS, you can change the default style variables.
|
||||
|
||||
To create a scss file. e.g. `datepicker.scss`:
|
||||
|
||||
```scss
|
||||
$namespace: 'xmx'; // change the 'mx' to 'xmx'. then <date-picker prefix-class="xmx" />
|
||||
|
||||
$default-color: #555;
|
||||
$primary-color: #1284e7;
|
||||
|
||||
@import '~vue2-datepicker/scss/index.scss';
|
||||
```
|
||||
|
||||
## Internationalization
|
||||
|
||||
The default language of v3.x is English. If you need other locales,
|
||||
you can import a locale file.
|
||||
Once you import a locale, it becomes the active locale.
|
||||
|
||||
```js
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import 'vue2-datepicker/index.css';
|
||||
|
||||
import 'vue2-datepicker/locale/zh-cn';
|
||||
```
|
||||
|
||||
You can also override some of the default locale by `lang`.
|
||||
[Full config](https://github.com/mengxiong10/vue2-datepicker/blob/master/locale.md)
|
||||
|
||||
```html
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
lang: {
|
||||
formatLocale: {
|
||||
firstDayOfWeek: 1,
|
||||
},
|
||||
monthBeforeYear: false,
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<date-picker :lang="lang"></date-picker>
|
||||
</template>
|
||||
```
|
||||
|
||||
### Props
|
||||
|
||||
| Prop | Description | Type | Default |
|
||||
| ------------------- | ------------------------------------------------ | ------------------------------------------- | -------------- |
|
||||
| type | select the type of picker | date \|datetime\|year\|month\|time\|week | 'date' |
|
||||
| range | if true, pick the range date | `boolean` | false |
|
||||
| format | to set the date format. similar to moment.js | [token](#token) | 'YYYY-MM-DD' |
|
||||
| formatter | use your own formatter, such as moment.js | [object](#formatter) | - |
|
||||
| value-type | data type of the binding value | [value-type](#value-type) | 'date' |
|
||||
| default-value | default date of the calendar | `Date` | new Date() |
|
||||
| lang | override the default locale | `object` | |
|
||||
| placeholder | input placeholder text | `string` | '' |
|
||||
| editable | whether the input is editable | `boolean` | true |
|
||||
| clearable | if false, don't show the clear icon | `boolean` | true |
|
||||
| confirm | if true, need click the button to change value | `boolean` | false |
|
||||
| confirm-text | the text of confirm button | `string` | 'OK' |
|
||||
| multiple | if true, multi-select date | `boolean` | false |
|
||||
| disabled | disable the component | `boolean` | false |
|
||||
| disabled-date | specify the date that cannot be selected | `(date) => boolean` | - |
|
||||
| disabled-time | specify the time that cannot be selected | `(date) => boolean` | - |
|
||||
| append-to-body | append the popup to body | `boolean` | true |
|
||||
| inline | without input | `boolean` | false |
|
||||
| input-class | input classname | `string` | 'mx-input' |
|
||||
| input-attr | input attrs(eg: { name: 'date', id: 'foo'}) | `object` | — |
|
||||
| open | open state of picker | `boolean` | - |
|
||||
| default-panel | default panel of the picker | year\|month | - |
|
||||
| popup-style | popup style | `object` | — |
|
||||
| popup-class | popup classes | | — |
|
||||
| shortcuts | set shortcuts to select | `Array<{text, onClick}>` | - |
|
||||
| title-format | format of the tooltip in calendar cell | [token](#token) | 'YYYY-MM-DD' |
|
||||
| partial-update | whether update date when select year or month | `boolean` | false |
|
||||
| range-separator | text of range separator | `string` | ' ~ ' |
|
||||
| show-week-number | determine whether show week number | `boolean` | false |
|
||||
| hour-step | interval between hours in time picker | 1 - 60 | 1 |
|
||||
| minute-step | interval between minutes in time picker | 1 - 60 | 1 |
|
||||
| second-step | interval between seconds in time picker | 1 - 60 | 1 |
|
||||
| hour-options | custom hour column | `Array<number>` | - |
|
||||
| minute-options | custom minute column | `Array<number>` | - |
|
||||
| second-options | custom second column | `Array<number>` | - |
|
||||
| show-hour | whether show hour column | `boolean` | base on format |
|
||||
| show-minute | whether show minute column | `boolean` | base on format |
|
||||
| show-second | whether show second column | `boolean` | base on format |
|
||||
| use12h | whether show ampm column | `boolean` | base on format |
|
||||
| show-time-header | whether show header of time picker | `boolean` | false |
|
||||
| time-title-format | format of the time header | [token](#token) | 'YYYY-MM-DD' |
|
||||
| time-picker-options | set fixed time list to select | [time-picker-options](#time-picker-options) | null |
|
||||
| prefix-class | set prefix class | `string` | 'mx' |
|
||||
| scroll-duration | set the duration of scroll when hour is selected | `number` | 100 |
|
||||
|
||||
#### Token
|
||||
|
||||
| Uint | Token | output |
|
||||
| -------------------------- | ----- | -------------------------------------- |
|
||||
| Year | YY | 70 71 ... 10 11 |
|
||||
| | YYYY | 1970 1971 ... 2010 2011 |
|
||||
| | Y | -1000 ...20 ... 1970 ... 9999 +10000 |
|
||||
| Month | M | 1 2 ... 11 12 |
|
||||
| | MM | 01 02 ... 11 12 |
|
||||
| | MMM | Jan Feb ... Nov Dec |
|
||||
| | MMMM | January February ... November December |
|
||||
| Day of Month | D | 1 2 ... 30 31 |
|
||||
| | DD | 01 02 ... 30 31 |
|
||||
| Day of Week | d | 0 1 ... 5 6 |
|
||||
| | dd | Su Mo ... Fr Sa |
|
||||
| | ddd | Sun Mon ... Fri Sat |
|
||||
| | dddd | Sunday Monday ... Friday Saturday |
|
||||
| AM/PM | A | AM PM |
|
||||
| | a | am pm |
|
||||
| Hour | H | 0 1 ... 22 23 |
|
||||
| | HH | 00 01 ... 22 23 |
|
||||
| | h | 1 2 ... 12 |
|
||||
| | hh | 01 02 ... 12 |
|
||||
| Minute | m | 0 1 ... 58 59 |
|
||||
| | mm | 00 01 ... 58 59 |
|
||||
| Second | s | 0 1 ... 58 59 |
|
||||
| | ss | 00 01 ... 58 59 |
|
||||
| Fractional Second | S | 0 1 ... 8 9 |
|
||||
| | SS | 00 01 ... 98 99 |
|
||||
| | SSS | 000 001 ... 998 999 |
|
||||
| Time Zone | Z | -07:00 -06:00 ... +06:00 +07:00 |
|
||||
| | ZZ | -0700 -0600 ... +0600 +0700 |
|
||||
| Week of Year | w | 1 2 ... 52 53 |
|
||||
| | ww | 01 02 ... 52 53 |
|
||||
| Unix Timestamp | X | 1360013296 |
|
||||
| Unix Millisecond Timestamp | x | 1360013296123 |
|
||||
|
||||
#### formatter
|
||||
|
||||
The `formatter` accepts an object to customize formatting.
|
||||
|
||||
```html
|
||||
<date-picker :formatter="momentFormat" />
|
||||
```
|
||||
|
||||
```js
|
||||
data() {
|
||||
return {
|
||||
// Use moment.js instead of the default
|
||||
momentFormat: {
|
||||
//[optional] Date to String
|
||||
stringify: (date) => {
|
||||
return date ? moment(date).format('LL') : ''
|
||||
},
|
||||
//[optional] String to Date
|
||||
parse: (value) => {
|
||||
return value ? moment(value, 'LL').toDate() : null
|
||||
},
|
||||
//[optional] getWeekNumber
|
||||
getWeek: (date) => {
|
||||
return // a number
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
#### value-type
|
||||
|
||||
set the format of binding value
|
||||
|
||||
| Value | Description |
|
||||
| ----------------- | ---------------------------------------------------- |
|
||||
| 'date' | return a Date object |
|
||||
| 'timestamp' | return a timestamp number |
|
||||
| 'format' | returns a string formatted using pattern of `format` |
|
||||
| token(MM/DD/YYYY) | returns a string formatted using this pattern |
|
||||
|
||||
#### shortcuts
|
||||
|
||||
The shortcuts for the range picker
|
||||
|
||||
```js
|
||||
[
|
||||
{ text: 'today', onClick: () => new Date() },
|
||||
{
|
||||
text: 'Yesterday',
|
||||
onClick: () => {
|
||||
const date = new Date();
|
||||
date.setTime(date.getTime() - 3600 * 1000 * 24);
|
||||
return date;
|
||||
},
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
| Attribute | Description |
|
||||
| --------- | ----------------------------------------- |
|
||||
| text | title of the shortcut |
|
||||
| onClick | callback function , need to return a Date |
|
||||
|
||||
#### time-picker-options
|
||||
|
||||
Set fixed time list to select;
|
||||
|
||||
```js
|
||||
{start: '00:00', step:'00:30' , end: '23:30', format: 'HH:mm' }
|
||||
```
|
||||
|
||||
| Attribute | Description |
|
||||
| --------- | ------------------------------------ |
|
||||
| start | start time |
|
||||
| step | step time |
|
||||
| end | end time |
|
||||
| format | the default is same as prop `format` |
|
||||
|
||||
### Events
|
||||
|
||||
| Name | Description | Callback Arguments |
|
||||
| --------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
||||
| input | When the value change(v-model event) | date |
|
||||
| change | When the value change(same as input) | date, type('date'\|'hour'\|'minute'\|'second'\|'ampm |
|
||||
| open | When panel opening | event |
|
||||
| close | When panel closing | |
|
||||
| confirm | When click 'confirm' button | date |
|
||||
| clear | When click 'clear' button | |
|
||||
| input-error | When user type a invalid Date | the input text |
|
||||
| focus | When input focus | |
|
||||
| blur | When input blur | |
|
||||
| pick | when select date [#429](https://github.com/mengxiong10/vue2-datepicker/issues/429) | date |
|
||||
| calendar-change | when change the calendar | date, oldDate, type('year'\|'month'\|'last-year'\|'next-year'\|'last-month'\|'next-month'\|'last-decade'\|'next-decade') |
|
||||
|
||||
### Slots
|
||||
|
||||
| Name | Description |
|
||||
| ------------- | ------------------------ |
|
||||
| icon-calendar | custom the calender icon |
|
||||
| icon-clear | custom the clear icon |
|
||||
| input | replace input |
|
||||
| header | popup header |
|
||||
| footer | popup footer |
|
||||
| sidebar | popup sidebar |
|
||||
|
||||
## ChangeLog
|
||||
|
||||
[CHANGELOG](CHANGELOG.md)
|
||||
|
||||
## One-time Donations
|
||||
|
||||
If you find this project useful, you can buy me a coffee
|
||||
|
||||
[Paypal Me](https://www.paypal.me/mengxiong10)
|
||||
|
||||

|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/mengxiong10/vue2-datepicker/blob/master/LICENSE)
|
||||
|
||||
Copyright (c) 2017-present xiemengxiong
|
||||
@@ -0,0 +1,599 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`DatePicker prop: attrs of input 1`] = `
|
||||
<div
|
||||
class="mx-datepicker"
|
||||
>
|
||||
<div
|
||||
class="mx-input-wrapper"
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
class="test"
|
||||
name="test"
|
||||
placeholder="test placeholder"
|
||||
type="number"
|
||||
/>
|
||||
<!---->
|
||||
<i
|
||||
class="mx-icon-calendar"
|
||||
>
|
||||
<svg
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M940.218182 107.054545h-209.454546V46.545455h-65.163636v60.50909H363.054545V46.545455H297.890909v60.50909H83.781818c-18.618182 0-32.581818 13.963636-32.581818 32.581819v805.236363c0 18.618182 13.963636 32.581818 32.581818 32.581818h861.090909c18.618182 0 32.581818-13.963636 32.581818-32.581818V139.636364c-4.654545-18.618182-18.618182-32.581818-37.236363-32.581819zM297.890909 172.218182V232.727273h65.163636V172.218182h307.2V232.727273h65.163637V172.218182h176.872727v204.8H116.363636V172.218182h181.527273zM116.363636 912.290909V442.181818h795.927273v470.109091H116.363636z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`DatePicker prop: clearable 1`] = `
|
||||
<div
|
||||
class="mx-datepicker"
|
||||
>
|
||||
<div
|
||||
class="mx-input-wrapper"
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
class="mx-input"
|
||||
name="date"
|
||||
placeholder=""
|
||||
type="text"
|
||||
/>
|
||||
<!---->
|
||||
<i
|
||||
class="mx-icon-calendar"
|
||||
>
|
||||
<svg
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M940.218182 107.054545h-209.454546V46.545455h-65.163636v60.50909H363.054545V46.545455H297.890909v60.50909H83.781818c-18.618182 0-32.581818 13.963636-32.581818 32.581819v805.236363c0 18.618182 13.963636 32.581818 32.581818 32.581818h861.090909c18.618182 0 32.581818-13.963636 32.581818-32.581818V139.636364c-4.654545-18.618182-18.618182-32.581818-37.236363-32.581819zM297.890909 172.218182V232.727273h65.163636V172.218182h307.2V232.727273h65.163637V172.218182h176.872727v204.8H116.363636V172.218182h181.527273zM116.363636 912.290909V442.181818h795.927273v470.109091H116.363636z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`DatePicker prop: editable 1`] = `
|
||||
<div
|
||||
class="mx-datepicker"
|
||||
>
|
||||
<div
|
||||
class="mx-input-wrapper"
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
class="mx-input"
|
||||
name="date"
|
||||
placeholder=""
|
||||
readonly=""
|
||||
type="text"
|
||||
/>
|
||||
<i
|
||||
class="mx-icon-clear"
|
||||
>
|
||||
<svg
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M810.005333 274.005333l-237.994667 237.994667 237.994667 237.994667-60.010667 60.010667-237.994667-237.994667-237.994667 237.994667-60.010667-60.010667 237.994667-237.994667-237.994667-237.994667 60.010667-60.010667 237.994667 237.994667 237.994667-237.994667z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
<i
|
||||
class="mx-icon-calendar"
|
||||
>
|
||||
<svg
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M940.218182 107.054545h-209.454546V46.545455h-65.163636v60.50909H363.054545V46.545455H297.890909v60.50909H83.781818c-18.618182 0-32.581818 13.963636-32.581818 32.581819v805.236363c0 18.618182 13.963636 32.581818 32.581818 32.581818h861.090909c18.618182 0 32.581818-13.963636 32.581818-32.581818V139.636364c-4.654545-18.618182-18.618182-32.581818-37.236363-32.581819zM297.890909 172.218182V232.727273h65.163636V172.218182h307.2V232.727273h65.163637V172.218182h176.872727v204.8H116.363636V172.218182h181.527273zM116.363636 912.290909V442.181818h795.927273v470.109091H116.363636z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`DatePicker prop: formatter 1`] = `
|
||||
<table
|
||||
class="mx-table mx-table-date"
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th
|
||||
class="mx-week-number-header"
|
||||
/>
|
||||
|
||||
<th>
|
||||
Su
|
||||
</th>
|
||||
<th>
|
||||
Mo
|
||||
</th>
|
||||
<th>
|
||||
Tu
|
||||
</th>
|
||||
<th>
|
||||
We
|
||||
</th>
|
||||
<th>
|
||||
Th
|
||||
</th>
|
||||
<th>
|
||||
Fr
|
||||
</th>
|
||||
<th>
|
||||
Sa
|
||||
</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<tr
|
||||
class="mx-date-row"
|
||||
>
|
||||
<td
|
||||
class="mx-week-number"
|
||||
>
|
||||
29
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="cell not-current-month"
|
||||
data-date="1569686400000"
|
||||
title="2019-09-29"
|
||||
>
|
||||
<div>
|
||||
29
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell not-current-month"
|
||||
data-date="1569772800000"
|
||||
title="2019-09-30"
|
||||
>
|
||||
<div>
|
||||
30
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1569859200000"
|
||||
title="2019-10-01"
|
||||
>
|
||||
<div>
|
||||
1
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1569945600000"
|
||||
title="2019-10-02"
|
||||
>
|
||||
<div>
|
||||
2
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570032000000"
|
||||
title="2019-10-03"
|
||||
>
|
||||
<div>
|
||||
3
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570118400000"
|
||||
title="2019-10-04"
|
||||
>
|
||||
<div>
|
||||
4
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570204800000"
|
||||
title="2019-10-05"
|
||||
>
|
||||
<div>
|
||||
5
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr
|
||||
class="mx-date-row"
|
||||
>
|
||||
<td
|
||||
class="mx-week-number"
|
||||
>
|
||||
6
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570291200000"
|
||||
title="2019-10-06"
|
||||
>
|
||||
<div>
|
||||
6
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570377600000"
|
||||
title="2019-10-07"
|
||||
>
|
||||
<div>
|
||||
7
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570464000000"
|
||||
title="2019-10-08"
|
||||
>
|
||||
<div>
|
||||
8
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570550400000"
|
||||
title="2019-10-09"
|
||||
>
|
||||
<div>
|
||||
9
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570636800000"
|
||||
title="2019-10-10"
|
||||
>
|
||||
<div>
|
||||
10
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570723200000"
|
||||
title="2019-10-11"
|
||||
>
|
||||
<div>
|
||||
11
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570809600000"
|
||||
title="2019-10-12"
|
||||
>
|
||||
<div>
|
||||
12
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr
|
||||
class="mx-date-row mx-active-week"
|
||||
>
|
||||
<td
|
||||
class="mx-week-number"
|
||||
>
|
||||
13
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="cell active"
|
||||
data-date="1570896000000"
|
||||
title="2019-10-13"
|
||||
>
|
||||
<div>
|
||||
13
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570982400000"
|
||||
title="2019-10-14"
|
||||
>
|
||||
<div>
|
||||
14
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571068800000"
|
||||
title="2019-10-15"
|
||||
>
|
||||
<div>
|
||||
15
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571155200000"
|
||||
title="2019-10-16"
|
||||
>
|
||||
<div>
|
||||
16
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571241600000"
|
||||
title="2019-10-17"
|
||||
>
|
||||
<div>
|
||||
17
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571328000000"
|
||||
title="2019-10-18"
|
||||
>
|
||||
<div>
|
||||
18
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571414400000"
|
||||
title="2019-10-19"
|
||||
>
|
||||
<div>
|
||||
19
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr
|
||||
class="mx-date-row"
|
||||
>
|
||||
<td
|
||||
class="mx-week-number"
|
||||
>
|
||||
20
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571500800000"
|
||||
title="2019-10-20"
|
||||
>
|
||||
<div>
|
||||
20
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571587200000"
|
||||
title="2019-10-21"
|
||||
>
|
||||
<div>
|
||||
21
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571673600000"
|
||||
title="2019-10-22"
|
||||
>
|
||||
<div>
|
||||
22
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571760000000"
|
||||
title="2019-10-23"
|
||||
>
|
||||
<div>
|
||||
23
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571846400000"
|
||||
title="2019-10-24"
|
||||
>
|
||||
<div>
|
||||
24
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571932800000"
|
||||
title="2019-10-25"
|
||||
>
|
||||
<div>
|
||||
25
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572019200000"
|
||||
title="2019-10-26"
|
||||
>
|
||||
<div>
|
||||
26
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr
|
||||
class="mx-date-row"
|
||||
>
|
||||
<td
|
||||
class="mx-week-number"
|
||||
>
|
||||
27
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572105600000"
|
||||
title="2019-10-27"
|
||||
>
|
||||
<div>
|
||||
27
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572192000000"
|
||||
title="2019-10-28"
|
||||
>
|
||||
<div>
|
||||
28
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572278400000"
|
||||
title="2019-10-29"
|
||||
>
|
||||
<div>
|
||||
29
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572364800000"
|
||||
title="2019-10-30"
|
||||
>
|
||||
<div>
|
||||
30
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572451200000"
|
||||
title="2019-10-31"
|
||||
>
|
||||
<div>
|
||||
31
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell not-current-month"
|
||||
data-date="1572537600000"
|
||||
title="2019-11-01"
|
||||
>
|
||||
<div>
|
||||
1
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell not-current-month"
|
||||
data-date="1572624000000"
|
||||
title="2019-11-02"
|
||||
>
|
||||
<div>
|
||||
2
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr
|
||||
class="mx-date-row"
|
||||
>
|
||||
<td
|
||||
class="mx-week-number"
|
||||
>
|
||||
3
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="cell not-current-month"
|
||||
data-date="1572710400000"
|
||||
title="2019-11-03"
|
||||
>
|
||||
<div>
|
||||
3
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell not-current-month"
|
||||
data-date="1572796800000"
|
||||
title="2019-11-04"
|
||||
>
|
||||
<div>
|
||||
4
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell not-current-month"
|
||||
data-date="1572883200000"
|
||||
title="2019-11-05"
|
||||
>
|
||||
<div>
|
||||
5
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell not-current-month"
|
||||
data-date="1572969600000"
|
||||
title="2019-11-06"
|
||||
>
|
||||
<div>
|
||||
6
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell not-current-month"
|
||||
data-date="1573056000000"
|
||||
title="2019-11-07"
|
||||
>
|
||||
<div>
|
||||
7
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell not-current-month"
|
||||
data-date="1573142400000"
|
||||
title="2019-11-08"
|
||||
>
|
||||
<div>
|
||||
8
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell not-current-month"
|
||||
data-date="1573228800000"
|
||||
title="2019-11-09"
|
||||
>
|
||||
<div>
|
||||
9
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
`;
|
||||
@@ -0,0 +1,522 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TableDate corrent render 1`] = `
|
||||
<div
|
||||
class="mx-calendar mx-calendar-panel-date"
|
||||
>
|
||||
<div
|
||||
class="mx-calendar-header"
|
||||
>
|
||||
<button
|
||||
class="mx-btn mx-btn-text mx-btn-icon-double-left"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="mx-icon-double-left"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
class="mx-btn mx-btn-text mx-btn-icon-left"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="mx-icon-left"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
class="mx-btn mx-btn-text mx-btn-icon-double-right"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="mx-icon-double-right"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
class="mx-btn mx-btn-text mx-btn-icon-right"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="mx-icon-right"
|
||||
/>
|
||||
</button>
|
||||
<span
|
||||
class="mx-calendar-header-label"
|
||||
>
|
||||
|
||||
<button
|
||||
class="mx-btn mx-btn-text mx-btn-current-month"
|
||||
type="button"
|
||||
>
|
||||
Oct
|
||||
</button>
|
||||
<button
|
||||
class="mx-btn mx-btn-text mx-btn-current-year"
|
||||
type="button"
|
||||
>
|
||||
2019
|
||||
</button>
|
||||
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mx-calendar-content"
|
||||
>
|
||||
<table
|
||||
class="mx-table mx-table-date"
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<!--v-if-->
|
||||
|
||||
<th>
|
||||
Su
|
||||
</th>
|
||||
<th>
|
||||
Mo
|
||||
</th>
|
||||
<th>
|
||||
Tu
|
||||
</th>
|
||||
<th>
|
||||
We
|
||||
</th>
|
||||
<th>
|
||||
Th
|
||||
</th>
|
||||
<th>
|
||||
Fr
|
||||
</th>
|
||||
<th>
|
||||
Sa
|
||||
</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<tr
|
||||
class="mx-date-row"
|
||||
>
|
||||
<!--v-if-->
|
||||
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1569686400000"
|
||||
title="29/09/2019"
|
||||
>
|
||||
<div>
|
||||
29
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1569772800000"
|
||||
title="30/09/2019"
|
||||
>
|
||||
<div>
|
||||
30
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1569859200000"
|
||||
title="01/10/2019"
|
||||
>
|
||||
<div>
|
||||
1
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1569945600000"
|
||||
title="02/10/2019"
|
||||
>
|
||||
<div>
|
||||
2
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570032000000"
|
||||
title="03/10/2019"
|
||||
>
|
||||
<div>
|
||||
3
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570118400000"
|
||||
title="04/10/2019"
|
||||
>
|
||||
<div>
|
||||
4
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570204800000"
|
||||
title="05/10/2019"
|
||||
>
|
||||
<div>
|
||||
5
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr
|
||||
class="mx-date-row"
|
||||
>
|
||||
<!--v-if-->
|
||||
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570291200000"
|
||||
title="06/10/2019"
|
||||
>
|
||||
<div>
|
||||
6
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570377600000"
|
||||
title="07/10/2019"
|
||||
>
|
||||
<div>
|
||||
7
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570464000000"
|
||||
title="08/10/2019"
|
||||
>
|
||||
<div>
|
||||
8
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570550400000"
|
||||
title="09/10/2019"
|
||||
>
|
||||
<div>
|
||||
9
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570636800000"
|
||||
title="10/10/2019"
|
||||
>
|
||||
<div>
|
||||
10
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570723200000"
|
||||
title="11/10/2019"
|
||||
>
|
||||
<div>
|
||||
11
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570809600000"
|
||||
title="12/10/2019"
|
||||
>
|
||||
<div>
|
||||
12
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr
|
||||
class="mx-date-row"
|
||||
>
|
||||
<!--v-if-->
|
||||
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570896000000"
|
||||
title="13/10/2019"
|
||||
>
|
||||
<div>
|
||||
13
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1570982400000"
|
||||
title="14/10/2019"
|
||||
>
|
||||
<div>
|
||||
14
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571068800000"
|
||||
title="15/10/2019"
|
||||
>
|
||||
<div>
|
||||
15
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571155200000"
|
||||
title="16/10/2019"
|
||||
>
|
||||
<div>
|
||||
16
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571241600000"
|
||||
title="17/10/2019"
|
||||
>
|
||||
<div>
|
||||
17
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571328000000"
|
||||
title="18/10/2019"
|
||||
>
|
||||
<div>
|
||||
18
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571414400000"
|
||||
title="19/10/2019"
|
||||
>
|
||||
<div>
|
||||
19
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr
|
||||
class="mx-date-row"
|
||||
>
|
||||
<!--v-if-->
|
||||
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571500800000"
|
||||
title="20/10/2019"
|
||||
>
|
||||
<div>
|
||||
20
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571587200000"
|
||||
title="21/10/2019"
|
||||
>
|
||||
<div>
|
||||
21
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571673600000"
|
||||
title="22/10/2019"
|
||||
>
|
||||
<div>
|
||||
22
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571760000000"
|
||||
title="23/10/2019"
|
||||
>
|
||||
<div>
|
||||
23
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571846400000"
|
||||
title="24/10/2019"
|
||||
>
|
||||
<div>
|
||||
24
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1571932800000"
|
||||
title="25/10/2019"
|
||||
>
|
||||
<div>
|
||||
25
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572019200000"
|
||||
title="26/10/2019"
|
||||
>
|
||||
<div>
|
||||
26
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr
|
||||
class="mx-date-row"
|
||||
>
|
||||
<!--v-if-->
|
||||
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572105600000"
|
||||
title="27/10/2019"
|
||||
>
|
||||
<div>
|
||||
27
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572192000000"
|
||||
title="28/10/2019"
|
||||
>
|
||||
<div>
|
||||
28
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572278400000"
|
||||
title="29/10/2019"
|
||||
>
|
||||
<div>
|
||||
29
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572364800000"
|
||||
title="30/10/2019"
|
||||
>
|
||||
<div>
|
||||
30
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572451200000"
|
||||
title="31/10/2019"
|
||||
>
|
||||
<div>
|
||||
31
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572537600000"
|
||||
title="01/11/2019"
|
||||
>
|
||||
<div>
|
||||
1
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572624000000"
|
||||
title="02/11/2019"
|
||||
>
|
||||
<div>
|
||||
2
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr
|
||||
class="mx-date-row"
|
||||
>
|
||||
<!--v-if-->
|
||||
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572710400000"
|
||||
title="03/11/2019"
|
||||
>
|
||||
<div>
|
||||
3
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572796800000"
|
||||
title="04/11/2019"
|
||||
>
|
||||
<div>
|
||||
4
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572883200000"
|
||||
title="05/11/2019"
|
||||
>
|
||||
<div>
|
||||
5
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1572969600000"
|
||||
title="06/11/2019"
|
||||
>
|
||||
<div>
|
||||
6
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1573056000000"
|
||||
title="07/11/2019"
|
||||
>
|
||||
<div>
|
||||
7
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1573142400000"
|
||||
title="08/11/2019"
|
||||
>
|
||||
<div>
|
||||
8
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-date="1573228800000"
|
||||
title="09/11/2019"
|
||||
>
|
||||
<div>
|
||||
9
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -0,0 +1,160 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TableMonth correct render 1`] = `
|
||||
<div
|
||||
class="mx-calendar mx-calendar-panel-month"
|
||||
>
|
||||
<div
|
||||
class="mx-calendar-header"
|
||||
>
|
||||
<button
|
||||
class="mx-btn mx-btn-text mx-btn-icon-double-left"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="mx-icon-double-left"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
class="mx-btn mx-btn-text mx-btn-icon-double-right"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="mx-icon-double-right"
|
||||
/>
|
||||
</button>
|
||||
<span
|
||||
class="mx-calendar-header-label"
|
||||
>
|
||||
<button
|
||||
class="mx-btn mx-btn-text"
|
||||
type="button"
|
||||
>
|
||||
2019
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mx-calendar-content"
|
||||
>
|
||||
<table
|
||||
class="mx-table mx-table-month"
|
||||
>
|
||||
|
||||
<tr>
|
||||
|
||||
<td
|
||||
class="cell"
|
||||
data-month="0"
|
||||
>
|
||||
<div>
|
||||
Jan
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-month="1"
|
||||
>
|
||||
<div>
|
||||
Feb
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-month="2"
|
||||
>
|
||||
<div>
|
||||
Mar
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
<td
|
||||
class="cell"
|
||||
data-month="3"
|
||||
>
|
||||
<div>
|
||||
Apr
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-month="4"
|
||||
>
|
||||
<div>
|
||||
May
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-month="5"
|
||||
>
|
||||
<div>
|
||||
Jun
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
<td
|
||||
class="cell"
|
||||
data-month="6"
|
||||
>
|
||||
<div>
|
||||
Jul
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-month="7"
|
||||
>
|
||||
<div>
|
||||
Aug
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-month="8"
|
||||
>
|
||||
<div>
|
||||
Sep
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
<td
|
||||
class="cell active"
|
||||
data-month="9"
|
||||
>
|
||||
<div>
|
||||
Oct
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-month="10"
|
||||
>
|
||||
<div>
|
||||
Nov
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-month="11"
|
||||
>
|
||||
<div>
|
||||
Dec
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -0,0 +1,151 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TableYear decade=2010 1`] = `
|
||||
<div
|
||||
class="mx-calendar mx-calendar-panel-year"
|
||||
>
|
||||
<div
|
||||
class="mx-calendar-header"
|
||||
>
|
||||
<button
|
||||
class="mx-btn mx-btn-text mx-btn-icon-double-left"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="mx-icon-double-left"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
class="mx-btn mx-btn-text mx-btn-icon-double-right"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="mx-icon-double-right"
|
||||
/>
|
||||
</button>
|
||||
<span
|
||||
class="mx-calendar-header-label"
|
||||
>
|
||||
<span>
|
||||
2010
|
||||
</span>
|
||||
<span
|
||||
class="mx-calendar-decade-separator"
|
||||
/>
|
||||
<span>
|
||||
2019
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mx-calendar-content"
|
||||
>
|
||||
<table
|
||||
class="mx-table mx-table-year"
|
||||
>
|
||||
|
||||
<tr>
|
||||
|
||||
<td
|
||||
class="cell"
|
||||
data-year="2010"
|
||||
>
|
||||
<div>
|
||||
2010
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-year="2011"
|
||||
>
|
||||
<div>
|
||||
2011
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
<td
|
||||
class="cell"
|
||||
data-year="2012"
|
||||
>
|
||||
<div>
|
||||
2012
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-year="2013"
|
||||
>
|
||||
<div>
|
||||
2013
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
<td
|
||||
class="cell"
|
||||
data-year="2014"
|
||||
>
|
||||
<div>
|
||||
2014
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-year="2015"
|
||||
>
|
||||
<div>
|
||||
2015
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
<td
|
||||
class="cell"
|
||||
data-year="2016"
|
||||
>
|
||||
<div>
|
||||
2016
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-year="2017"
|
||||
>
|
||||
<div>
|
||||
2017
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
<td
|
||||
class="cell"
|
||||
data-year="2018"
|
||||
>
|
||||
<div>
|
||||
2018
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="cell"
|
||||
data-year="2019"
|
||||
>
|
||||
<div>
|
||||
2019
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,320 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TimeRange render: correct classes of the columns 1`] = `
|
||||
<div
|
||||
class="mx-range-wrapper"
|
||||
>
|
||||
<div
|
||||
class="mx-time"
|
||||
>
|
||||
<!--v-if-->
|
||||
<div
|
||||
class="mx-time-content"
|
||||
>
|
||||
<div
|
||||
class="mx-time-columns"
|
||||
>
|
||||
|
||||
<div
|
||||
class="mx-scrollbar mx-time-column"
|
||||
style="position: relative; overflow: hidden;"
|
||||
>
|
||||
<div
|
||||
class="mx-scrollbar-wrap"
|
||||
style="margin-right: -0px;"
|
||||
>
|
||||
|
||||
<ul
|
||||
class="mx-time-list"
|
||||
data-index="0"
|
||||
data-type="hour"
|
||||
>
|
||||
|
||||
<li
|
||||
class="mx-time-item"
|
||||
data-index="0"
|
||||
>
|
||||
12
|
||||
</li>
|
||||
<li
|
||||
class="mx-time-item"
|
||||
data-index="1"
|
||||
>
|
||||
02
|
||||
</li>
|
||||
<li
|
||||
class="mx-time-item"
|
||||
data-index="2"
|
||||
>
|
||||
04
|
||||
</li>
|
||||
<li
|
||||
class="mx-time-item"
|
||||
data-index="3"
|
||||
>
|
||||
06
|
||||
</li>
|
||||
<li
|
||||
class="mx-time-item active"
|
||||
data-index="4"
|
||||
>
|
||||
08
|
||||
</li>
|
||||
<li
|
||||
class="mx-time-item"
|
||||
data-index="5"
|
||||
>
|
||||
10
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div
|
||||
class="mx-scrollbar-track"
|
||||
>
|
||||
<div
|
||||
class="mx-scrollbar-thumb"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx-scrollbar mx-time-column"
|
||||
style="position: relative; overflow: hidden;"
|
||||
>
|
||||
<div
|
||||
class="mx-scrollbar-wrap"
|
||||
style="margin-right: -0px;"
|
||||
>
|
||||
|
||||
<ul
|
||||
class="mx-time-list"
|
||||
data-index="1"
|
||||
data-type="minute"
|
||||
>
|
||||
|
||||
<li
|
||||
class="mx-time-item"
|
||||
data-index="0"
|
||||
>
|
||||
00
|
||||
</li>
|
||||
<li
|
||||
class="mx-time-item active"
|
||||
data-index="1"
|
||||
>
|
||||
30
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div
|
||||
class="mx-scrollbar-track"
|
||||
>
|
||||
<div
|
||||
class="mx-scrollbar-thumb"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx-scrollbar mx-time-column"
|
||||
style="position: relative; overflow: hidden;"
|
||||
>
|
||||
<div
|
||||
class="mx-scrollbar-wrap"
|
||||
style="margin-right: -0px;"
|
||||
>
|
||||
|
||||
<ul
|
||||
class="mx-time-list"
|
||||
data-index="2"
|
||||
data-type="ampm"
|
||||
>
|
||||
|
||||
<li
|
||||
class="mx-time-item active"
|
||||
data-index="0"
|
||||
>
|
||||
AM
|
||||
</li>
|
||||
<li
|
||||
class="mx-time-item"
|
||||
data-index="1"
|
||||
>
|
||||
PM
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div
|
||||
class="mx-scrollbar-track"
|
||||
>
|
||||
<div
|
||||
class="mx-scrollbar-thumb"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx-time"
|
||||
>
|
||||
<!--v-if-->
|
||||
<div
|
||||
class="mx-time-content"
|
||||
>
|
||||
<div
|
||||
class="mx-time-columns"
|
||||
>
|
||||
|
||||
<div
|
||||
class="mx-scrollbar mx-time-column"
|
||||
style="position: relative; overflow: hidden;"
|
||||
>
|
||||
<div
|
||||
class="mx-scrollbar-wrap"
|
||||
style="margin-right: -0px;"
|
||||
>
|
||||
|
||||
<ul
|
||||
class="mx-time-list"
|
||||
data-index="0"
|
||||
data-type="hour"
|
||||
>
|
||||
|
||||
<li
|
||||
class="mx-time-item"
|
||||
data-index="0"
|
||||
>
|
||||
12
|
||||
</li>
|
||||
<li
|
||||
class="mx-time-item"
|
||||
data-index="1"
|
||||
>
|
||||
02
|
||||
</li>
|
||||
<li
|
||||
class="mx-time-item"
|
||||
data-index="2"
|
||||
>
|
||||
04
|
||||
</li>
|
||||
<li
|
||||
class="mx-time-item active"
|
||||
data-index="3"
|
||||
>
|
||||
06
|
||||
</li>
|
||||
<li
|
||||
class="mx-time-item"
|
||||
data-index="4"
|
||||
>
|
||||
08
|
||||
</li>
|
||||
<li
|
||||
class="mx-time-item"
|
||||
data-index="5"
|
||||
>
|
||||
10
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div
|
||||
class="mx-scrollbar-track"
|
||||
>
|
||||
<div
|
||||
class="mx-scrollbar-thumb"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx-scrollbar mx-time-column"
|
||||
style="position: relative; overflow: hidden;"
|
||||
>
|
||||
<div
|
||||
class="mx-scrollbar-wrap"
|
||||
style="margin-right: -0px;"
|
||||
>
|
||||
|
||||
<ul
|
||||
class="mx-time-list"
|
||||
data-index="1"
|
||||
data-type="minute"
|
||||
>
|
||||
|
||||
<li
|
||||
class="mx-time-item"
|
||||
data-index="0"
|
||||
>
|
||||
00
|
||||
</li>
|
||||
<li
|
||||
class="mx-time-item active"
|
||||
data-index="1"
|
||||
>
|
||||
30
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div
|
||||
class="mx-scrollbar-track"
|
||||
>
|
||||
<div
|
||||
class="mx-scrollbar-thumb"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx-scrollbar mx-time-column"
|
||||
style="position: relative; overflow: hidden;"
|
||||
>
|
||||
<div
|
||||
class="mx-scrollbar-wrap"
|
||||
style="margin-right: -0px;"
|
||||
>
|
||||
|
||||
<ul
|
||||
class="mx-time-list"
|
||||
data-index="2"
|
||||
data-type="ampm"
|
||||
>
|
||||
|
||||
<li
|
||||
class="mx-time-item disabled"
|
||||
data-index="0"
|
||||
>
|
||||
AM
|
||||
</li>
|
||||
<li
|
||||
class="mx-time-item active"
|
||||
data-index="1"
|
||||
>
|
||||
PM
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div
|
||||
class="mx-scrollbar-track"
|
||||
>
|
||||
<div
|
||||
class="mx-scrollbar-thumb"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -0,0 +1,234 @@
|
||||
/* eslint-disable no-await-in-loop */
|
||||
import { mount, shallowMount } from '@vue/test-utils';
|
||||
import CalendarPanel from '../src/calendar/calendar-panel';
|
||||
|
||||
let wrapper;
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
describe('CalendarPanel', () => {
|
||||
it('feat: type = date, should emit select when click date', () => {
|
||||
wrapper = mount(CalendarPanel, {
|
||||
props: {
|
||||
value: new Date(2019, 9, 4),
|
||||
},
|
||||
});
|
||||
const td = wrapper.find('.mx-table-date td');
|
||||
td.trigger('click');
|
||||
expect(wrapper.emitted().select[0][0]).toEqual(new Date(2019, 8, 29));
|
||||
});
|
||||
|
||||
it('feat: type = month, should emit event when click month', () => {
|
||||
wrapper = mount(CalendarPanel, {
|
||||
props: {
|
||||
type: 'month',
|
||||
defaultValue: new Date(2019, 9, 1),
|
||||
},
|
||||
});
|
||||
const td = wrapper.find('.mx-table-month td > div');
|
||||
td.trigger('click');
|
||||
expect(wrapper.emitted().select[0][0]).toEqual(new Date(2019, 0, 1));
|
||||
});
|
||||
|
||||
it('feat: type = year, should emit event when click year', () => {
|
||||
wrapper = mount(CalendarPanel, {
|
||||
props: {
|
||||
type: 'year',
|
||||
defaultValue: new Date(2019, 9, 1),
|
||||
},
|
||||
});
|
||||
const td = wrapper.find('.mx-table-year td > div');
|
||||
td.trigger('click');
|
||||
expect(wrapper.emitted().select[0][0]).toEqual(new Date(2010, 0));
|
||||
});
|
||||
|
||||
it('feat: when year >= 0 && year < 100, should be emit right', () => {
|
||||
wrapper = mount(CalendarPanel, {
|
||||
props: {
|
||||
type: 'year',
|
||||
defaultValue: new Date().setFullYear(11),
|
||||
},
|
||||
});
|
||||
const td = wrapper.find('.mx-table-year td > div');
|
||||
td.trigger('click');
|
||||
const expectedDate = new Date(10, 0).setFullYear(10);
|
||||
expect(wrapper.emitted().select[0][0].getTime()).toBe(expectedDate);
|
||||
});
|
||||
|
||||
it('feat: active class', async () => {
|
||||
wrapper = mount(CalendarPanel);
|
||||
const td = wrapper.find('.mx-table-date td:nth-child(6)');
|
||||
expect(td.classes()).not.toContain('active');
|
||||
await wrapper.setProps({ value: new Date(2019, 9, 4) });
|
||||
expect(td.classes()).toContain('active');
|
||||
});
|
||||
|
||||
it('feat: panel change', async () => {
|
||||
wrapper = mount(CalendarPanel);
|
||||
const { vm } = wrapper;
|
||||
await wrapper.find('.mx-btn-current-year').trigger('click');
|
||||
expect(vm.panel).toBe('year');
|
||||
await wrapper.find('.mx-table-year td > div').trigger('click');
|
||||
expect(vm.panel).toBe('month');
|
||||
await wrapper.find('.mx-table-month td > div').trigger('click');
|
||||
expect(vm.panel).toBe('date');
|
||||
await wrapper.find('.mx-btn-current-month').trigger('click');
|
||||
expect(vm.panel).toBe('month');
|
||||
await wrapper.find('.mx-calendar-header-label > button').trigger('click');
|
||||
expect(vm.panel).toBe('year');
|
||||
});
|
||||
|
||||
it('feat: click prev/next month', async () => {
|
||||
wrapper = mount(CalendarPanel);
|
||||
|
||||
const nextBtn = wrapper.find('.mx-btn-icon-right');
|
||||
const lastBtn = wrapper.find('.mx-btn-icon-left');
|
||||
const { vm } = wrapper;
|
||||
let count = 12;
|
||||
while (count--) {
|
||||
const oldYear = vm.calendarYear;
|
||||
const oldMonth = vm.calendarMonth;
|
||||
await nextBtn.trigger('click');
|
||||
const newYear = vm.calendarYear;
|
||||
const newMonth = vm.calendarMonth;
|
||||
if (oldMonth === 11) {
|
||||
expect(newMonth).toBe(0);
|
||||
expect(newYear).toBe(oldYear + 1);
|
||||
} else {
|
||||
expect(newMonth).toBe(oldMonth + 1);
|
||||
expect(newYear).toBe(oldYear);
|
||||
}
|
||||
}
|
||||
count = 12;
|
||||
while (count--) {
|
||||
const oldYear = vm.calendarYear;
|
||||
const oldMonth = vm.calendarMonth;
|
||||
await lastBtn.trigger('click');
|
||||
const newYear = vm.calendarYear;
|
||||
const newMonth = vm.calendarMonth;
|
||||
if (oldMonth === 0) {
|
||||
expect(newMonth).toBe(11);
|
||||
expect(newYear).toBe(oldYear - 1);
|
||||
} else {
|
||||
expect(newMonth).toBe(oldMonth - 1);
|
||||
expect(newYear).toBe(oldYear);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
['date', 'month'].forEach((type) => {
|
||||
it(`feat: click prev/next year in ${type} panel`, async () => {
|
||||
wrapper = mount(CalendarPanel, {
|
||||
props: {
|
||||
value: new Date(2018, 4, 5),
|
||||
defaultPanel: type,
|
||||
},
|
||||
});
|
||||
const nextBtn = wrapper.find('.mx-btn-icon-double-right');
|
||||
const lastBtn = wrapper.find('.mx-btn-icon-double-left');
|
||||
const { vm } = wrapper;
|
||||
const oldYear = vm.calendarYear;
|
||||
expect(oldYear).toBe(2018);
|
||||
await nextBtn.trigger('click');
|
||||
let newYear = vm.calendarYear;
|
||||
expect(newYear).toBe(2019);
|
||||
await lastBtn.trigger('click');
|
||||
newYear = vm.calendarYear;
|
||||
expect(newYear).toBe(oldYear);
|
||||
});
|
||||
});
|
||||
|
||||
it('feat: click prev/next decade', () => {
|
||||
wrapper = mount(CalendarPanel, {
|
||||
props: {
|
||||
value: new Date(2018, 4, 5),
|
||||
defaultPanel: 'year',
|
||||
},
|
||||
});
|
||||
const nextBtn = wrapper.find('.mx-btn-icon-double-right');
|
||||
const lastBtn = wrapper.find('.mx-btn-icon-double-left');
|
||||
nextBtn.trigger('click');
|
||||
expect(wrapper.vm.calendarYear).toBe(2028);
|
||||
lastBtn.trigger('click');
|
||||
lastBtn.trigger('click');
|
||||
expect(wrapper.vm.calendarYear).toBe(2008);
|
||||
});
|
||||
|
||||
const renderType = (type) => {
|
||||
it(`prop: type=${type}`, () => {
|
||||
wrapper = shallowMount(CalendarPanel, {
|
||||
props: {
|
||||
type,
|
||||
value: new Date(2019, 9, 1, 10),
|
||||
},
|
||||
});
|
||||
expect(wrapper.vm.panel).toBe(type);
|
||||
});
|
||||
};
|
||||
['date', 'month', 'year'].forEach(renderType);
|
||||
|
||||
it('feat: select year to change the calendar', async () => {
|
||||
wrapper = mount(CalendarPanel, {
|
||||
props: {
|
||||
value: new Date(2018, 4, 5),
|
||||
defaultPanel: 'year',
|
||||
},
|
||||
});
|
||||
await wrapper.find('.mx-table-year td > div').trigger('click');
|
||||
expect(wrapper.vm.calendarYear).toBe(2010);
|
||||
await wrapper.find('.mx-table-month td > div').trigger('click');
|
||||
expect(wrapper.vm.calendarMonth).toBe(0);
|
||||
});
|
||||
|
||||
it('prop: disabledDate', () => {
|
||||
const disabledDate = (date) => {
|
||||
return date < new Date(2019, 9, 1) || date > new Date(2019, 9, 20);
|
||||
};
|
||||
wrapper = mount(CalendarPanel, {
|
||||
props: {
|
||||
value: new Date(2019, 9, 4),
|
||||
disabledDate,
|
||||
},
|
||||
});
|
||||
const tds = wrapper.findAll('.mx-table-date td');
|
||||
for (let i = 0; i < 42; i++) {
|
||||
const td = tds[i];
|
||||
const classes = td.classes();
|
||||
if (i < 2 || i > 21) {
|
||||
expect(classes).toContain('disabled');
|
||||
} else {
|
||||
expect(classes).not.toContain('disabled');
|
||||
}
|
||||
}
|
||||
tds[1].trigger('click');
|
||||
expect(wrapper.emitted().select).toBeUndefined();
|
||||
});
|
||||
|
||||
it('prop: partialUpdate', async () => {
|
||||
wrapper = mount(CalendarPanel, {
|
||||
props: {
|
||||
value: new Date(2019, 9, 4),
|
||||
partialUpdate: true,
|
||||
defaultPanel: 'year',
|
||||
},
|
||||
});
|
||||
wrapper.findAll('.mx-table-year td > div')[0].trigger('click');
|
||||
expect(wrapper.emitted().select[0][0]).toEqual(new Date(2010, 9, 4));
|
||||
await wrapper.setProps({ value: new Date(2010, 9, 4) });
|
||||
wrapper.find('.mx-table-month td > div').trigger('click');
|
||||
expect(wrapper.emitted().select[1][0]).toEqual(new Date(2010, 0, 4));
|
||||
});
|
||||
|
||||
it('prop: defaultPanel', () => {
|
||||
wrapper = mount(CalendarPanel, {
|
||||
props: {
|
||||
open: true,
|
||||
type: 'month',
|
||||
defaultPanel: 'year',
|
||||
},
|
||||
});
|
||||
expect(wrapper.vm.panel).toBe('year');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,83 @@
|
||||
import { mount } from '@vue/test-utils';
|
||||
import CalendarRange from '../src/calendar/calendar-range';
|
||||
import CalendarPanel from '../src/calendar/calendar-panel';
|
||||
|
||||
let wrapper;
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
describe('CalendarRange', () => {
|
||||
it('feat: correct classes', () => {
|
||||
wrapper = mount(CalendarRange, {
|
||||
props: {
|
||||
value: [new Date(2019, 9, 30), new Date(2019, 10, 2)],
|
||||
},
|
||||
});
|
||||
const activeTds = wrapper.findAll('.mx-table-date .active');
|
||||
const rangeTds = wrapper.findAll('.mx-table-date .in-range');
|
||||
expect(activeTds.length).toBe(2);
|
||||
expect(activeTds[0].text()).toBe('30');
|
||||
expect(activeTds[1].text()).toBe('2');
|
||||
expect(rangeTds.length).toBe(2);
|
||||
expect(rangeTds[0].text()).toBe('31');
|
||||
expect(rangeTds[1].text()).toBe('1');
|
||||
});
|
||||
|
||||
it('feat: click range', async () => {
|
||||
wrapper = mount(CalendarRange, {
|
||||
props: {
|
||||
defaultValue: new Date(2019, 9, 1),
|
||||
},
|
||||
});
|
||||
expect(wrapper.vm.calendars).toEqual([new Date(2019, 9, 1), new Date(2019, 10, 1)]);
|
||||
const tds = wrapper.findAll('.mx-table-date td');
|
||||
await tds[2].trigger('click');
|
||||
expect(wrapper.emitted().select).toBeUndefined();
|
||||
await tds[8].trigger('click');
|
||||
expect(wrapper.emitted().select[0][0]).toEqual([new Date(2019, 9, 1), new Date(2019, 9, 7)]);
|
||||
});
|
||||
|
||||
it('feat: calendars min gap', async () => {
|
||||
wrapper = mount(CalendarRange, {
|
||||
props: {
|
||||
defaultValue: new Date(2019, 6, 1),
|
||||
},
|
||||
});
|
||||
const firstRightIcon = wrapper.find('.mx-calendar-panel-date .mx-btn-icon-right');
|
||||
const secondLeftIcon = wrapper.find('.mx-calendar-panel-date:nth-child(2) .mx-btn-icon-left');
|
||||
|
||||
await firstRightIcon.trigger('click');
|
||||
expect(wrapper.vm.calendars).toEqual([new Date(2019, 7, 1), new Date(2019, 8, 1)]);
|
||||
|
||||
await secondLeftIcon.trigger('click');
|
||||
expect(wrapper.vm.calendars).toEqual([new Date(2019, 6, 1), new Date(2019, 7, 1)]);
|
||||
});
|
||||
|
||||
it('partialUpdate should be false', () => {
|
||||
wrapper = mount(CalendarRange, {
|
||||
props: {
|
||||
partialUpdate: true,
|
||||
},
|
||||
});
|
||||
const panels = wrapper.findAllComponents(CalendarPanel);
|
||||
const startPanel = panels[0];
|
||||
const endPanel = panels[1];
|
||||
expect(startPanel.vm.partialUpdate).toBe(false);
|
||||
expect(endPanel.vm.partialUpdate).toBe(false);
|
||||
});
|
||||
|
||||
it('supports defaultValue is Array', () => {
|
||||
wrapper = mount(CalendarRange, {
|
||||
props: {
|
||||
defaultValue: [new Date(2019, 9, 1), new Date(2019, 11, 1)],
|
||||
},
|
||||
});
|
||||
const panels = wrapper.findAllComponents(CalendarPanel);
|
||||
const startPanel = panels[0];
|
||||
const endPanel = panels[1];
|
||||
expect(startPanel.vm.calendarMonth).toBe(9);
|
||||
expect(endPanel.vm.calendarMonth).toBe(11);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,456 @@
|
||||
import { mount } from '@vue/test-utils';
|
||||
import { format, parse } from 'date-fns';
|
||||
import { nextTick } from 'vue';
|
||||
import Popup from '../src/popup';
|
||||
import DatePicker from '../src/date-picker';
|
||||
|
||||
const shallowMount = mount;
|
||||
|
||||
let wrapper;
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
describe('DatePicker', () => {
|
||||
it('feat: open and close the popup', async () => {
|
||||
wrapper = mount(DatePicker, {
|
||||
attachTo: document.body,
|
||||
appendToBody: false,
|
||||
});
|
||||
expect(wrapper.vm.popupVisible).toBe(false);
|
||||
// expect click input should show the popup
|
||||
const input = wrapper.find('input');
|
||||
await input.trigger('mousedown');
|
||||
expect(wrapper.vm.popupVisible).toBe(true);
|
||||
// expect click out side should hide the popup
|
||||
document.body.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
|
||||
await nextTick();
|
||||
expect(wrapper.vm.popupVisible).toBe(false);
|
||||
// expect focus input should show the popop
|
||||
await input.trigger('focus');
|
||||
expect(wrapper.vm.popupVisible).toBe(true);
|
||||
// expoce keydown tab should hide the popup
|
||||
await input.trigger('keydown.tab');
|
||||
expect(wrapper.vm.popupVisible).toBe(false);
|
||||
});
|
||||
|
||||
it('feat: should init panel and calendar when reopen', async () => {
|
||||
wrapper = mount(DatePicker, {
|
||||
props: {
|
||||
defaultValue: new Date(2019, 9, 1),
|
||||
open: true,
|
||||
appendToBody: false,
|
||||
},
|
||||
});
|
||||
const yearBtn = wrapper.find('.mx-btn-current-year');
|
||||
await yearBtn.trigger('click');
|
||||
// change to year panel
|
||||
expect(wrapper.find('.mx-calendar-panel-year').exists()).toBe(true);
|
||||
await wrapper.setProps({ open: false });
|
||||
await wrapper.setProps({ open: true });
|
||||
expect(wrapper.find('.mx-calendar-panel-year').exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('prop: open', async () => {
|
||||
wrapper = mount(DatePicker, {
|
||||
props: {
|
||||
open: false,
|
||||
appendToBody: false,
|
||||
},
|
||||
});
|
||||
const { vm } = wrapper;
|
||||
vm.openPopup();
|
||||
expect(wrapper.find('.mx-datepicker-popup').exists()).toBe(false);
|
||||
await wrapper.setProps({ open: true });
|
||||
expect(wrapper.find('.mx-datepicker-popup').exists()).toBe(true);
|
||||
vm.closePopup();
|
||||
expect(wrapper.find('.mx-datepicker-popup').exists()).toBe(true);
|
||||
const emitted = wrapper.emitted();
|
||||
expect(emitted['update:open'][0][0]).toBe(true);
|
||||
expect(emitted['update:open'][1][0]).toBe(false);
|
||||
});
|
||||
|
||||
it('prop: disabled(should not show the popup)', () => {
|
||||
wrapper = mount(DatePicker, {
|
||||
props: {
|
||||
disabled: true,
|
||||
},
|
||||
});
|
||||
const input = wrapper.find('input');
|
||||
expect(input.attributes('disabled')).not.toBeUndefined();
|
||||
input.trigger('click');
|
||||
expect(wrapper.find('.mx-datepicker-popup').exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('prop: clearable', () => {
|
||||
wrapper = shallowMount(DatePicker, {
|
||||
props: {
|
||||
value: new Date(2019, 4, 10),
|
||||
defaultValue: new Date(2019, 4, 10),
|
||||
clearable: false,
|
||||
},
|
||||
// calendar-panel: default-value="Fri May 10 2019 00:00:00 GMT+0800 (CST)"
|
||||
// Exclude the impact of timezone
|
||||
scopedSlots: {
|
||||
content: '<div></div>',
|
||||
},
|
||||
});
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('prop: editable', () => {
|
||||
wrapper = shallowMount(DatePicker, {
|
||||
props: {
|
||||
value: new Date(2019, 4, 10),
|
||||
defaultValue: new Date(2019, 4, 10),
|
||||
editable: false,
|
||||
},
|
||||
scopedSlots: {
|
||||
content: '<div></div>',
|
||||
},
|
||||
});
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('prop: attrs of input', () => {
|
||||
wrapper = shallowMount(DatePicker, {
|
||||
props: {
|
||||
defaultValue: new Date(2019, 4, 10),
|
||||
placeholder: 'test placeholder',
|
||||
inputClass: 'test',
|
||||
inputAttr: {
|
||||
type: 'number',
|
||||
name: 'test',
|
||||
},
|
||||
},
|
||||
scopedSlots: {
|
||||
content: '<div></div>',
|
||||
},
|
||||
});
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('prop: format', () => {
|
||||
wrapper = shallowMount(DatePicker, {
|
||||
props: {
|
||||
format: 'YYYY/MM/DD',
|
||||
value: new Date(2019, 9, 10),
|
||||
},
|
||||
});
|
||||
const input = wrapper.find('input').element;
|
||||
expect(input.value).toBe('2019/10/10');
|
||||
});
|
||||
|
||||
it('prop: formatter', () => {
|
||||
wrapper = mount(DatePicker, {
|
||||
props: {
|
||||
valueType: 'format',
|
||||
value: '13/10/2019',
|
||||
open: true,
|
||||
type: 'week',
|
||||
appendToBody: false,
|
||||
formatter: {
|
||||
stringify(date) {
|
||||
return format(date, 'dd/MM/yyyy');
|
||||
},
|
||||
parse(value) {
|
||||
return parse(value, 'dd/MM/yyyy', new Date());
|
||||
},
|
||||
getWeek(date) {
|
||||
return date.getDate();
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const input = wrapper.find('input').element;
|
||||
expect(input.value).toBe('13/10/2019');
|
||||
const tableDate = wrapper.find('.mx-table-date');
|
||||
expect(tableDate.element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('prop: valueType', async () => {
|
||||
const value = new Date(2019, 9, 20);
|
||||
const emitValue = new Date(2019, 9, 22);
|
||||
wrapper = shallowMount(DatePicker, {
|
||||
props: {
|
||||
value: value,
|
||||
format: 'YYYY/MM/DD',
|
||||
},
|
||||
});
|
||||
const { vm } = wrapper;
|
||||
expect(vm.text).toBe('2019/10/20');
|
||||
vm.emitValue(emitValue);
|
||||
await wrapper.setProps({ valueType: 'format', value: '2019/10/20' });
|
||||
expect(vm.text).toBe('2019/10/20');
|
||||
vm.emitValue(emitValue);
|
||||
await wrapper.setProps({ valueType: 'timestamp', value: value.getTime() });
|
||||
expect(vm.text).toBe('2019/10/20');
|
||||
vm.emitValue(emitValue);
|
||||
await wrapper.setProps({ valueType: 'DD/MM/YYYY', value: '20/10/2019' });
|
||||
expect(vm.text).toBe('2019/10/20');
|
||||
vm.emitValue(emitValue);
|
||||
const emitted = wrapper.emitted();
|
||||
expect(emitted.input).toEqual([
|
||||
[emitValue],
|
||||
['2019/10/22'],
|
||||
[emitValue.getTime()],
|
||||
['22/10/2019'],
|
||||
]);
|
||||
});
|
||||
|
||||
it('prop: shortcut', async () => {
|
||||
const date = new Date(2019, 4, 10);
|
||||
wrapper = shallowMount(DatePicker, {
|
||||
props: {
|
||||
open: true,
|
||||
valueType: 'YYYY/MM/DD',
|
||||
range: false,
|
||||
appendToBody: false,
|
||||
shortcuts: [
|
||||
{
|
||||
text: 'Today',
|
||||
onClick() {
|
||||
return date;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const btn = wrapper.find('.mx-btn-shortcut');
|
||||
await btn.trigger('click');
|
||||
const emitted = wrapper.emitted();
|
||||
expect(emitted.input).toEqual([['2019/05/10']]);
|
||||
await wrapper.setProps({
|
||||
range: true,
|
||||
shortcuts: [
|
||||
{
|
||||
text: 'range',
|
||||
onClick() {
|
||||
return [date, date];
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
btn.trigger('click');
|
||||
expect(emitted.input[1]).toEqual([['2019/05/10', '2019/05/10']]);
|
||||
});
|
||||
|
||||
it('prop: popupClass', () => {
|
||||
wrapper = mount(DatePicker, {
|
||||
props: {
|
||||
open: true,
|
||||
popupClass: 'test',
|
||||
},
|
||||
});
|
||||
const popup = wrapper.findComponent(Popup);
|
||||
expect(popup.classes()).toContain('test');
|
||||
});
|
||||
|
||||
it('prop: popupStyle', () => {
|
||||
wrapper = mount(DatePicker, {
|
||||
props: {
|
||||
open: true,
|
||||
popupStyle: {
|
||||
color: 'red',
|
||||
},
|
||||
},
|
||||
});
|
||||
const popup = wrapper.findComponent(Popup);
|
||||
expect(popup.element.style.color).toBe('red');
|
||||
});
|
||||
|
||||
it('prop: confirm', async () => {
|
||||
wrapper = shallowMount(DatePicker, {
|
||||
props: {
|
||||
confirm: true,
|
||||
appendToBody: false,
|
||||
},
|
||||
});
|
||||
const { vm } = wrapper;
|
||||
await wrapper.find('input').trigger('focus');
|
||||
const btn = wrapper.find('.mx-datepicker-btn-confirm');
|
||||
expect(btn.exists()).toBe(true);
|
||||
// click the date expect popup don't close
|
||||
vm.handleSelectDate(new Date(2018, 5, 5));
|
||||
expect(wrapper.emitted().input).toBeUndefined();
|
||||
expect(vm.popupVisible).toBe(true);
|
||||
await btn.trigger('click');
|
||||
expect(wrapper.emitted().input[0][0]).toEqual(new Date(2018, 5, 5));
|
||||
expect(vm.popupVisible).toBe(false);
|
||||
});
|
||||
|
||||
it('prop: confirmText', () => {
|
||||
wrapper = shallowMount(DatePicker, {
|
||||
props: {
|
||||
open: true,
|
||||
confirm: true,
|
||||
confirmText: 'test',
|
||||
appendToBody: false,
|
||||
},
|
||||
});
|
||||
|
||||
const btn = wrapper.find('.mx-datepicker-btn-confirm');
|
||||
expect(btn.text()).toBe('test');
|
||||
});
|
||||
|
||||
it('prop: appendToBody', () => {
|
||||
wrapper = mount(DatePicker, {
|
||||
props: {
|
||||
open: true,
|
||||
appendToBody: true,
|
||||
},
|
||||
});
|
||||
|
||||
const popup = wrapper.findComponent(Popup);
|
||||
expect(popup.element.parentNode).toBe(document.body);
|
||||
});
|
||||
|
||||
it('feat: should emit clear event when click clear button', () => {
|
||||
wrapper = shallowMount(DatePicker, {
|
||||
props: {
|
||||
value: new Date(2019, 10, 9),
|
||||
},
|
||||
});
|
||||
const clearButton = wrapper.find('.mx-icon-clear');
|
||||
clearButton.trigger('mousedown');
|
||||
const emitted = wrapper.emitted();
|
||||
expect(emitted.clear).toBeTruthy();
|
||||
expect(emitted.input[0][0]).toBe(null);
|
||||
});
|
||||
|
||||
it('feat: should emit [null, null] when clear range', () => {
|
||||
wrapper = shallowMount(DatePicker, {
|
||||
props: {
|
||||
range: true,
|
||||
value: [new Date(2019, 10, 9), new Date(2019, 11, 9)],
|
||||
},
|
||||
});
|
||||
const clearButton = wrapper.find('.mx-icon-clear');
|
||||
clearButton.trigger('mousedown');
|
||||
const emitted = wrapper.emitted();
|
||||
expect(emitted.input[0][0]).toEqual([null, null]);
|
||||
});
|
||||
|
||||
it('feat: should close popup when click time in datetime mode', () => {
|
||||
wrapper = mount(DatePicker, {
|
||||
props: {
|
||||
type: 'datetime',
|
||||
timePickerOptions: {
|
||||
start: '00:00',
|
||||
step: '00:30',
|
||||
end: '23:30',
|
||||
},
|
||||
open: true,
|
||||
appendToBody: false,
|
||||
showTimePanel: true,
|
||||
},
|
||||
});
|
||||
const el = wrapper.find('.mx-time-option');
|
||||
el.trigger('click');
|
||||
expect(wrapper.emitted().close).toBeTruthy();
|
||||
});
|
||||
|
||||
// present the button submit form
|
||||
it('the type of all buttons should be button', () => {
|
||||
wrapper = mount(DatePicker, {
|
||||
props: {
|
||||
open: true,
|
||||
showTimePanel: true,
|
||||
appendToBody: false,
|
||||
},
|
||||
});
|
||||
const els = wrapper.findAll('button');
|
||||
els.forEach((v) => {
|
||||
expect(v.element.type).toBe('button');
|
||||
});
|
||||
});
|
||||
|
||||
it('should emit pick event on first click', () => {
|
||||
wrapper = mount(DatePicker, {
|
||||
props: {
|
||||
range: true,
|
||||
open: true,
|
||||
defaultValue: new Date(2019, 9, 1),
|
||||
appendToBody: false,
|
||||
},
|
||||
});
|
||||
const td = wrapper.find('.mx-table-date td');
|
||||
td.trigger('click');
|
||||
expect(wrapper.emitted().pick[0][0]).toEqual(new Date(2019, 8, 29));
|
||||
});
|
||||
|
||||
it('Ignore whitespace around separator on manual range input', async () => {
|
||||
const rangeSeparator = ' ~ ';
|
||||
const text = '2020-02-12';
|
||||
wrapper = mount(DatePicker, {
|
||||
props: {
|
||||
range: true,
|
||||
rangeSeparator: ' ~ ',
|
||||
valueType: 'format',
|
||||
},
|
||||
});
|
||||
const input = wrapper.find('input');
|
||||
|
||||
await input.setValue(`${text} ${rangeSeparator} ${text}`);
|
||||
await input.trigger('change');
|
||||
await input.setValue(`${text}${rangeSeparator.trim()}${text}`);
|
||||
await input.trigger('change');
|
||||
await wrapper.setProps({ rangeSeparator: ' - ' });
|
||||
await input.setValue(`${text} - ${text}`);
|
||||
await input.trigger('change');
|
||||
expect(wrapper.emitted().input).toEqual([[[text, text]], [[text, text]], [[text, text]]]);
|
||||
});
|
||||
|
||||
it('prop: multiple', () => {
|
||||
const value = [new Date(2020, 5, 6), new Date(2020, 6, 7)];
|
||||
wrapper = mount(DatePicker, {
|
||||
props: {
|
||||
multiple: true,
|
||||
open: true,
|
||||
appendToBody: false,
|
||||
value,
|
||||
},
|
||||
});
|
||||
wrapper.find('.mx-date-row .active').trigger('click');
|
||||
expect(wrapper.emitted().input[0][0]).toEqual(value.slice(0, 1));
|
||||
wrapper.find('[title="2020-07-15"]').trigger('click');
|
||||
expect(wrapper.emitted().input[1][0]).toEqual(value.concat(new Date(2020, 6, 15)));
|
||||
});
|
||||
|
||||
it('prop: invalid multiple', () => {
|
||||
wrapper = shallowMount(DatePicker, {
|
||||
props: {
|
||||
multiple: true,
|
||||
range: true,
|
||||
},
|
||||
});
|
||||
const { vm } = wrapper;
|
||||
expect(vm.validMultipleType).toBe(false);
|
||||
wrapper.setProps({
|
||||
range: false,
|
||||
type: 'datetime',
|
||||
});
|
||||
expect(vm.validMultipleType).toBe(false);
|
||||
});
|
||||
|
||||
it('If the value entered manually is in the disabled range should be invalid', () => {
|
||||
const someday = new Date(2020, 6, 1);
|
||||
wrapper = shallowMount(DatePicker, {
|
||||
format: 'YYYY-MM-DD',
|
||||
props: {
|
||||
disabledDate: (date) => {
|
||||
return date < someday;
|
||||
},
|
||||
},
|
||||
});
|
||||
const textInput = wrapper.find('input');
|
||||
textInput.setValue('2020-08-01');
|
||||
textInput.trigger('change');
|
||||
expect(wrapper.emitted().input[0][0]).toEqual(new Date(2020, 7, 1));
|
||||
textInput.setValue('2020-05-01');
|
||||
textInput.trigger('change');
|
||||
expect(wrapper.emitted().input[1]).toBe(undefined);
|
||||
expect(wrapper.emitted()['input-error'][0][0]).toBe('2020-05-01');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,49 @@
|
||||
import { mount } from '@vue/test-utils';
|
||||
import DatetimePanel from '../src/datetime/datetime-panel';
|
||||
|
||||
let wrapper;
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
describe('DatetimePanel', () => {
|
||||
it('feat: click date', async () => {
|
||||
wrapper = mount(DatetimePanel, {
|
||||
props: {
|
||||
type: 'datetime',
|
||||
defaultValue: new Date(2019, 9, 1, 12),
|
||||
},
|
||||
});
|
||||
const td = wrapper.find('.mx-table-date td:nth-child(4)');
|
||||
await td.trigger('click');
|
||||
expect(wrapper.emitted().select[0][0]).toEqual(new Date(2019, 9, 2, 12));
|
||||
let timeTitle = wrapper.find('.mx-time-header-title');
|
||||
expect(timeTitle.exists()).toBe(true);
|
||||
await timeTitle.trigger('click');
|
||||
timeTitle = wrapper.find('.mx-time-header-title');
|
||||
expect(timeTitle.exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('feat: disabled time', async () => {
|
||||
const disabledDate = (date) => date < new Date(2019, 9, 2);
|
||||
const disabledTime = (date) => date < new Date(2019, 9, 2, 12);
|
||||
wrapper = mount(DatetimePanel, {
|
||||
props: {
|
||||
defaultValue: new Date(2019, 9, 2, 10),
|
||||
disabledDate,
|
||||
disabledTime,
|
||||
},
|
||||
});
|
||||
const td = wrapper.find('.mx-table-date td:nth-child(4)');
|
||||
await td.trigger('click');
|
||||
expect(wrapper.emitted().select).toBeUndefined();
|
||||
const timeTitle = wrapper.find('.mx-time-header-title');
|
||||
expect(timeTitle.text()).toBe('2019-10-02');
|
||||
// set the defaultValue is not disabled
|
||||
const defaultValue = new Date(2019, 9, 2, 12);
|
||||
await wrapper.setProps({ defaultValue });
|
||||
await td.trigger('click');
|
||||
expect(wrapper.emitted().select[0][0]).toEqual(defaultValue);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,62 @@
|
||||
import { mount } from '@vue/test-utils';
|
||||
import DatetimeRange from '../src/datetime/datetime-range';
|
||||
|
||||
let wrapper;
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
describe('DatetimeRange', () => {
|
||||
it('feat: click dates', async () => {
|
||||
wrapper = mount(DatetimeRange, {
|
||||
props: {
|
||||
type: 'datetime',
|
||||
value: [new Date(2019, 9, 4, 18), new Date(2019, 9, 6, 12)],
|
||||
},
|
||||
});
|
||||
const td = wrapper.find('.mx-table-date td:nth-child(4)');
|
||||
const td2 = wrapper.find('.mx-table-date td:nth-child(5)');
|
||||
td.trigger('click');
|
||||
await td2.trigger('click');
|
||||
expect(wrapper.emitted().select[0][0]).toEqual([
|
||||
new Date(2019, 9, 2, 18),
|
||||
new Date(2019, 9, 3, 12),
|
||||
]);
|
||||
let timeTitle = wrapper.find('.mx-time-header-title');
|
||||
expect(timeTitle.exists()).toBe(true);
|
||||
await timeTitle.trigger('click');
|
||||
timeTitle = wrapper.find('.mx-time-header-title');
|
||||
expect(timeTitle.exists()).toBe(false);
|
||||
td.trigger('click');
|
||||
await td.trigger('click');
|
||||
expect(wrapper.emitted().select[1][0]).toEqual([
|
||||
new Date(2019, 9, 2, 18),
|
||||
new Date(2019, 9, 2, 18),
|
||||
]);
|
||||
});
|
||||
|
||||
it('feat: disabled time', async () => {
|
||||
const disabledDate = (date) => date < new Date(2019, 9, 2);
|
||||
const disabledTime = (date) => date < new Date(2019, 9, 2, 12);
|
||||
wrapper = mount(DatetimeRange, {
|
||||
sync: false,
|
||||
props: {
|
||||
defaultValue: [new Date(2019, 9, 1), new Date(2019, 9, 1, 12)],
|
||||
disabledDate,
|
||||
disabledTime,
|
||||
},
|
||||
});
|
||||
const td = wrapper.find('.mx-table-date td:nth-child(4)');
|
||||
td.trigger('click');
|
||||
await td.trigger('click');
|
||||
expect(wrapper.emitted().select).toBeUndefined();
|
||||
const timeTitle = wrapper.find('.mx-time-header-title');
|
||||
expect(timeTitle.text()).toBe('2019-10-02');
|
||||
const defaultValue = [new Date(2019, 9, 2, 12), new Date(2019, 9, 2, 12)];
|
||||
await wrapper.setProps({ defaultValue });
|
||||
await td.trigger('click');
|
||||
await td.trigger('click');
|
||||
expect(wrapper.emitted().select[0][0]).toEqual(defaultValue);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,65 @@
|
||||
import { mount } from '@vue/test-utils';
|
||||
import DatePicker from '../src/date-picker';
|
||||
import Calendar from '../src/calendar/calendar-panel';
|
||||
import '../src/locale/zh-cn';
|
||||
|
||||
let wrapper;
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
describe('Locale', () => {
|
||||
it('render the correct default locale', () => {
|
||||
wrapper = mount(DatePicker, {
|
||||
props: {
|
||||
value: new Date(2019, 9, 10),
|
||||
open: true,
|
||||
appendToBody: false,
|
||||
},
|
||||
});
|
||||
expect(wrapper.find('.mx-table-date th').text()).toBe('一');
|
||||
expect(wrapper.find('.mx-table-date td').element.title).toBe('2019-09-30');
|
||||
});
|
||||
|
||||
it('prop: lang - string', async () => {
|
||||
wrapper = mount(DatePicker, {
|
||||
props: {
|
||||
value: new Date(2019, 9, 10),
|
||||
open: true,
|
||||
lang: 'en',
|
||||
titleFormat: 'MMM DD, YYYY',
|
||||
appendToBody: false,
|
||||
},
|
||||
});
|
||||
expect(wrapper.find('.mx-table-date th').text()).toBe('Su');
|
||||
expect(wrapper.find('.mx-table-date .active').element.title).toBe('Oct 10, 2019');
|
||||
expect(wrapper.find('.mx-btn-current-month').text()).toBe('Oct');
|
||||
await wrapper.findComponent(Calendar).setData({ panel: 'month' });
|
||||
// expect(wrapper.vm.panel).toBe('month');
|
||||
expect(wrapper.find('.mx-table-month td').text()).toBe('Jan');
|
||||
wrapper.setProps({ lang: 'zh-cn' });
|
||||
await wrapper.findComponent(Calendar).setData({ panel: 'date' });
|
||||
expect(wrapper.find('.mx-table-date th').text()).toBe('一');
|
||||
expect(wrapper.find('.mx-table-date .active').element.title).toBe('10月 10, 2019');
|
||||
expect(wrapper.find('.mx-btn-current-month').text()).toBe('10月');
|
||||
await wrapper.findComponent(Calendar).setData({ panel: 'month' });
|
||||
expect(wrapper.find('.mx-table-month td').text()).toBe('1月');
|
||||
});
|
||||
|
||||
it('prop: lang - object', () => {
|
||||
wrapper = mount(DatePicker, {
|
||||
props: {
|
||||
open: true,
|
||||
appendToBody: false,
|
||||
lang: {
|
||||
formatLocale: {
|
||||
firstDayOfWeek: 2,
|
||||
},
|
||||
days: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(wrapper.find('.mx-table-date th').text()).toBe('周二');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
import { mount } from '@vue/test-utils';
|
||||
import TableDate from '../src/calendar/table-date';
|
||||
|
||||
let wrapper;
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
describe('TableDate', () => {
|
||||
it('corrent render', () => {
|
||||
wrapper = mount(TableDate, {
|
||||
props: {
|
||||
calendar: new Date(2019, 9, 1, 0, 0, 0),
|
||||
titleFormat: 'DD/MM/YYYY',
|
||||
},
|
||||
});
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
import { mount } from '@vue/test-utils';
|
||||
import TableMonth from '../src/calendar/table-month';
|
||||
|
||||
let wrapper;
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
describe('TableMonth', () => {
|
||||
it('correct render', () => {
|
||||
wrapper = mount(TableMonth, {
|
||||
props: {
|
||||
calendar: new Date(2019, 9, 1, 0, 0, 0),
|
||||
getCellClasses: (month) => {
|
||||
if (month === 9) {
|
||||
return 'active';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
import { mount } from '@vue/test-utils';
|
||||
import TableYear from '../src/calendar/table-year';
|
||||
|
||||
let wrapper;
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
describe('TableYear', () => {
|
||||
it('decade=2010', () => {
|
||||
wrapper = mount(TableYear, {
|
||||
props: {
|
||||
calendar: new Date(2019, 9, 1, 0, 0, 0),
|
||||
},
|
||||
});
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,113 @@
|
||||
import { mount } from '@vue/test-utils';
|
||||
import TimePanel from '../src/time/time-panel';
|
||||
import ListColumns from '../src/time/list-columns';
|
||||
|
||||
let wrapper;
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
describe('TimePanel', () => {
|
||||
it('render: correct classes of the columns', () => {
|
||||
wrapper = mount(TimePanel, {
|
||||
props: {
|
||||
value: new Date(2019, 9, 4, 12, 30, 30),
|
||||
disabledTime: (date) => date.getHours() < 10,
|
||||
},
|
||||
});
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('render: correct columns by format', () => {
|
||||
wrapper = mount(TimePanel, {
|
||||
props: {
|
||||
value: new Date(2019, 9, 4),
|
||||
format: 'hh:mm a',
|
||||
minuteStep: 30,
|
||||
hourOptions: Array.from({ length: 10 }).map((_, i) => i + 8),
|
||||
},
|
||||
});
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('render: correct classes of the fixed time list', () => {
|
||||
wrapper = mount(TimePanel, {
|
||||
props: {
|
||||
value: new Date(2019, 10, 9, 12, 30),
|
||||
disabledTime: (date) => date.getHours() < 10,
|
||||
timePickerOptions: {
|
||||
start: '08:30',
|
||||
step: '00:30',
|
||||
end: '18:30',
|
||||
},
|
||||
format: 'HH:mm',
|
||||
},
|
||||
});
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('render: correct 12hours in the fixed time list', () => {
|
||||
wrapper = mount(TimePanel, {
|
||||
props: {
|
||||
value: new Date(2019, 10, 9, 12, 30),
|
||||
timePickerOptions: {
|
||||
start: '08:30',
|
||||
step: '00:30',
|
||||
end: '18:30',
|
||||
},
|
||||
format: 'hh:mm A',
|
||||
},
|
||||
});
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('feat: emit select event when click', async () => {
|
||||
wrapper = mount(TimePanel, {
|
||||
props: {
|
||||
format: 'hh:mm:ss a',
|
||||
defaultValue: new Date(2019, 9, 10, 2),
|
||||
},
|
||||
});
|
||||
const hour = wrapper.find('[data-type=hour] li:nth-child(2)');
|
||||
hour.trigger('click');
|
||||
expect(wrapper.emitted().select[0][0]).toEqual(new Date(2019, 9, 10, 1));
|
||||
await wrapper.setProps({ value: new Date(2019, 9, 10, 1) });
|
||||
const minute = wrapper.find('[data-type=minute] li:nth-child(2)');
|
||||
minute.trigger('click');
|
||||
expect(wrapper.emitted().select[1][0]).toEqual(new Date(2019, 9, 10, 1, 1));
|
||||
await wrapper.setProps({ value: new Date(2019, 9, 10, 1, 1) });
|
||||
const second = wrapper.find('[data-type=second] li:nth-child(2)');
|
||||
second.trigger('click');
|
||||
expect(wrapper.emitted().select[2][0]).toEqual(new Date(2019, 9, 10, 1, 1, 1));
|
||||
await wrapper.setProps({ value: new Date(2019, 9, 10, 1, 1, 1) });
|
||||
const pm = wrapper.find('[data-type=ampm] li:nth-child(2)');
|
||||
pm.trigger('click');
|
||||
expect(wrapper.emitted().select[3][0]).toEqual(new Date(2019, 9, 10, 13, 1, 1));
|
||||
});
|
||||
|
||||
it('feat: disabledTime should not emit event', () => {
|
||||
wrapper = mount(TimePanel, {
|
||||
props: {
|
||||
value: new Date(2019, 9, 4, 12, 30, 30),
|
||||
disabledTime: (date) => date.getHours() < 10,
|
||||
},
|
||||
});
|
||||
const hour = wrapper.find('[data-type=hour] li:nth-child(2)');
|
||||
hour.trigger('click');
|
||||
expect(wrapper.emitted().select).toBeUndefined();
|
||||
});
|
||||
|
||||
it('fix: when the custom format pass into time panel', () => {
|
||||
wrapper = mount(TimePanel, {
|
||||
props: {
|
||||
value: new Date(),
|
||||
format: {},
|
||||
},
|
||||
});
|
||||
const cols = wrapper.findComponent(ListColumns);
|
||||
expect(cols.props('showHour')).toBe(true);
|
||||
expect(cols.props('showMinute')).toBe(true);
|
||||
expect(cols.props('showSecond')).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,47 @@
|
||||
import { mount } from '@vue/test-utils';
|
||||
import TimeRange from '../src/time/time-range';
|
||||
|
||||
let wrapper;
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
describe('TimeRange', () => {
|
||||
it('render: correct classes of the columns', () => {
|
||||
wrapper = mount(TimeRange, {
|
||||
props: {
|
||||
format: 'hh:mm a',
|
||||
minuteStep: 30,
|
||||
hourStep: 2,
|
||||
value: [new Date(2019, 9, 4, 8, 30, 0), new Date(2019, 9, 4, 18, 30, 0)],
|
||||
},
|
||||
});
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('feat: change the end time when start > end', () => {
|
||||
wrapper = mount(TimeRange, {
|
||||
props: {
|
||||
value: [new Date(2019, 9, 4, 8, 30, 0), new Date(2019, 9, 4, 18, 30, 0)],
|
||||
},
|
||||
});
|
||||
const hour = wrapper.find('[data-type=hour] li:nth-child(20)');
|
||||
hour.trigger('click');
|
||||
expect(wrapper.emitted().select[0][0]).toEqual([
|
||||
new Date(2019, 9, 4, 19, 30, 0),
|
||||
new Date(2019, 9, 4, 19, 30, 0),
|
||||
]);
|
||||
});
|
||||
|
||||
it('supports defaultValue is Array', () => {
|
||||
wrapper = mount(TimeRange, {
|
||||
props: {
|
||||
defaultValue: [new Date(2019, 9, 1, 10), new Date(2019, 11, 1, 12)],
|
||||
},
|
||||
});
|
||||
const actived = wrapper.findAll('.active');
|
||||
expect(actived[0].text()).toBe('10');
|
||||
expect(actived[3].text()).toBe('12');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
// need to compile node_modules (eg: vue-runtime-helps)
|
||||
module.exports = (api) => {
|
||||
api.cache(false);
|
||||
return {
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
modules: false,
|
||||
},
|
||||
],
|
||||
],
|
||||
plugins: ['@vue/babel-plugin-jsx', '@babel/plugin-transform-object-assign'],
|
||||
env: {
|
||||
test: {
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets: {
|
||||
node: 'current',
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
plugins: ['@vue/babel-plugin-jsx'],
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const libLocales = path.resolve(__dirname, '../../node_modules/date-format-parse/lib/locale');
|
||||
|
||||
const localLocalePath = path.resolve(__dirname, '../../src/locale');
|
||||
|
||||
const yearBeforeMonth = ['hu', 'ja', 'ko', 'lv', 'vi', 'zh-cn', 'zh-tw'];
|
||||
|
||||
const yearFormatMap = {
|
||||
'zh-cn': 'YYYY年',
|
||||
'zh-tw': 'YYYY年',
|
||||
};
|
||||
|
||||
const getTemplate = locale => {
|
||||
const formatLocale = locale.replace(/-(\w+)/, (m, p1) => p1.toLocaleUpperCase());
|
||||
const yearFormat = yearFormatMap[locale] || 'YYYY';
|
||||
|
||||
const template = `
|
||||
${locale === 'en' ? '' : "import DatePicker from 'vue2-datepicker';"}
|
||||
import ${formatLocale} from 'date-format-parse/lib/locale/${locale}';
|
||||
|
||||
const lang = {
|
||||
formatLocale: ${formatLocale},
|
||||
yearFormat: '${yearFormat}',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: ${yearBeforeMonth.indexOf(locale) === -1},
|
||||
};
|
||||
|
||||
${locale === 'en' ? '' : `DatePicker.locale('${locale}', lang);`}
|
||||
|
||||
export default lang;
|
||||
`;
|
||||
return template.trim();
|
||||
};
|
||||
|
||||
function generateLocales() {
|
||||
fs.readdirSync(libLocales).forEach(filename => {
|
||||
if (!/\.js$/.test(filename)) {
|
||||
return;
|
||||
}
|
||||
const name = filename.replace(/\.js$/, '');
|
||||
const data = getTemplate(name);
|
||||
fs.writeFile(path.join(localLocalePath, filename), data, err => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
generateLocales();
|
||||
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Check current branch
|
||||
if test "master" != "$(git symbolic-ref --short HEAD)"; then
|
||||
echo 'Not on `master` branch.' >&2;
|
||||
exit 128;
|
||||
fi
|
||||
|
||||
|
||||
# Check local working tree
|
||||
if test -n "$(git status --porcelain)"; then
|
||||
echo 'Unclean working tree. Commit or stash changes first.' >&2;
|
||||
exit 128;
|
||||
fi
|
||||
|
||||
# Check remote history
|
||||
if test "0" != "$(git rev-list --count --left-only @'{u}'...HEAD)"; then
|
||||
echo 'Remote history differ. Please pull changes.' >&2;
|
||||
exit 128;
|
||||
fi
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
if [[ -z $1 ]]; then
|
||||
echo "Enter new version: "
|
||||
read -r VERSION
|
||||
else
|
||||
VERSION=$1
|
||||
fi
|
||||
|
||||
read -p "Releasing $VERSION - are you sure? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]
|
||||
then
|
||||
echo "Releasing $VERSION ..."
|
||||
|
||||
# build
|
||||
VERSION=$VERSION npm run build
|
||||
|
||||
npm version $VERSION --message "$VERSION"
|
||||
|
||||
# publish
|
||||
git push
|
||||
git push origin refs/tags/v$VERSION
|
||||
|
||||
npm publish --tag next
|
||||
fi
|
||||
@@ -0,0 +1,45 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint',
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
jest: true,
|
||||
es6: true,
|
||||
},
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
node: {
|
||||
extensions: ['.js', '.jsx', '.vue'],
|
||||
},
|
||||
},
|
||||
'import/extensions': ['.js', '.jsx', '.vue'],
|
||||
},
|
||||
extends: ['airbnb-base', 'plugin:vue/recommended', 'prettier', 'prettier/vue'],
|
||||
|
||||
plugins: ['vue'],
|
||||
|
||||
rules: {
|
||||
// allow debugger during development
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
'no-console': ['error', { allow: ['warn', 'error'] }],
|
||||
'no-plusplus': 'off',
|
||||
'no-underscore-dangle': 'off',
|
||||
'no-param-reassign': 'off',
|
||||
'no-restricted-globals': 'off',
|
||||
'import/prefer-default-export': 'off',
|
||||
'import/no-unresolved': [2, { ignore: ['vue2-datepicker'] }],
|
||||
'import/no-extraneous-dependencies': 'off',
|
||||
'import/extensions': [
|
||||
'error',
|
||||
'always',
|
||||
{
|
||||
js: 'never',
|
||||
},
|
||||
],
|
||||
'vue/require-default-prop': 'off',
|
||||
'vue/require-prop-types': 'off',
|
||||
'vue/no-v-html': 'off',
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
*.local
|
||||
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Vite App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Generated
+2713
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "example",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build"
|
||||
},
|
||||
"dependencies": {
|
||||
"vue": "^3.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^1.0.0-rc.8",
|
||||
"@vue/compiler-sfc": "^3.0.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<div>
|
||||
<DatePicker v-model="value" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import 'vue2-datepicker/index.css';
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
DatePicker,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: null,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,8 @@
|
||||
#app {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
margin-top: 60px;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
import './index.css';
|
||||
|
||||
createApp(App).mount('#app');
|
||||
Generated
+13714
File diff suppressed because it is too large
Load Diff
+121
@@ -0,0 +1,121 @@
|
||||
{
|
||||
"name": "vue2-datepicker",
|
||||
"description": "Vue3 Datepicker Component",
|
||||
"main": "index.js",
|
||||
"module": "index.esm.js",
|
||||
"alias": {
|
||||
"vue2-datepicker": "./src/index.js"
|
||||
},
|
||||
"files": [
|
||||
"/locale",
|
||||
"/index.*",
|
||||
"/scss"
|
||||
],
|
||||
"version": "3.7.0",
|
||||
"scripts": {
|
||||
"dev": "cross-env NODE_ENV=development rollup -c -w",
|
||||
"build:index": "cross-env NODE_ENV=production rollup -c",
|
||||
"build:locale": "cross-env NODE_ENV=production rollup -c rollup.locale.config.js",
|
||||
"build:css": "sass --style=compressed --no-source-map src/style/index.scss index.css && postcss index.css --use autoprefixer -o index.css --no-map && cp -R src/style scss",
|
||||
"build": "npm run test && npm run clean && npm run build:index && npm run build:css && npm run build:locale",
|
||||
"clean": "rimraf scss locale index.*",
|
||||
"lint": "eslint src/**/*.{js,vue}",
|
||||
"lint:fix": "eslint src/**/*.{js,vue} --fix",
|
||||
"format": "prettier --write src/**/*",
|
||||
"test": "npm run lint && jest",
|
||||
"cov": "jest --coverage --coverageReporters=text-lcov | coveralls",
|
||||
"version": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md",
|
||||
"release": "bash build/git.sh && bash build/release.sh"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/mengxiong10/vue2-datepicker.git"
|
||||
},
|
||||
"keywords": [
|
||||
"vue",
|
||||
"calendar",
|
||||
"datepicker",
|
||||
"datetimepicker"
|
||||
],
|
||||
"author": "xiemengxiong",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/mengxiong10/vue2-datepicker/issues"
|
||||
},
|
||||
"homepage": "https://github.com/mengxiong10/vue2-datepicker#readme",
|
||||
"dependencies": {
|
||||
"date-format-parse": "^0.2.5",
|
||||
"vue": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/plugin-transform-object-assign": "^7.12.1",
|
||||
"@babel/preset-env": "^7.12.1",
|
||||
"@rollup/plugin-babel": "^5.2.1",
|
||||
"@rollup/plugin-commonjs": "^16.0.0",
|
||||
"@rollup/plugin-node-resolve": "^10.0.0",
|
||||
"@vue/babel-plugin-jsx": "^1.0.0-rc.3",
|
||||
"@vue/compiler-sfc": "^3.0.0",
|
||||
"@vue/test-utils": "^2.0.0-0",
|
||||
"autoprefixer": "^9.8.6",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-jest": "^26.6.3",
|
||||
"conventional-changelog-cli": "^2.1.1",
|
||||
"cross-env": "^7.0.2",
|
||||
"date-fns": "^2.16.1",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-config-airbnb-base": "^14.0.0",
|
||||
"eslint-config-prettier": "^6.1.0",
|
||||
"eslint-plugin-import": "^2.18.2",
|
||||
"eslint-plugin-prettier": "^3.1.3",
|
||||
"eslint-plugin-vue": "^7.0.0-0",
|
||||
"jest": "^24.9.0",
|
||||
"jest-serializer-vue": "^2.0.2",
|
||||
"postcss-cli": "^6.1.3",
|
||||
"prettier": "^1.19.1",
|
||||
"rollup": "^2.33.1",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"rollup-plugin-vue": "^6.0.0-beta.10",
|
||||
"sass": "^1.26.5",
|
||||
"typescript": "~3.9.3",
|
||||
"vue-jest": "^5.0.0-0"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
"js",
|
||||
"vue"
|
||||
],
|
||||
"transform": {
|
||||
"^.+\\.js$": "<rootDir>/node_modules/babel-jest",
|
||||
".*\\.(vue)$": "<rootDir>/node_modules/vue-jest"
|
||||
},
|
||||
"snapshotSerializers": [
|
||||
"jest-serializer-vue"
|
||||
],
|
||||
"moduleNameMapper": {
|
||||
"vue2-datepicker": "<rootDir>/src"
|
||||
},
|
||||
"coverageReporters": [
|
||||
"text",
|
||||
"text-summary"
|
||||
]
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged",
|
||||
"commit-msg": "commitlint -x @commitlint/config-conventional -E HUSKY_GIT_PARAMS"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"**/*.{js,vue}": [
|
||||
"eslint --fix",
|
||||
"prettier --write",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not ie < 10"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import babel from '@rollup/plugin-babel';
|
||||
import vue from 'rollup-plugin-vue';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
import pkg from './package.json';
|
||||
|
||||
const external = Object.keys(pkg.dependencies);
|
||||
|
||||
const input = 'src/index.js';
|
||||
|
||||
const plugins = [
|
||||
resolve({
|
||||
extensions: ['.js', '.jsx', '.es6', '.es', '.mjs', '.vue'],
|
||||
}),
|
||||
vue(),
|
||||
babel({
|
||||
babelHelpers: 'bundled',
|
||||
skipPreflightCheck: true,
|
||||
extensions: ['.js', '.jsx', '.es6', '.es', '.mjs', '.vue'],
|
||||
}),
|
||||
commonjs(),
|
||||
];
|
||||
|
||||
const esm = {
|
||||
external,
|
||||
input,
|
||||
output: [
|
||||
{
|
||||
file: pkg.module,
|
||||
format: 'esm',
|
||||
exports: 'named',
|
||||
},
|
||||
],
|
||||
plugins,
|
||||
};
|
||||
|
||||
const umd = {
|
||||
input,
|
||||
external: 'vue',
|
||||
output: [
|
||||
{
|
||||
file: pkg.main,
|
||||
format: 'umd',
|
||||
name: 'DatePicker',
|
||||
sourcemap: true,
|
||||
globals: {
|
||||
vue: 'Vue',
|
||||
},
|
||||
},
|
||||
{
|
||||
file: pkg.main.replace(/\.js$/, '.min.js'),
|
||||
format: 'umd',
|
||||
name: 'DatePicker',
|
||||
sourcemap: true,
|
||||
globals: {
|
||||
vue: 'Vue',
|
||||
},
|
||||
plugins: [
|
||||
terser({
|
||||
output: { comments: false },
|
||||
compress: {
|
||||
keep_infinity: true,
|
||||
pure_getters: true,
|
||||
},
|
||||
warnings: true,
|
||||
ecma: 5,
|
||||
toplevel: false,
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
plugins,
|
||||
};
|
||||
|
||||
export default [esm, umd];
|
||||
@@ -0,0 +1,56 @@
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import babel from '@rollup/plugin-babel';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const localePath = path.resolve(__dirname, 'src/locale');
|
||||
const fileList = fs.readdirSync(localePath);
|
||||
|
||||
const plugins = [
|
||||
resolve({
|
||||
extensions: ['.js', '.json'],
|
||||
}),
|
||||
babel({
|
||||
babelHelpers: 'bundled',
|
||||
exclude: 'node_modules/**',
|
||||
}),
|
||||
commonjs(),
|
||||
];
|
||||
|
||||
const umd = fileList.map((file) => {
|
||||
const input = path.join(localePath, file);
|
||||
const external = ['vue2-datepicker'];
|
||||
const name = path.basename(file, '.js').replace(/-(\w+)/g, (m, p1) => p1.toUpperCase());
|
||||
return {
|
||||
input,
|
||||
plugins,
|
||||
external,
|
||||
output: {
|
||||
file: `locale/${file}`,
|
||||
format: 'umd',
|
||||
name: `DatePicker.lang.${name}`,
|
||||
globals: {
|
||||
'vue2-datepicker': 'DatePicker',
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const esm = fileList.map((file) => {
|
||||
const input = path.join(localePath, file);
|
||||
const external = (id) => !id.startsWith('.') && !id.startsWith('/');
|
||||
return {
|
||||
input,
|
||||
plugins,
|
||||
external,
|
||||
output: {
|
||||
file: `locale/es/${file}`,
|
||||
format: 'esm',
|
||||
exports: 'named',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export default [...esm, ...umd];
|
||||
@@ -0,0 +1,260 @@
|
||||
import {
|
||||
getValidDate,
|
||||
isValidDate,
|
||||
createDate,
|
||||
setMonth,
|
||||
startOfYear,
|
||||
startOfMonth,
|
||||
startOfDay,
|
||||
} from '../util/date';
|
||||
import TableDate from './table-date';
|
||||
import TableMonth from './table-month';
|
||||
import TableYear from './table-year';
|
||||
|
||||
export default {
|
||||
name: 'CalendarPanel',
|
||||
inject: {
|
||||
prefixClass: {
|
||||
default: 'mx',
|
||||
},
|
||||
dispatchDatePicker: {
|
||||
default: () => () => {},
|
||||
},
|
||||
},
|
||||
emits: ['select', 'update:calendar'],
|
||||
props: {
|
||||
value: {},
|
||||
defaultValue: {
|
||||
default() {
|
||||
const date = new Date();
|
||||
date.setHours(0, 0, 0, 0);
|
||||
return date;
|
||||
},
|
||||
},
|
||||
defaultPanel: {
|
||||
type: String,
|
||||
},
|
||||
disabledDate: {
|
||||
type: Function,
|
||||
default: () => false,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'date',
|
||||
},
|
||||
getClasses: {
|
||||
type: Function,
|
||||
default: () => [],
|
||||
},
|
||||
showWeekNumber: {
|
||||
type: Boolean,
|
||||
default: undefined,
|
||||
},
|
||||
titleFormat: {
|
||||
type: String,
|
||||
default: 'YYYY-MM-DD',
|
||||
},
|
||||
calendar: Date,
|
||||
// update date when select year or month
|
||||
partialUpdate: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
const panels = ['date', 'month', 'year'];
|
||||
const index = Math.max(panels.indexOf(this.type), panels.indexOf(this.defaultPanel));
|
||||
const panel = index !== -1 ? panels[index] : 'date';
|
||||
return {
|
||||
panel,
|
||||
innerCalendar: new Date(),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
innerValue() {
|
||||
const value = Array.isArray(this.value) ? this.value : [this.value];
|
||||
const map = {
|
||||
year: startOfYear,
|
||||
month: startOfMonth,
|
||||
date: startOfDay,
|
||||
};
|
||||
const start = map[this.type] || map.date;
|
||||
return value.filter(isValidDate).map(v => start(v));
|
||||
},
|
||||
calendarYear() {
|
||||
return this.innerCalendar.getFullYear();
|
||||
},
|
||||
calendarMonth() {
|
||||
return this.innerCalendar.getMonth();
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
immediate: true,
|
||||
handler: 'initCalendar',
|
||||
},
|
||||
calendar: {
|
||||
handler: 'initCalendar',
|
||||
},
|
||||
defaultValue: {
|
||||
handler: 'initCalendar',
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
initCalendar() {
|
||||
let calendarDate = this.calendar;
|
||||
if (!isValidDate(calendarDate)) {
|
||||
const { length } = this.innerValue;
|
||||
calendarDate = getValidDate(length > 0 ? this.innerValue[length - 1] : this.defaultValue);
|
||||
}
|
||||
this.innerCalendar = startOfMonth(calendarDate);
|
||||
},
|
||||
isDisabled(date) {
|
||||
return this.disabledDate(new Date(date), this.innerValue);
|
||||
},
|
||||
emitDate(date, type) {
|
||||
if (!this.isDisabled(date)) {
|
||||
this.$emit('select', date, type, this.innerValue);
|
||||
// someone need get the first selected date to set range value. (#429)
|
||||
this.dispatchDatePicker('pick', date, type);
|
||||
}
|
||||
},
|
||||
handleCalendarChange(calendar, type) {
|
||||
const oldCalendar = new Date(this.innerCalendar);
|
||||
this.innerCalendar = calendar;
|
||||
this.$emit('update:calendar', calendar);
|
||||
this.dispatchDatePicker('calendar-change', calendar, oldCalendar, type);
|
||||
},
|
||||
handelPanelChange(panel) {
|
||||
this.panel = panel;
|
||||
},
|
||||
handleSelectYear(year) {
|
||||
if (this.type === 'year') {
|
||||
const date = this.getYearCellDate(year);
|
||||
this.emitDate(date, 'year');
|
||||
} else {
|
||||
this.handleCalendarChange(createDate(year, this.calendarMonth), 'year');
|
||||
this.handelPanelChange('month');
|
||||
if (this.partialUpdate && this.innerValue.length === 1) {
|
||||
const date = new Date(this.innerValue[0]);
|
||||
date.setFullYear(year);
|
||||
this.emitDate(date, 'year');
|
||||
}
|
||||
}
|
||||
},
|
||||
handleSelectMonth(month) {
|
||||
if (this.type === 'month') {
|
||||
const date = this.getMonthCellDate(month);
|
||||
this.emitDate(date, 'month');
|
||||
} else {
|
||||
this.handleCalendarChange(createDate(this.calendarYear, month), 'month');
|
||||
this.handelPanelChange('date');
|
||||
if (this.partialUpdate && this.innerValue.length === 1) {
|
||||
const date = new Date(this.innerValue[0]);
|
||||
date.setFullYear(this.calendarYear);
|
||||
this.emitDate(setMonth(date, month), 'month');
|
||||
}
|
||||
}
|
||||
},
|
||||
handleSelectDate(date) {
|
||||
this.emitDate(date, this.type === 'week' ? 'week' : 'date');
|
||||
},
|
||||
getMonthCellDate(month) {
|
||||
return createDate(this.calendarYear, month);
|
||||
},
|
||||
getYearCellDate(year) {
|
||||
return createDate(year, 0);
|
||||
},
|
||||
getDateClasses(cellDate) {
|
||||
const notCurrentMonth = cellDate.getMonth() !== this.calendarMonth;
|
||||
const classes = [];
|
||||
if (cellDate.getTime() === new Date().setHours(0, 0, 0, 0)) {
|
||||
classes.push('today');
|
||||
}
|
||||
if (notCurrentMonth) {
|
||||
classes.push('not-current-month');
|
||||
}
|
||||
const state = this.getStateClass(cellDate);
|
||||
if (!(state === 'active' && notCurrentMonth)) {
|
||||
classes.push(state);
|
||||
}
|
||||
return classes.concat(this.getClasses(cellDate, this.innerValue, classes.join(' ')));
|
||||
},
|
||||
getMonthClasses(month) {
|
||||
if (this.type !== 'month') {
|
||||
return this.calendarMonth === month ? 'active' : '';
|
||||
}
|
||||
const classes = [];
|
||||
const cellDate = this.getMonthCellDate(month);
|
||||
classes.push(this.getStateClass(cellDate));
|
||||
return classes.concat(this.getClasses(cellDate, this.innerValue, classes.join(' ')));
|
||||
},
|
||||
getYearClasses(year) {
|
||||
if (this.type !== 'year') {
|
||||
return this.calendarYear === year ? 'active' : '';
|
||||
}
|
||||
const classes = [];
|
||||
const cellDate = this.getYearCellDate(year);
|
||||
classes.push(this.getStateClass(cellDate));
|
||||
return classes.concat(this.getClasses(cellDate, this.innerValue, classes.join(' ')));
|
||||
},
|
||||
getStateClass(cellDate) {
|
||||
if (this.isDisabled(cellDate)) {
|
||||
return 'disabled';
|
||||
}
|
||||
if (this.innerValue.some(v => v.getTime() === cellDate.getTime())) {
|
||||
return 'active';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
getWeekState(row) {
|
||||
if (this.type !== 'week') return '';
|
||||
const start = row[0].getTime();
|
||||
const end = row[6].getTime();
|
||||
const active = this.innerValue.some(v => {
|
||||
const time = v.getTime();
|
||||
return time >= start && time <= end;
|
||||
});
|
||||
return active ? `${this.prefixClass}-active-week` : '';
|
||||
},
|
||||
},
|
||||
render() {
|
||||
const { panel, innerCalendar } = this;
|
||||
if (panel === 'year') {
|
||||
return (
|
||||
<TableYear
|
||||
calendar={innerCalendar}
|
||||
getCellClasses={this.getYearClasses}
|
||||
onSelect={this.handleSelectYear}
|
||||
onChangecalendar={this.handleCalendarChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (panel === 'month') {
|
||||
return (
|
||||
<TableMonth
|
||||
calendar={innerCalendar}
|
||||
getCellClasses={this.getMonthClasses}
|
||||
onSelect={this.handleSelectMonth}
|
||||
onChangepanel={this.handelPanelChange}
|
||||
onChangecalendar={this.handleCalendarChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<TableDate
|
||||
class={{ [`${this.prefixClass}-calendar-week-mode`]: this.type === 'week' }}
|
||||
calendar={innerCalendar}
|
||||
getCellClasses={this.getDateClasses}
|
||||
getRowClasses={this.getWeekState}
|
||||
titleFormat={this.titleFormat}
|
||||
showWeekNumber={
|
||||
typeof showWeekNumber === 'boolean' ? this.showWeekNumber : this.type === 'week'
|
||||
}
|
||||
onSelect={this.handleSelectDate}
|
||||
onChangepanel={this.handelPanelChange}
|
||||
onChangecalendar={this.handleCalendarChange}
|
||||
/>
|
||||
);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,134 @@
|
||||
import CalendarPanel from './calendar-panel';
|
||||
import { getValidDate, isValidDate, isValidRangeDate, startOfMonth } from '../util/date';
|
||||
|
||||
export default {
|
||||
name: 'CalendarRange',
|
||||
inject: {
|
||||
prefixClass: {
|
||||
default: 'mx',
|
||||
},
|
||||
},
|
||||
emits: ['select'],
|
||||
props: {
|
||||
...CalendarPanel.props,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
innerValue: [],
|
||||
calendars: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
// Minimum difference between start and end calendars
|
||||
calendarMinDiff() {
|
||||
const map = {
|
||||
date: 1, // type:date min 1 month
|
||||
month: 1 * 12, // type:month min 1 year
|
||||
year: 10 * 12, // type:year min 10 year
|
||||
};
|
||||
return map[this.type] || map.date;
|
||||
},
|
||||
calendarMaxDiff() {
|
||||
return Infinity;
|
||||
},
|
||||
defaultValues() {
|
||||
return Array.isArray(this.defaultValue)
|
||||
? this.defaultValue
|
||||
: [this.defaultValue, this.defaultValue];
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
immediate: true,
|
||||
handler() {
|
||||
this.innerValue = isValidRangeDate(this.value)
|
||||
? this.value
|
||||
: [new Date(NaN), new Date(NaN)];
|
||||
const calendars = this.innerValue.map((v, i) =>
|
||||
startOfMonth(getValidDate(v, this.defaultValues[i]))
|
||||
);
|
||||
this.updateCalendars(calendars);
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleSelect(date, type) {
|
||||
const [startValue, endValue] = this.innerValue;
|
||||
if (isValidDate(startValue) && !isValidDate(endValue)) {
|
||||
if (startValue.getTime() > date.getTime()) {
|
||||
this.innerValue = [date, startValue];
|
||||
} else {
|
||||
this.innerValue = [startValue, date];
|
||||
}
|
||||
this.emitDate(this.innerValue, type);
|
||||
} else {
|
||||
this.innerValue = [date, new Date(NaN)];
|
||||
}
|
||||
},
|
||||
emitDate(dates, type) {
|
||||
this.$emit('select', dates, type);
|
||||
},
|
||||
updateStartCalendar(value) {
|
||||
this.updateCalendars([value, this.calendars[1]], 1);
|
||||
},
|
||||
updateEndCalendar(value) {
|
||||
this.updateCalendars([this.calendars[0], value], 0);
|
||||
},
|
||||
updateCalendars(calendars, adjustIndex = 1) {
|
||||
const gap = this.getCalendarGap(calendars);
|
||||
if (gap) {
|
||||
const calendar = new Date(calendars[adjustIndex]);
|
||||
calendar.setMonth(calendar.getMonth() + (adjustIndex === 0 ? -gap : gap));
|
||||
calendars[adjustIndex] = calendar;
|
||||
}
|
||||
this.calendars = calendars;
|
||||
},
|
||||
getCalendarGap(calendars) {
|
||||
const [calendarLeft, calendarRight] = calendars;
|
||||
const yearDiff = calendarRight.getFullYear() - calendarLeft.getFullYear();
|
||||
const monthDiff = calendarRight.getMonth() - calendarLeft.getMonth();
|
||||
const diff = yearDiff * 12 + monthDiff;
|
||||
const min = this.calendarMinDiff;
|
||||
const max = this.calendarMaxDiff;
|
||||
if (diff < min) {
|
||||
return min - diff;
|
||||
}
|
||||
if (diff > max) {
|
||||
return max - diff;
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
getRangeClasses(cellDate, currentDates, classnames) {
|
||||
const classes = [].concat(this.getClasses(cellDate, currentDates, classnames));
|
||||
if (
|
||||
!/disabled|active|not-current-month/.test(classnames) &&
|
||||
currentDates.length === 2 &&
|
||||
cellDate.getTime() > currentDates[0].getTime() &&
|
||||
cellDate.getTime() < currentDates[1].getTime()
|
||||
) {
|
||||
classes.push('in-range');
|
||||
}
|
||||
return classes;
|
||||
},
|
||||
},
|
||||
render() {
|
||||
const calendarRange = this.calendars.map((calendar, index) => {
|
||||
const props = {
|
||||
...this.$props,
|
||||
calendar,
|
||||
value: this.innerValue,
|
||||
defaultValue: this.defaultValues[index],
|
||||
getClasses: this.getRangeClasses,
|
||||
// don't update when range is true
|
||||
partialUpdate: false,
|
||||
onSelect: this.handleSelect,
|
||||
'onUpdate:calendar': index === 0 ? this.updateStartCalendar : this.updateEndCalendar,
|
||||
};
|
||||
return <CalendarPanel {...props}></CalendarPanel>;
|
||||
});
|
||||
|
||||
const { prefixClass } = this;
|
||||
|
||||
return <div class={`${prefixClass}-range-wrapper`}>{calendarRange}</div>;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<button
|
||||
type="button"
|
||||
:class="`${prefixClass}-btn ${prefixClass}-btn-text ${prefixClass}-btn-icon-${type}`"
|
||||
>
|
||||
<i :class="`${prefixClass}-icon-${type}`"></i>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
inject: {
|
||||
prefixClass: {
|
||||
default: 'mx',
|
||||
},
|
||||
},
|
||||
props: {
|
||||
type: String,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,175 @@
|
||||
<template>
|
||||
<div :class="`${prefixClass}-calendar ${prefixClass}-calendar-panel-date`">
|
||||
<div :class="`${prefixClass}-calendar-header`">
|
||||
<icon-button type="double-left" @click="handleIconDoubleLeftClick"></icon-button>
|
||||
<icon-button type="left" @click="handleIconLeftClick"></icon-button>
|
||||
<icon-button type="double-right" @click="handleIconDoubleRightClick"></icon-button>
|
||||
<icon-button type="right" @click="handleIconRightClick"></icon-button>
|
||||
<span :class="`${prefixClass}-calendar-header-label`">
|
||||
<button
|
||||
v-for="item in yearMonth"
|
||||
:key="item.panel"
|
||||
type="button"
|
||||
:class="
|
||||
`${prefixClass}-btn ${prefixClass}-btn-text ${prefixClass}-btn-current-${item.panel}`
|
||||
"
|
||||
@click="handlePanelChange(item.panel)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<div :class="`${prefixClass}-calendar-content`">
|
||||
<table :class="`${prefixClass}-table ${prefixClass}-table-date`">
|
||||
<thead>
|
||||
<tr>
|
||||
<th v-if="showWeekNumber" :class="`${prefixClass}-week-number-header`"></th>
|
||||
<th v-for="day in days" :key="day">{{ day }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody @click="handleCellClick">
|
||||
<tr
|
||||
v-for="(row, i) in dates"
|
||||
:key="i"
|
||||
:class="[`${prefixClass}-date-row`, getRowClasses(row)]"
|
||||
>
|
||||
<td v-if="showWeekNumber" :class="`${prefixClass}-week-number`">
|
||||
{{ getWeekNumber(row[0]) }}
|
||||
</td>
|
||||
<td
|
||||
v-for="(cell, j) in row"
|
||||
:key="j"
|
||||
:data-date="cell.getTime()"
|
||||
class="cell"
|
||||
:class="getCellClasses(cell)"
|
||||
:title="getCellTitle(cell)"
|
||||
>
|
||||
<div>{{ cell.getDate() }}</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getWeek, format } from 'date-format-parse';
|
||||
import IconButton from './icon-button';
|
||||
import { chunk } from '../util/base';
|
||||
import { createDate, getCalendar } from '../util/date';
|
||||
import { getLocale } from '../locale';
|
||||
|
||||
export default {
|
||||
name: 'TableDate',
|
||||
components: { IconButton },
|
||||
inject: {
|
||||
getLocale: {
|
||||
default: () => getLocale,
|
||||
},
|
||||
getWeek: {
|
||||
default: () => getWeek,
|
||||
},
|
||||
prefixClass: {
|
||||
default: 'mx',
|
||||
},
|
||||
},
|
||||
props: {
|
||||
calendar: {
|
||||
type: Date,
|
||||
default: () => new Date(),
|
||||
},
|
||||
showWeekNumber: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
titleFormat: {
|
||||
type: String,
|
||||
default: 'YYYY-MM-DD',
|
||||
},
|
||||
getRowClasses: {
|
||||
type: Function,
|
||||
default: () => [],
|
||||
},
|
||||
getCellClasses: {
|
||||
type: Function,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
emits: ['select', 'changepanel', 'changecalendar'],
|
||||
computed: {
|
||||
firstDayOfWeek() {
|
||||
return this.getLocale().formatLocale.firstDayOfWeek || 0;
|
||||
},
|
||||
yearMonth() {
|
||||
const { yearFormat, monthBeforeYear, monthFormat = 'MMM' } = this.getLocale();
|
||||
const yearLabel = {
|
||||
panel: 'year',
|
||||
label: this.formatDate(this.calendar, yearFormat),
|
||||
};
|
||||
const monthLabel = {
|
||||
panel: 'month',
|
||||
label: this.formatDate(this.calendar, monthFormat),
|
||||
};
|
||||
return monthBeforeYear ? [monthLabel, yearLabel] : [yearLabel, monthLabel];
|
||||
},
|
||||
days() {
|
||||
const locale = this.getLocale();
|
||||
const days = locale.days || locale.formatLocale.weekdaysMin;
|
||||
return days.concat(days).slice(this.firstDayOfWeek, this.firstDayOfWeek + 7);
|
||||
},
|
||||
dates() {
|
||||
const year = this.calendar.getFullYear();
|
||||
const month = this.calendar.getMonth();
|
||||
const arr = getCalendar({
|
||||
firstDayOfWeek: this.firstDayOfWeek,
|
||||
year,
|
||||
month,
|
||||
});
|
||||
return chunk(arr, 7);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getNextCalendar(diffMonth) {
|
||||
const year = this.calendar.getFullYear();
|
||||
const month = this.calendar.getMonth();
|
||||
return createDate(year, month + diffMonth);
|
||||
},
|
||||
handleIconLeftClick() {
|
||||
this.$emit('changecalendar', this.getNextCalendar(-1), 'last-month');
|
||||
},
|
||||
handleIconRightClick() {
|
||||
this.$emit('changecalendar', this.getNextCalendar(1), 'next-month');
|
||||
},
|
||||
handleIconDoubleLeftClick() {
|
||||
this.$emit('changecalendar', this.getNextCalendar(-12), 'last-year');
|
||||
},
|
||||
handleIconDoubleRightClick() {
|
||||
this.$emit('changecalendar', this.getNextCalendar(12), 'next-year');
|
||||
},
|
||||
handlePanelChange(panel) {
|
||||
this.$emit('changepanel', panel);
|
||||
},
|
||||
handleCellClick(evt) {
|
||||
let { target } = evt;
|
||||
if (target.tagName === 'DIV') {
|
||||
target = target.parentNode;
|
||||
}
|
||||
const date = target.getAttribute('data-date');
|
||||
if (date) {
|
||||
this.$emit('select', new Date(parseInt(date, 10)));
|
||||
}
|
||||
},
|
||||
formatDate(date, fmt) {
|
||||
return format(date, fmt, { locale: this.getLocale().formatLocale });
|
||||
},
|
||||
getCellTitle(date) {
|
||||
const fmt = this.titleFormat;
|
||||
return this.formatDate(date, fmt);
|
||||
},
|
||||
getWeekNumber(date) {
|
||||
return this.getWeek(date, this.getLocale().formatLocale);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<div :class="`${prefixClass}-calendar ${prefixClass}-calendar-panel-month`">
|
||||
<div :class="`${prefixClass}-calendar-header`">
|
||||
<icon-button type="double-left" @click="handleIconDoubleLeftClick"></icon-button>
|
||||
<icon-button type="double-right" @click="handleIconDoubleRightClick"></icon-button>
|
||||
<span :class="`${prefixClass}-calendar-header-label`">
|
||||
<button
|
||||
type="button"
|
||||
:class="`${prefixClass}-btn ${prefixClass}-btn-text`"
|
||||
@click="handlePanelChange"
|
||||
>
|
||||
{{ calendarYear }}
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<div :class="`${prefixClass}-calendar-content`">
|
||||
<table :class="`${prefixClass}-table ${prefixClass}-table-month`" @click="handleClick">
|
||||
<tr v-for="(row, i) in months" :key="i">
|
||||
<td
|
||||
v-for="(cell, j) in row"
|
||||
:key="j"
|
||||
:data-month="cell.month"
|
||||
class="cell"
|
||||
:class="getCellClasses(cell.month)"
|
||||
>
|
||||
<div>{{ cell.text }}</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { chunk } from '../util/base';
|
||||
import IconButton from './icon-button';
|
||||
import { getLocale } from '../locale';
|
||||
import { createDate } from '../util/date';
|
||||
|
||||
export default {
|
||||
name: 'TableMonth',
|
||||
components: { IconButton },
|
||||
inject: {
|
||||
getLocale: {
|
||||
default: () => getLocale,
|
||||
},
|
||||
prefixClass: {
|
||||
default: 'mx',
|
||||
},
|
||||
},
|
||||
props: {
|
||||
calendar: {
|
||||
type: Date,
|
||||
default: () => new Date(),
|
||||
},
|
||||
getCellClasses: {
|
||||
type: Function,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
emits: ['select', 'changecalendar', 'changepanel'],
|
||||
computed: {
|
||||
calendarYear() {
|
||||
return this.calendar.getFullYear();
|
||||
},
|
||||
months() {
|
||||
const locale = this.getLocale();
|
||||
const monthsLocale = locale.months || locale.formatLocale.monthsShort;
|
||||
const months = monthsLocale.map((text, month) => {
|
||||
return { text, month };
|
||||
});
|
||||
return chunk(months, 3);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getNextCalendar(diffYear) {
|
||||
const year = this.calendar.getFullYear();
|
||||
const month = this.calendar.getMonth();
|
||||
return createDate(year + diffYear, month);
|
||||
},
|
||||
handleIconDoubleLeftClick() {
|
||||
this.$emit('changecalendar', this.getNextCalendar(-1), 'last-year');
|
||||
},
|
||||
handleIconDoubleRightClick() {
|
||||
this.$emit('changecalendar', this.getNextCalendar(1), 'next-year');
|
||||
},
|
||||
handlePanelChange() {
|
||||
this.$emit('changepanel', 'year');
|
||||
},
|
||||
handleClick(evt) {
|
||||
let { target } = evt;
|
||||
if (target.tagName === 'DIV') {
|
||||
target = target.parentNode;
|
||||
}
|
||||
const month = target.getAttribute('data-month');
|
||||
if (month) {
|
||||
this.$emit('select', parseInt(month, 10));
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<div :class="`${prefixClass}-calendar ${prefixClass}-calendar-panel-year`">
|
||||
<div :class="`${prefixClass}-calendar-header`">
|
||||
<icon-button type="double-left" @click="handleIconDoubleLeftClick"></icon-button>
|
||||
<icon-button type="double-right" @click="handleIconDoubleRightClick"></icon-button>
|
||||
<span :class="`${prefixClass}-calendar-header-label`">
|
||||
<span>{{ firstYear }}</span>
|
||||
<span :class="`${prefixClass}-calendar-decade-separator`"></span>
|
||||
<span>{{ lastYear }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div :class="`${prefixClass}-calendar-content`">
|
||||
<table :class="`${prefixClass}-table ${prefixClass}-table-year`" @click="handleClick">
|
||||
<tr v-for="(row, i) in years" :key="i">
|
||||
<td
|
||||
v-for="(cell, j) in row"
|
||||
:key="j"
|
||||
:data-year="cell"
|
||||
class="cell"
|
||||
:class="getCellClasses(cell)"
|
||||
>
|
||||
<div>{{ cell }}</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import IconButton from './icon-button';
|
||||
import { chunk } from '../util/base';
|
||||
import { createDate } from '../util/date';
|
||||
|
||||
export default {
|
||||
name: 'TableYear',
|
||||
components: { IconButton },
|
||||
inject: {
|
||||
prefixClass: {
|
||||
default: 'mx',
|
||||
},
|
||||
},
|
||||
props: {
|
||||
calendar: {
|
||||
type: Date,
|
||||
default: () => new Date(),
|
||||
},
|
||||
getCellClasses: {
|
||||
type: Function,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
emits: ['select', 'changecalendar'],
|
||||
computed: {
|
||||
years() {
|
||||
const firstYear = Math.floor(this.calendar.getFullYear() / 10) * 10;
|
||||
const years = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
years.push(firstYear + i);
|
||||
}
|
||||
return chunk(years, 2);
|
||||
},
|
||||
firstYear() {
|
||||
return this.years[0][0];
|
||||
},
|
||||
lastYear() {
|
||||
const last = arr => arr[arr.length - 1];
|
||||
return last(last(this.years));
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getNextCalendar(diffYear) {
|
||||
const year = this.calendar.getFullYear();
|
||||
const month = this.calendar.getMonth();
|
||||
return createDate(year + diffYear, month);
|
||||
},
|
||||
handleIconDoubleLeftClick() {
|
||||
this.$emit('changecalendar', this.getNextCalendar(-10), 'last-decade');
|
||||
},
|
||||
handleIconDoubleRightClick() {
|
||||
this.$emit('changecalendar', this.getNextCalendar(10), 'next-decade');
|
||||
},
|
||||
handleClick(evt) {
|
||||
let { target } = evt;
|
||||
if (target.tagName === 'DIV') {
|
||||
target = target.parentNode;
|
||||
}
|
||||
const year = target.getAttribute('data-year');
|
||||
if (year) {
|
||||
this.$emit('select', parseInt(year, 10));
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,573 @@
|
||||
import { parse, format, getWeek } from 'date-format-parse';
|
||||
import { isValidDate, isValidRangeDate, isValidDates } from './util/date';
|
||||
import { pick, isObject, mergeDeep } from './util/base';
|
||||
import { getLocale } from './locale';
|
||||
import Popup from './popup';
|
||||
import IconCalendar from './icon/icon-calendar';
|
||||
import IconClose from './icon/icon-close';
|
||||
import CalendarPanel from './calendar/calendar-panel';
|
||||
import CalendarRange from './calendar/calendar-range';
|
||||
import TimePanel from './time/time-panel';
|
||||
import TimeRange from './time/time-range';
|
||||
import DatetimePanel from './datetime/datetime-panel';
|
||||
import DatetimeRange from './datetime/datetime-range';
|
||||
|
||||
const componentMap = {
|
||||
default: CalendarPanel,
|
||||
time: TimePanel,
|
||||
datetime: DatetimePanel,
|
||||
};
|
||||
const componentRangeMap = {
|
||||
default: CalendarRange,
|
||||
time: TimeRange,
|
||||
datetime: DatetimeRange,
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'DatePicker',
|
||||
provide() {
|
||||
return {
|
||||
// make locale reactive
|
||||
getLocale: () => this.locale,
|
||||
getWeek: this.getWeek,
|
||||
prefixClass: this.prefixClass,
|
||||
dispatchDatePicker: this.$emit.bind(this),
|
||||
};
|
||||
},
|
||||
props: {
|
||||
...DatetimePanel.props,
|
||||
modelValue: {},
|
||||
valueType: {
|
||||
type: String,
|
||||
default: 'date', // date, format, timestamp, or token like 'YYYY-MM-DD'
|
||||
},
|
||||
type: {
|
||||
type: String, // ['date', 'datetime', 'time', 'year', 'month', 'week']
|
||||
default: 'date',
|
||||
},
|
||||
format: {
|
||||
type: String,
|
||||
},
|
||||
formatter: {
|
||||
type: Object,
|
||||
},
|
||||
range: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
rangeSeparator: {
|
||||
type: String,
|
||||
},
|
||||
lang: {
|
||||
type: [String, Object],
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
editable: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
prefixClass: {
|
||||
type: String,
|
||||
default: 'mx',
|
||||
},
|
||||
inputClass: {},
|
||||
inputAttr: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
appendToBody: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: undefined,
|
||||
},
|
||||
popupClass: {},
|
||||
popupStyle: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
inline: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
confirm: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: 'OK',
|
||||
},
|
||||
renderInputText: {
|
||||
type: Function,
|
||||
},
|
||||
shortcuts: {
|
||||
type: Array,
|
||||
validator(value) {
|
||||
return (
|
||||
Array.isArray(value) &&
|
||||
value.every(
|
||||
(v) => isObject(v) && typeof v.text === 'string' && typeof v.onClick === 'function'
|
||||
)
|
||||
);
|
||||
},
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// cache the innervalue, wait to confirm
|
||||
currentValue: null,
|
||||
userInput: null,
|
||||
defaultOpen: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
popupVisible() {
|
||||
return !this.disabled && (typeof this.open === 'boolean' ? this.open : this.defaultOpen);
|
||||
},
|
||||
innerRangeSeparator() {
|
||||
return this.rangeSeparator || (this.multiple ? ',' : ' ~ ');
|
||||
},
|
||||
innerFormat() {
|
||||
const map = {
|
||||
date: 'YYYY-MM-DD',
|
||||
datetime: 'YYYY-MM-DD HH:mm:ss',
|
||||
year: 'YYYY',
|
||||
month: 'YYYY-MM',
|
||||
time: 'HH:mm:ss',
|
||||
week: 'w',
|
||||
};
|
||||
return this.format || map[this.type] || map.date;
|
||||
},
|
||||
innerValue() {
|
||||
let value = this.modelValue !== undefined ? this.modelValue : this.value;
|
||||
if (this.validMultipleType) {
|
||||
value = Array.isArray(value) ? value : [];
|
||||
return value.map(this.value2date);
|
||||
}
|
||||
if (this.range) {
|
||||
value = Array.isArray(value) ? value.slice(0, 2) : [null, null];
|
||||
return value.map(this.value2date);
|
||||
}
|
||||
return this.value2date(value);
|
||||
},
|
||||
text() {
|
||||
if (this.userInput !== null) {
|
||||
return this.userInput;
|
||||
}
|
||||
if (typeof this.renderInputText === 'function') {
|
||||
return this.renderInputText(this.innerValue);
|
||||
}
|
||||
if (!this.isValidValue(this.innerValue)) {
|
||||
return '';
|
||||
}
|
||||
if (Array.isArray(this.innerValue)) {
|
||||
return this.innerValue.map((v) => this.formatDate(v)).join(this.innerRangeSeparator);
|
||||
}
|
||||
return this.formatDate(this.innerValue);
|
||||
},
|
||||
showClearIcon() {
|
||||
return !this.disabled && this.clearable && this.text;
|
||||
},
|
||||
locale() {
|
||||
if (isObject(this.lang)) {
|
||||
return mergeDeep(getLocale(), this.lang);
|
||||
}
|
||||
return getLocale(this.lang);
|
||||
},
|
||||
validMultipleType() {
|
||||
const types = ['date', 'month', 'year'];
|
||||
return this.multiple && !this.range && types.indexOf(this.type) !== -1;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
innerValue: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
this.currentValue = val;
|
||||
},
|
||||
},
|
||||
},
|
||||
created() {
|
||||
if (typeof this.format === 'object') {
|
||||
console.warn(
|
||||
"[vue2-datepicker]: The prop `format` don't support Object any more. You can use the new prop `formatter` to replace it"
|
||||
);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClickOutSide(evt) {
|
||||
const { target } = evt;
|
||||
if (!this.$el.contains(target)) {
|
||||
this.closePopup();
|
||||
}
|
||||
},
|
||||
getFormatter(key) {
|
||||
return (
|
||||
(isObject(this.formatter) && this.formatter[key]) ||
|
||||
(isObject(this.format) && this.format[key])
|
||||
);
|
||||
},
|
||||
getWeek(date, options) {
|
||||
if (typeof this.getFormatter('getWeek') === 'function') {
|
||||
return this.getFormatter('getWeek')(date, options);
|
||||
}
|
||||
return getWeek(date, options);
|
||||
},
|
||||
parseDate(value, fmt) {
|
||||
fmt = fmt || this.innerFormat;
|
||||
if (typeof this.getFormatter('parse') === 'function') {
|
||||
return this.getFormatter('parse')(value, fmt);
|
||||
}
|
||||
const backupDate = new Date();
|
||||
return parse(value, fmt, { locale: this.locale.formatLocale, backupDate });
|
||||
},
|
||||
formatDate(date, fmt) {
|
||||
fmt = fmt || this.innerFormat;
|
||||
if (typeof this.getFormatter('stringify') === 'function') {
|
||||
return this.getFormatter('stringify')(date, fmt);
|
||||
}
|
||||
return format(date, fmt, { locale: this.locale.formatLocale });
|
||||
},
|
||||
// transform the outer value to inner date
|
||||
value2date(value) {
|
||||
switch (this.valueType) {
|
||||
case 'date':
|
||||
return value instanceof Date ? new Date(value.getTime()) : new Date(NaN);
|
||||
case 'timestamp':
|
||||
return typeof value === 'number' ? new Date(value) : new Date(NaN);
|
||||
case 'format':
|
||||
return typeof value === 'string' ? this.parseDate(value) : new Date(NaN);
|
||||
default:
|
||||
return typeof value === 'string' ? this.parseDate(value, this.valueType) : new Date(NaN);
|
||||
}
|
||||
},
|
||||
// transform the inner date to outer value
|
||||
date2value(date) {
|
||||
if (!isValidDate(date)) return null;
|
||||
switch (this.valueType) {
|
||||
case 'date':
|
||||
return date;
|
||||
case 'timestamp':
|
||||
return date.getTime();
|
||||
case 'format':
|
||||
return this.formatDate(date);
|
||||
default:
|
||||
return this.formatDate(date, this.valueType);
|
||||
}
|
||||
},
|
||||
emitValue(date, type) {
|
||||
// fix IE11/10 trigger input event when input is focused. (placeholder !== '')
|
||||
this.userInput = null;
|
||||
const value = Array.isArray(date) ? date.map(this.date2value) : this.date2value(date);
|
||||
this.$emit('update:modelValue', value);
|
||||
this.$emit('input', value);
|
||||
this.$emit('change', value, type);
|
||||
this.afterEmitValue(type);
|
||||
return value;
|
||||
},
|
||||
afterEmitValue(type) {
|
||||
// this.type === 'datetime', click the time should close popup
|
||||
if (!type || type === this.type || type === 'time') {
|
||||
this.closePopup();
|
||||
}
|
||||
},
|
||||
isValidValue(value) {
|
||||
if (this.validMultipleType) {
|
||||
return isValidDates(value);
|
||||
}
|
||||
if (this.range) {
|
||||
return isValidRangeDate(value);
|
||||
}
|
||||
return isValidDate(value);
|
||||
},
|
||||
isValidValueAndNotDisabled(value) {
|
||||
if (!this.isValidValue(value)) {
|
||||
return false;
|
||||
}
|
||||
const disabledDate =
|
||||
typeof this.disabledDate === 'function' ? this.disabledDate : () => false;
|
||||
const disabledTime =
|
||||
typeof this.disabledTime === 'function' ? this.disabledTime : () => false;
|
||||
if (!Array.isArray(value)) {
|
||||
value = [value];
|
||||
}
|
||||
return value.every((v) => !disabledDate(v) && !disabledTime(v));
|
||||
},
|
||||
handleMultipleDates(date, dates) {
|
||||
if (this.validMultipleType && dates) {
|
||||
const nextDates = dates.filter((v) => v.getTime() !== date.getTime());
|
||||
if (nextDates.length === dates.length) {
|
||||
nextDates.push(date);
|
||||
}
|
||||
return nextDates;
|
||||
}
|
||||
return date;
|
||||
},
|
||||
handleSelectDate(val, type, dates) {
|
||||
val = this.handleMultipleDates(val, dates);
|
||||
if (this.confirm) {
|
||||
this.currentValue = val;
|
||||
} else {
|
||||
this.emitValue(val, this.validMultipleType ? `multiple-${type}` : type);
|
||||
}
|
||||
},
|
||||
handleClear(evt) {
|
||||
evt.stopPropagation();
|
||||
this.emitValue(this.range ? [null, null] : null);
|
||||
this.$emit('clear');
|
||||
},
|
||||
handleConfirmDate() {
|
||||
const value = this.emitValue(this.currentValue);
|
||||
this.$emit('confirm', value);
|
||||
},
|
||||
handleSelectShortcut(evt) {
|
||||
const index = evt.currentTarget.getAttribute('data-index');
|
||||
const item = this.shortcuts[parseInt(index, 10)];
|
||||
if (isObject(item) && typeof item.onClick === 'function') {
|
||||
const date = item.onClick(this);
|
||||
if (date) {
|
||||
this.emitValue(date);
|
||||
}
|
||||
}
|
||||
},
|
||||
openPopup(evt) {
|
||||
if (this.popupVisible) return;
|
||||
this.defaultOpen = true;
|
||||
this.$emit('open', evt);
|
||||
this.$emit('update:open', true);
|
||||
},
|
||||
closePopup() {
|
||||
if (!this.popupVisible) return;
|
||||
this.defaultOpen = false;
|
||||
this.$emit('close');
|
||||
this.$emit('update:open', false);
|
||||
},
|
||||
blur() {
|
||||
// when use slot input
|
||||
if (this.$refs.input) {
|
||||
this.$refs.input.blur();
|
||||
}
|
||||
},
|
||||
focus() {
|
||||
if (this.$refs.input) {
|
||||
this.$refs.input.focus();
|
||||
}
|
||||
},
|
||||
handleInputChange() {
|
||||
if (!this.editable || this.userInput === null) return;
|
||||
const text = this.userInput.trim();
|
||||
this.userInput = null;
|
||||
if (text === '') {
|
||||
this.handleClear();
|
||||
return;
|
||||
}
|
||||
let date;
|
||||
if (this.validMultipleType) {
|
||||
date = text.split(this.innerRangeSeparator).map((v) => this.parseDate(v.trim()));
|
||||
} else if (this.range) {
|
||||
let arr = text.split(this.innerRangeSeparator);
|
||||
if (arr.length !== 2) {
|
||||
// Maybe the separator during the day is the same as the separator for the date
|
||||
// eg: 2019-10-09-2020-01-02
|
||||
arr = text.split(this.innerRangeSeparator.trim());
|
||||
}
|
||||
date = arr.map((v) => this.parseDate(v.trim()));
|
||||
} else {
|
||||
date = this.parseDate(text);
|
||||
}
|
||||
if (this.isValidValueAndNotDisabled(date)) {
|
||||
this.emitValue(date);
|
||||
this.blur();
|
||||
} else {
|
||||
this.$emit('input-error', text);
|
||||
}
|
||||
},
|
||||
handleInputInput(evt) {
|
||||
this.userInput = evt.target.value;
|
||||
},
|
||||
handleInputKeydown(evt) {
|
||||
const { keyCode } = evt;
|
||||
// Tab 9 or Enter 13
|
||||
if (keyCode === 9) {
|
||||
this.closePopup();
|
||||
} else if (keyCode === 13) {
|
||||
this.handleInputChange();
|
||||
}
|
||||
},
|
||||
handleInputBlur(evt) {
|
||||
// tab close
|
||||
this.$emit('blur', evt);
|
||||
},
|
||||
handleInputFocus(evt) {
|
||||
this.openPopup(evt);
|
||||
this.$emit('focus', evt);
|
||||
},
|
||||
hasSlot(name) {
|
||||
return this.$slots[name];
|
||||
},
|
||||
renderSlot(name, fallback, props) {
|
||||
const slotFn = this.$slots[name];
|
||||
return slotFn ? slotFn(props) : fallback;
|
||||
},
|
||||
renderInput() {
|
||||
const { prefixClass } = this;
|
||||
const props = {
|
||||
name: 'date',
|
||||
type: 'text',
|
||||
autocomplete: 'off',
|
||||
value: this.text,
|
||||
class: this.inputClass || `${this.prefixClass}-input`,
|
||||
readonly: !this.editable,
|
||||
disabled: this.disabled,
|
||||
placeholder: this.placeholder,
|
||||
...this.inputAttr,
|
||||
onKeydown: this.handleInputKeydown,
|
||||
onFocus: this.handleInputFocus,
|
||||
onBlur: this.handleInputBlur,
|
||||
onInput: this.handleInputInput,
|
||||
onChange: this.handleInputChange,
|
||||
};
|
||||
const input = this.renderSlot('input', <input {...props} ref="input" />, props);
|
||||
return (
|
||||
<div class={`${prefixClass}-input-wrapper`} onMousedown={this.openPopup}>
|
||||
{input}
|
||||
{this.showClearIcon ? (
|
||||
<i class={`${prefixClass}-icon-clear`} onMousedown={this.handleClear}>
|
||||
{this.renderSlot('icon-clear', <IconClose />)}
|
||||
</i>
|
||||
) : null}
|
||||
<i class={`${prefixClass}-icon-calendar`}>
|
||||
{this.renderSlot('icon-calendar', <IconCalendar />)}
|
||||
</i>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
renderContent() {
|
||||
const map = this.range ? componentRangeMap : componentMap;
|
||||
const Component = map[this.type] || map.default;
|
||||
const props = {
|
||||
...pick(this.$props, Object.keys(Component.props)),
|
||||
value: this.currentValue,
|
||||
};
|
||||
const content = <Component {...props} onSelect={this.handleSelectDate} ref="picker" />;
|
||||
return (
|
||||
<div class={`${this.prefixClass}-datepicker-body`}>
|
||||
{this.renderSlot('content', content, {
|
||||
value: this.currentValue,
|
||||
emit: this.handleSelectDate,
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
renderSidebar() {
|
||||
const { prefixClass } = this;
|
||||
return (
|
||||
<div class={`${prefixClass}-datepicker-sidebar`}>
|
||||
{this.renderSlot('sidebar', null, {
|
||||
value: this.currentValue,
|
||||
emit: this.handleSelectDate,
|
||||
})}
|
||||
{this.shortcuts.map((v, i) => (
|
||||
<button
|
||||
key={i}
|
||||
data-index={i}
|
||||
type="button"
|
||||
class={`${prefixClass}-btn ${prefixClass}-btn-text ${prefixClass}-btn-shortcut`}
|
||||
onClick={this.handleSelectShortcut}>
|
||||
{v.text}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
renderHeader() {
|
||||
return (
|
||||
<div class={`${this.prefixClass}-datepicker-header`}>
|
||||
{this.renderSlot('header', null, {
|
||||
value: this.currentValue,
|
||||
emit: this.handleSelectDate,
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
renderFooter() {
|
||||
const { prefixClass } = this;
|
||||
return (
|
||||
<div class={`${prefixClass}-datepicker-footer`}>
|
||||
{this.renderSlot('footer', null, {
|
||||
value: this.currentValue,
|
||||
emit: this.handleSelectDate,
|
||||
})}
|
||||
{this.confirm ? (
|
||||
<button
|
||||
type="button"
|
||||
class={`${prefixClass}-btn ${prefixClass}-datepicker-btn-confirm`}
|
||||
onClick={this.handleConfirmDate}>
|
||||
{this.confirmText}
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
render() {
|
||||
const { prefixClass, inline, disabled } = this;
|
||||
const sidedar = this.hasSlot('sidebar') || this.shortcuts.length ? this.renderSidebar() : null;
|
||||
const content = (
|
||||
<div class={`${prefixClass}-datepicker-content`}>
|
||||
{this.hasSlot('header') ? this.renderHeader() : null}
|
||||
{this.renderContent()}
|
||||
{this.hasSlot('footer') || this.confirm ? this.renderFooter() : null}
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div
|
||||
class={{
|
||||
[`${prefixClass}-datepicker`]: true,
|
||||
[`${prefixClass}-datepicker-range`]: this.range,
|
||||
[`${prefixClass}-datepicker-inline`]: inline,
|
||||
disabled,
|
||||
}}>
|
||||
{!inline ? this.renderInput() : null}
|
||||
{!inline ? (
|
||||
<Popup
|
||||
ref="popup"
|
||||
class={this.popupClass}
|
||||
style={this.popupStyle}
|
||||
visible={this.popupVisible}
|
||||
appendToBody={this.appendToBody}
|
||||
onClickoutside={this.handleClickOutSide}>
|
||||
{sidedar}
|
||||
{content}
|
||||
</Popup>
|
||||
) : (
|
||||
<div class={`${prefixClass}-datepicker-main`}>
|
||||
{sidedar}
|
||||
{content}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,89 @@
|
||||
import CalendarPanel from '../calendar/calendar-panel';
|
||||
import TimePanel from '../time/time-panel';
|
||||
import { assignTime, getValidDate } from '../util/date';
|
||||
import { pick } from '../util/base';
|
||||
|
||||
export default {
|
||||
name: 'DatetimePanel',
|
||||
inject: {
|
||||
prefixClass: {
|
||||
default: 'mx',
|
||||
},
|
||||
},
|
||||
emits: ['select'],
|
||||
props: {
|
||||
...CalendarPanel.props,
|
||||
...TimePanel.props,
|
||||
showTimePanel: {
|
||||
type: Boolean,
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
defaultTimeVisible: false,
|
||||
currentValue: this.value,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
timeVisible() {
|
||||
return typeof this.showTimePanel === 'boolean' ? this.showTimePanel : this.defaultTimeVisible;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
this.currentValue = val;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
closeTimePanel() {
|
||||
this.defaultTimeVisible = false;
|
||||
},
|
||||
openTimePanel() {
|
||||
this.defaultTimeVisible = true;
|
||||
},
|
||||
emitDate(date, type) {
|
||||
this.$emit('select', date, type);
|
||||
},
|
||||
handleSelect(date, type) {
|
||||
if (type === 'date') {
|
||||
this.openTimePanel();
|
||||
}
|
||||
let datetime = assignTime(date, getValidDate(this.value, this.defaultValue));
|
||||
if (this.disabledTime(new Date(datetime))) {
|
||||
// set the time of defalutValue;
|
||||
datetime = assignTime(date, this.defaultValue);
|
||||
if (this.disabledTime(new Date(datetime))) {
|
||||
// if disabled don't emit date
|
||||
this.currentValue = datetime;
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.emitDate(datetime, type);
|
||||
},
|
||||
},
|
||||
render() {
|
||||
const calendarProps = {
|
||||
...pick(this.$props, Object.keys(CalendarPanel.props)),
|
||||
type: 'date',
|
||||
value: this.currentValue,
|
||||
onSelect: this.handleSelect,
|
||||
};
|
||||
const timeProps = {
|
||||
...pick(this.$props, Object.keys(TimePanel.props)),
|
||||
showTimeHeader: true,
|
||||
value: this.currentValue,
|
||||
onSelect: this.emitDate,
|
||||
onClicktitle: this.closeTimePanel,
|
||||
};
|
||||
|
||||
const { prefixClass } = this;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<CalendarPanel {...calendarProps} />
|
||||
{this.timeVisible && <TimePanel class={`${prefixClass}-calendar-time`} {...timeProps} />}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,95 @@
|
||||
import CalendarRange from '../calendar/calendar-range';
|
||||
import TimeRange from '../time/time-range';
|
||||
import { pick } from '../util/base';
|
||||
import { isValidRangeDate, assignTime } from '../util/date';
|
||||
|
||||
export default {
|
||||
name: 'DatetimeRange',
|
||||
inject: {
|
||||
prefixClass: {
|
||||
default: 'mx',
|
||||
},
|
||||
},
|
||||
props: {
|
||||
...CalendarRange.props,
|
||||
...TimeRange.props,
|
||||
showTimePanel: {
|
||||
type: Boolean,
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
defaultTimeVisible: false,
|
||||
currentValue: this.value,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
timeVisible() {
|
||||
return typeof this.showTimePanel === 'boolean' ? this.showTimePanel : this.defaultTimeVisible;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
this.currentValue = val;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
closeTimePanel() {
|
||||
this.defaultTimeVisible = false;
|
||||
},
|
||||
openTimePanel() {
|
||||
this.defaultTimeVisible = true;
|
||||
},
|
||||
emitDate(dates, type) {
|
||||
this.$emit('select', dates, type);
|
||||
},
|
||||
handleSelect(dates, type) {
|
||||
if (type === 'date') {
|
||||
this.openTimePanel();
|
||||
}
|
||||
const defaultValues = Array.isArray(this.defaultValue)
|
||||
? this.defaultValue
|
||||
: [this.defaultValue, this.defaultValue];
|
||||
let datetimes = dates.map((date, i) => {
|
||||
const time = isValidRangeDate(this.value) ? this.value[i] : defaultValues[i];
|
||||
return assignTime(date, time);
|
||||
});
|
||||
if (datetimes[1].getTime() < datetimes[0].getTime()) {
|
||||
datetimes = [datetimes[0], datetimes[0]];
|
||||
}
|
||||
if (datetimes.some(this.disabledTime)) {
|
||||
datetimes = dates.map((date, i) => assignTime(date, defaultValues[i]));
|
||||
if (datetimes.some(this.disabledTime)) {
|
||||
this.currentValue = datetimes;
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.emitDate(datetimes, type);
|
||||
},
|
||||
},
|
||||
render() {
|
||||
const calendarProps = {
|
||||
...pick(this.$props, Object.keys(CalendarRange.props)),
|
||||
type: 'date',
|
||||
value: this.currentValue,
|
||||
onSelect: this.handleSelect,
|
||||
};
|
||||
const timeProps = {
|
||||
...pick(this.$props, Object.keys(TimeRange.props)),
|
||||
value: this.currentValue,
|
||||
showTimeHeader: true,
|
||||
onSelect: this.emitDate,
|
||||
onClicktitle: this.closeTimePanel,
|
||||
};
|
||||
|
||||
const { prefixClass } = this;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<CalendarRange {...calendarProps} />
|
||||
{this.timeVisible && <TimeRange class={`${prefixClass}-calendar-time`} {...timeProps} />}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">
|
||||
<path
|
||||
d="M940.218182 107.054545h-209.454546V46.545455h-65.163636v60.50909H363.054545V46.545455H297.890909v60.50909H83.781818c-18.618182 0-32.581818 13.963636-32.581818 32.581819v805.236363c0 18.618182 13.963636 32.581818 32.581818 32.581818h861.090909c18.618182 0 32.581818-13.963636 32.581818-32.581818V139.636364c-4.654545-18.618182-18.618182-32.581818-37.236363-32.581819zM297.890909 172.218182V232.727273h65.163636V172.218182h307.2V232.727273h65.163637V172.218182h176.872727v204.8H116.363636V172.218182h181.527273zM116.363636 912.290909V442.181818h795.927273v470.109091H116.363636z"
|
||||
></path>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">
|
||||
<path
|
||||
d="M810.005333 274.005333l-237.994667 237.994667 237.994667 237.994667-60.010667 60.010667-237.994667-237.994667-237.994667 237.994667-60.010667-60.010667 237.994667-237.994667-237.994667-237.994667 60.010667-60.010667 237.994667 237.994667 237.994667-237.994667z"
|
||||
></path>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,26 @@
|
||||
/* istanbul ignore file */
|
||||
import DatePicker from './date-picker';
|
||||
import CalendarPanel from './calendar/calendar-panel';
|
||||
import CalendarRange from './calendar/calendar-range';
|
||||
import TimePanel from './time/time-panel';
|
||||
import TimeRange from './time/time-range';
|
||||
import DatetimePanel from './datetime/datetime-panel';
|
||||
import DatetimeRange from './datetime/datetime-range';
|
||||
import { locale } from './locale';
|
||||
|
||||
DatePicker.locale = locale;
|
||||
|
||||
DatePicker.install = function install(app) {
|
||||
app.component(DatePicker.name, DatePicker);
|
||||
};
|
||||
|
||||
Object.assign(DatePicker, {
|
||||
CalendarPanel,
|
||||
CalendarRange,
|
||||
TimePanel,
|
||||
TimeRange,
|
||||
DatetimePanel,
|
||||
DatetimeRange,
|
||||
});
|
||||
|
||||
export default DatePicker;
|
||||
@@ -0,0 +1,29 @@
|
||||
import enUS from './locale/en';
|
||||
|
||||
let defaultLocale = 'en';
|
||||
const locales = {};
|
||||
locales[defaultLocale] = enUS;
|
||||
|
||||
export function locale(name, object, isLocal) {
|
||||
if (typeof name !== 'string') return locales[defaultLocale];
|
||||
let l = defaultLocale;
|
||||
if (locales[name]) {
|
||||
l = name;
|
||||
}
|
||||
if (object) {
|
||||
locales[name] = object;
|
||||
l = name;
|
||||
}
|
||||
if (!isLocal) {
|
||||
defaultLocale = l;
|
||||
}
|
||||
return locales[name] || locales[defaultLocale];
|
||||
}
|
||||
|
||||
/**
|
||||
* get locale object
|
||||
* @param {string} name lang
|
||||
*/
|
||||
export function getLocale(name) {
|
||||
return locale(name, null, true);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import af from 'date-format-parse/lib/locale/af';
|
||||
|
||||
const lang = {
|
||||
formatLocale: af,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('af', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import arDZ from 'date-format-parse/lib/locale/ar-dz';
|
||||
|
||||
const lang = {
|
||||
formatLocale: arDZ,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('ar-dz', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import arSA from 'date-format-parse/lib/locale/ar-sa';
|
||||
|
||||
const lang = {
|
||||
formatLocale: arSA,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('ar-sa', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import ar from 'date-format-parse/lib/locale/ar';
|
||||
|
||||
const lang = {
|
||||
formatLocale: ar,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('ar', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import az from 'date-format-parse/lib/locale/az';
|
||||
|
||||
const lang = {
|
||||
formatLocale: az,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('az', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import be from 'date-format-parse/lib/locale/be';
|
||||
|
||||
const lang = {
|
||||
formatLocale: be,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('be', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import bg from 'date-format-parse/lib/locale/bg';
|
||||
|
||||
const lang = {
|
||||
formatLocale: bg,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('bg', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import bm from 'date-format-parse/lib/locale/bm';
|
||||
|
||||
const lang = {
|
||||
formatLocale: bm,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('bm', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import bn from 'date-format-parse/lib/locale/bn';
|
||||
|
||||
const lang = {
|
||||
formatLocale: bn,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('bn', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import ca from 'date-format-parse/lib/locale/ca';
|
||||
|
||||
const lang = {
|
||||
formatLocale: ca,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('ca', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import cs from 'date-format-parse/lib/locale/cs';
|
||||
|
||||
const lang = {
|
||||
formatLocale: cs,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('cs', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import cy from 'date-format-parse/lib/locale/cy';
|
||||
|
||||
const lang = {
|
||||
formatLocale: cy,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('cy', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import da from 'date-format-parse/lib/locale/da';
|
||||
|
||||
const lang = {
|
||||
formatLocale: da,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('da', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import de from 'date-format-parse/lib/locale/de';
|
||||
|
||||
const lang = {
|
||||
formatLocale: de,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('de', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import el from 'date-format-parse/lib/locale/el';
|
||||
|
||||
const lang = {
|
||||
formatLocale: el,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('el', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,10 @@
|
||||
import en from 'date-format-parse/lib/locale/en';
|
||||
|
||||
const lang = {
|
||||
formatLocale: en,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import eo from 'date-format-parse/lib/locale/eo';
|
||||
|
||||
const lang = {
|
||||
formatLocale: eo,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('eo', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import es from 'date-format-parse/lib/locale/es';
|
||||
|
||||
const lang = {
|
||||
formatLocale: es,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('es', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import et from 'date-format-parse/lib/locale/et';
|
||||
|
||||
const lang = {
|
||||
formatLocale: et,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('et', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import fi from 'date-format-parse/lib/locale/fi';
|
||||
|
||||
const lang = {
|
||||
formatLocale: fi,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('fi', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import fr from 'date-format-parse/lib/locale/fr';
|
||||
|
||||
const lang = {
|
||||
formatLocale: fr,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('fr', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import gl from 'date-format-parse/lib/locale/gl';
|
||||
|
||||
const lang = {
|
||||
formatLocale: gl,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('gl', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import gu from 'date-format-parse/lib/locale/gu';
|
||||
|
||||
const lang = {
|
||||
formatLocale: gu,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('gu', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import he from 'date-format-parse/lib/locale/he';
|
||||
|
||||
const lang = {
|
||||
formatLocale: he,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('he', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import hi from 'date-format-parse/lib/locale/hi';
|
||||
|
||||
const lang = {
|
||||
formatLocale: hi,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('hi', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import hr from 'date-format-parse/lib/locale/hr';
|
||||
|
||||
const lang = {
|
||||
formatLocale: hr,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('hr', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import hu from 'date-format-parse/lib/locale/hu';
|
||||
|
||||
const lang = {
|
||||
formatLocale: hu,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: false,
|
||||
};
|
||||
|
||||
DatePicker.locale('hu', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import id from 'date-format-parse/lib/locale/id';
|
||||
|
||||
const lang = {
|
||||
formatLocale: id,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('id', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import is from 'date-format-parse/lib/locale/is';
|
||||
|
||||
const lang = {
|
||||
formatLocale: is,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('is', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import it from 'date-format-parse/lib/locale/it';
|
||||
|
||||
const lang = {
|
||||
formatLocale: it,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('it', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import ja from 'date-format-parse/lib/locale/ja';
|
||||
|
||||
const lang = {
|
||||
formatLocale: ja,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: false,
|
||||
};
|
||||
|
||||
DatePicker.locale('ja', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import ka from 'date-format-parse/lib/locale/ka';
|
||||
|
||||
const lang = {
|
||||
formatLocale: ka,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('ka', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import kk from 'date-format-parse/lib/locale/kk';
|
||||
|
||||
const lang = {
|
||||
formatLocale: kk,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('kk', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import ko from 'date-format-parse/lib/locale/ko';
|
||||
|
||||
const lang = {
|
||||
formatLocale: ko,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: false,
|
||||
};
|
||||
|
||||
DatePicker.locale('ko', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import lt from 'date-format-parse/lib/locale/lt';
|
||||
|
||||
const lang = {
|
||||
formatLocale: lt,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('lt', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import lv from 'date-format-parse/lib/locale/lv';
|
||||
|
||||
const lang = {
|
||||
formatLocale: lv,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: false,
|
||||
};
|
||||
|
||||
DatePicker.locale('lv', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import mk from 'date-format-parse/lib/locale/mk';
|
||||
|
||||
const lang = {
|
||||
formatLocale: mk,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('mk', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import ms from 'date-format-parse/lib/locale/ms';
|
||||
|
||||
const lang = {
|
||||
formatLocale: ms,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('ms', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import nb from 'date-format-parse/lib/locale/nb';
|
||||
|
||||
const lang = {
|
||||
formatLocale: nb,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('nb', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import nlBE from 'date-format-parse/lib/locale/nl-be';
|
||||
|
||||
const lang = {
|
||||
formatLocale: nlBE,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('nl-be', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import nl from 'date-format-parse/lib/locale/nl';
|
||||
|
||||
const lang = {
|
||||
formatLocale: nl,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('nl', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import pl from 'date-format-parse/lib/locale/pl';
|
||||
|
||||
const lang = {
|
||||
formatLocale: pl,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('pl', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import ptBR from 'date-format-parse/lib/locale/pt-br';
|
||||
|
||||
const lang = {
|
||||
formatLocale: ptBR,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('pt-br', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import pt from 'date-format-parse/lib/locale/pt';
|
||||
|
||||
const lang = {
|
||||
formatLocale: pt,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('pt', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import ro from 'date-format-parse/lib/locale/ro';
|
||||
|
||||
const lang = {
|
||||
formatLocale: ro,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('ro', lang);
|
||||
|
||||
export default lang;
|
||||
@@ -0,0 +1,13 @@
|
||||
import DatePicker from 'vue2-datepicker';
|
||||
import ru from 'date-format-parse/lib/locale/ru';
|
||||
|
||||
const lang = {
|
||||
formatLocale: ru,
|
||||
yearFormat: 'YYYY',
|
||||
monthFormat: 'MMM',
|
||||
monthBeforeYear: true,
|
||||
};
|
||||
|
||||
DatePicker.locale('ru', lang);
|
||||
|
||||
export default lang;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user