├── packages ├── demo │ ├── .gitignore │ ├── src │ │ ├── app.ts │ │ ├── app.css │ │ └── views │ │ │ └── DemoApp.vue │ ├── tsconfig.json │ ├── package.json │ ├── vite.config.ts │ └── index.html ├── lib │ ├── .gitignore │ ├── src │ │ ├── utils │ │ │ ├── index.ts │ │ │ ├── index.spec.ts │ │ │ ├── generators.ts │ │ │ ├── generators.spec.ts │ │ │ ├── datetime.ts │ │ │ └── datetime.spec.ts │ │ ├── composables │ │ │ ├── KeyPress.ts │ │ │ └── ListScroller.ts │ │ ├── flow │ │ │ ├── namespace.ts │ │ │ ├── index.ts │ │ │ ├── FlowManager.ts │ │ │ └── FlowManager.spec.ts │ │ ├── index.ts │ │ ├── namespace.ts │ │ ├── index.spec.ts │ │ ├── DatetimeYearPicker.spec.ts │ │ ├── DatetimeCalendar.spec.ts │ │ ├── DatetimeMonthPicker.spec.ts │ │ ├── DatetimeYearPicker.vue │ │ ├── DatetimeMonthPicker.vue │ │ ├── DatetimeCalendar.vue │ │ ├── DatetimeTimePicker.vue │ │ ├── DateTime.spec.ts │ │ ├── DateTime.vue │ │ ├── DatetimePopup.vue │ │ ├── DatetimeTimePicker.spec.ts │ │ └── DatetimePopup.spec.ts │ ├── tsconfig.build.json │ ├── tsconfig.json │ ├── vite.config.ts │ └── package.json └── CHANGELOG.md ├── demo.gif ├── tsconfig.tsc.json ├── tsconfig.json ├── tsconfig.build.json ├── .gitignore ├── README.md ├── viteBaseConfig.ts ├── tea.yaml ├── LICENSE ├── CONTRIBUTING.md ├── package.json └── CHANGELOG.md /packages/demo/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | 3 | node_modules 4 | -------------------------------------------------------------------------------- /packages/lib/.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | 3 | dist 4 | 5 | node_modules 6 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xhuhu/vue-datetime3-newdemo/HEAD/demo.gif -------------------------------------------------------------------------------- /tsconfig.tsc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": [ 4 | "packages/lib/src/*" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /packages/lib/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export function capitalize(string: string): string { 2 | return string.charAt(0).toUpperCase() + string.slice(1); 3 | } 4 | 5 | export function pad(number: number): string { 6 | return String(number).padStart(2, '0'); 7 | } 8 | -------------------------------------------------------------------------------- /packages/lib/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": [ 4 | "node_modules", 5 | "test/**/*", 6 | "vite.config.ts" 7 | ], 8 | "compilerOptions": { 9 | "declaration": true, 10 | "outDir": "dist" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/eslint-config-velis/tsconfig.json", 3 | "include": [ 4 | "packages/demo/**/*", 5 | "packages/lib/src/**/*", 6 | "viteBaseConfig.ts" 7 | ], 8 | "exclude": [ 9 | "node_modules", 10 | "build", 11 | "dist" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": [ 4 | "packages/demo/**/*", 5 | "node_modules", 6 | "packages/lib/test/**/*", 7 | "viteBaseConfig.ts" 8 | ], 9 | "compilerOptions": { 10 | "declaration": true, 11 | "outDir": "dist" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/demo/src/app.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | 3 | import createDatetime from 'vue-datetime'; 4 | 5 | import DemoApp from './views/DemoApp.vue'; 6 | 7 | import './app.css'; 8 | // import '../../lib/dist/style.css'; 9 | 10 | const app = createApp(DemoApp); 11 | app.use(createDatetime()); 12 | 13 | app.mount('#app'); 14 | -------------------------------------------------------------------------------- /packages/demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../node_modules/eslint-config-velis/tsconfig.json", 3 | "compilerOptions": { 4 | "paths": { 5 | "vue-datetime": ["../lib/src/vue-datetime3.ts"], 6 | } 7 | }, 8 | "include": [ 9 | "/src/**/*" 10 | ], 11 | "exclude": [ 12 | "node_modules", 13 | "dist" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/lib/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "paths": { 5 | "@": ["./src/*"], 6 | "~": ["../../node_modules/*"], 7 | } 8 | }, 9 | "include": [ 10 | "src", 11 | "test", 12 | "vite.config.ts" 13 | ], 14 | "exclude": [ 15 | "node_modules", 16 | "build", 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # editors 2 | .DS_Store 3 | .idea 4 | 5 | # node modules 6 | node_modules/ 7 | 8 | # package managers 9 | package-lock.json 10 | yarn.lock 11 | 12 | # logs 13 | npm-debug.log 14 | yarn-error.log 15 | 16 | # build destinations 17 | dist 18 | # packages/demo/dist 19 | 20 | # testing utils 21 | packages/lib/test/coverage 22 | reports 23 | packages/lib/README.md 24 | -------------------------------------------------------------------------------- /packages/lib/src/composables/KeyPress.ts: -------------------------------------------------------------------------------- 1 | import { onMounted, onUnmounted } from 'vue'; 2 | 3 | export default function useKeyPressListener(eventHandler: (event: KeyboardEvent) => void) { 4 | onMounted(() => { 5 | document.addEventListener('keydown', eventHandler); 6 | }); 7 | onUnmounted(() => { 8 | document.removeEventListener('keydown', eventHandler); 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /packages/lib/src/flow/namespace.ts: -------------------------------------------------------------------------------- 1 | export type FlowType = 'datetime' | 'date' | 'time'; 2 | 3 | export type FlowStep = 'date' | 'time' | 'year' | 'month'; 4 | 5 | export type EndStatus = 'end'; 6 | 7 | export type StepType = FlowStep | EndStatus; 8 | 9 | export interface IFlowManager { 10 | step(index: number): StepType; 11 | first(): StepType; 12 | next(current: StepType): StepType; 13 | diversion(next: string): void; 14 | } 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vue-datetime3 2 | 3 | --- 4 | 5 | > Mobile friendly datetime picker for Vue. Supports date, datetime and time modes, i18n and more. 6 | 7 | This is a fork and port of Vue 2 [vue-datetime](https://github.com/mariomka/vue-datetime) by [mariomka](https://github.com/mariomka) 8 | to support Vue 3 and typescript. For older versions of Vue refer to aforementioned project. 9 | 10 | ## License 11 | 12 | [The MIT License](http://opensource.org/licenses/MIT) 13 | -------------------------------------------------------------------------------- /packages/lib/src/utils/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { capitalize, pad } from './index'; 2 | 3 | describe('General Utils', () => { 4 | it('Capitalize', () => { 5 | const test = 'test'; 6 | const capTest = 'Test'; 7 | expect(capitalize(test)).toEqual(capTest); 8 | }); 9 | 10 | it('Pad', () => { 11 | expect(pad(0)).toBe('00'); 12 | expect(pad(2)).toBe('02'); 13 | expect(pad(12)).toBe('12'); 14 | expect(pad(20)).toBe('20'); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo", 3 | "version": "1.0.0", 4 | "description": "Demo app for vue datetime", 5 | "author": "Mario Juárez ", 6 | "main": "src/app.ts", 7 | "scripts": { 8 | "dev": "vite", 9 | "demo": "vite --mode demo" 10 | }, 11 | "dependencies": { 12 | "vue-datetime3": "*", 13 | "luxon": "^3.3.0", 14 | "vue": "^3.3.4" 15 | }, 16 | "devDependencies": { 17 | "vite": "^4.1.4" 18 | }, 19 | "license": "MIT" 20 | } 21 | -------------------------------------------------------------------------------- /packages/lib/src/index.ts: -------------------------------------------------------------------------------- 1 | import { App } from 'vue'; 2 | 3 | import Datetime from './DateTime.vue'; 4 | import DatetimePopup from './DatetimePopup.vue'; 5 | 6 | export default function createDatetime() { 7 | const install = (app: App) => { 8 | app.component('DateTime', Datetime); 9 | app.component('DateTimePopup', DatetimePopup); 10 | }; 11 | 12 | return { install }; 13 | } 14 | const version = '__VERSION__'; 15 | createDatetime.version = version; 16 | 17 | // Export all views too 18 | export { 19 | Datetime, 20 | DatetimePopup, 21 | version, 22 | }; 23 | -------------------------------------------------------------------------------- /packages/lib/src/composables/ListScroller.ts: -------------------------------------------------------------------------------- 1 | import { onMounted, onUpdated, Ref } from 'vue'; 2 | 3 | import type { ListElement } from '../namespace'; 4 | 5 | export default function useListScroller(list: Ref, pickedClass: string) { 6 | const scrollFunc = () => { 7 | if (list.value) { 8 | const selectedHour: ListElement | null = list.value?.querySelector(pickedClass); 9 | list.value.scrollTo?.({ top: selectedHour ? selectedHour.offsetTop - 152 : 0, behavior: 'auto' }); 10 | } 11 | }; 12 | 13 | onMounted(scrollFunc); 14 | onUpdated(scrollFunc); 15 | 16 | return scrollFunc; 17 | } 18 | -------------------------------------------------------------------------------- /packages/lib/src/namespace.ts: -------------------------------------------------------------------------------- 1 | export interface TimeElement { 2 | key: number 3 | number: number | undefined 4 | label?: string 5 | selected: boolean 6 | disabled: boolean 7 | } 8 | 9 | export interface ListElement extends HTMLElement { 10 | offsetTop: number 11 | } 12 | 13 | export interface Actions { 14 | cancel?: string 15 | ok?: string, 16 | } 17 | 18 | export interface DateElement { 19 | year: number 20 | month: number 21 | day: number 22 | } 23 | 24 | export interface ChangeEvent { 25 | year?: number, 26 | month?: number, 27 | day?: number, 28 | hour?: number, 29 | minute?: number, 30 | suffixTouched?: boolean 31 | } 32 | -------------------------------------------------------------------------------- /viteBaseConfig.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url'; 2 | import { UserConfigExport } from 'vite'; 3 | import vue from '@vitejs/plugin-vue'; 4 | import dts from 'vite-plugin-dts'; 5 | 6 | export default function getBaseViteConfig( 7 | override?: UserConfigExport 8 | ): UserConfigExport { 9 | return { 10 | plugins: [ 11 | vue(), 12 | dts(), 13 | ], 14 | resolve: { 15 | alias: { 16 | // @ts-ignore 17 | '~': fileURLToPath(new URL('./node_modules', import.meta.url)) 18 | }, 19 | extensions: [ 20 | '.js', 21 | '.ts', 22 | '.vue', 23 | '.json', 24 | '.css' 25 | ] 26 | }, 27 | ...override 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/demo/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from 'path'; 2 | 3 | import { AliasOptions, ConfigEnv, defineConfig } from 'vite'; 4 | 5 | // eslint-disable-next-line 6 | import getBaseViteConfig from '../../viteBaseConfig'; 7 | 8 | export default ({ mode }: ConfigEnv) => { 9 | const aliases: AliasOptions = { 10 | 'vue-datetime': (mode === 'development') ? 11 | resolve(__dirname, '../lib/src/index') : 'vue-datetime3', 12 | }; 13 | return defineConfig(getBaseViteConfig({ 14 | server: { 15 | port: 8080, 16 | fs: { 17 | // Allowing serving files from one level up to the project root 18 | allow: ['../..'], 19 | }, 20 | }, 21 | resolve: { alias: aliases }, 22 | })); 23 | }; 24 | -------------------------------------------------------------------------------- /packages/lib/src/flow/index.ts: -------------------------------------------------------------------------------- 1 | import FlowManager, { dateFlow, dateTimeFlow, flowEndStatus, timeFlow } from './FlowManager'; 2 | import { FlowStep, FlowType, IFlowManager } from './namespace'; 3 | 4 | export const createFlowManager = (flow: FlowStep[]): IFlowManager => (new FlowManager(flow)); 5 | 6 | export const createFlowManagerFromType = (type: FlowType): IFlowManager => { 7 | switch (type) { 8 | case 'datetime': 9 | return new FlowManager(dateTimeFlow); 10 | case 'date': 11 | return new FlowManager(dateFlow); 12 | case 'time': 13 | return new FlowManager(timeFlow); 14 | default: 15 | throw new TypeError(`Cannot create flow type of ${type}`); 16 | } 17 | }; 18 | 19 | export { flowEndStatus }; 20 | 21 | export default FlowManager; 22 | -------------------------------------------------------------------------------- /packages/demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | vue-datetime demo 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /packages/lib/src/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { expectTypeOf } from 'vitest'; 2 | import { createApp } from 'vue'; 3 | 4 | import createDatetime from './index'; 5 | 6 | describe('API testing', () => { 7 | it('Default export should return a plugin function', () => { 8 | const result = createDatetime(); 9 | 10 | expect(result?.install).toBeDefined(); 11 | expectTypeOf(result.install).toMatchTypeOf(); 12 | }); 13 | 14 | it('Check if plugin exposes all the right components', () => { 15 | const app = createApp({ template: '
' }).use(createDatetime()); 16 | 17 | // eslint-disable-next-line no-underscore-dangle 18 | expect(Object.entries(app._context.components)).toHaveLength(2); 19 | // eslint-disable-next-line no-underscore-dangle 20 | expect(Object.keys(app._context.components)).toEqual(['DateTime', 'DateTimePopup']); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /packages/lib/src/utils/generators.ts: -------------------------------------------------------------------------------- 1 | import { Info, WeekdayNumbers } from 'luxon'; 2 | 3 | import { capitalize } from '.'; 4 | 5 | export function weekdaysGenerator(weekStart: WeekdayNumbers): string[] { 6 | const localWeekStart = weekStart - 1; 7 | 8 | let weekDays = Info.weekdays('short').map((weekday) => capitalize(weekday)); 9 | 10 | weekDays = weekDays.concat(weekDays.splice(0, localWeekStart)); 11 | 12 | return weekDays; 13 | } 14 | 15 | export function monthsGenerator(): string[] { 16 | return [...Info.months().map((month: string) => capitalize(month))]; 17 | } 18 | 19 | export function hoursGenerator(step: number): number[] { 20 | return [...Array(Math.ceil(24 / step))].map((_, index) => index * step); 21 | } 22 | 23 | export function minutesGenerator(step: number): number[] { 24 | return [...Array(Math.ceil(60 / step))].map((_, index) => index * step); 25 | } 26 | 27 | export function yearsGenerator(current: number): number[] { 28 | return [...Array(201)].map((_, index) => current - 100 + index); 29 | } 30 | -------------------------------------------------------------------------------- /tea.yaml: -------------------------------------------------------------------------------- 1 | # https://tea.xyz/what-is-this-file 2 | --- 3 | version: 1.0.0 4 | codeOwners: 5 | - '0xBDe8ADD4a2034475d4F501228b23D5c9F0b195CB' 6 | - '0x293b35659ec37FAE89408bf8A72d89e430aC86c9' 7 | - '0x6ee5619F0D6c0F530252f96DeB861F96AF9b733F' 8 | - '0x51302DDA4E29c812d7660049c178d8fEAACA7Df3' 9 | - '0x7F5F5b4742BF1A04DbCD1f83E742cdd658597D1f' 10 | - '0xd0db12E391031d46e071c3154DfCC2e9F1deADb5' 11 | - '0x049e20f78cE63eE6EA79CD0004554FF6526D1f5A' 12 | - '0xa0F9a70473cA850F7c60ef7698a1dAfF321bdf2a' 13 | - '0x13d76fC6D16f502afe95e2fC6A95927C905BeC7E' 14 | - '0xF70f96406092CcB3806842E2f7779C01A7346bc9' 15 | - '0xa4B775c3c99CfFaBf82773c57D293cfF8Aac14Fd' 16 | - '0x3a03006F24B50DA3eb81641Ad6bce625f5966949' 17 | - '0x73404449Ac35684780bDf917D176fe33Bd71424D' 18 | - '0x6811c098100B44c7CC26BeFA8510be6dFaF8B616' 19 | - '0x0DE801156503b50CE7E2036688Dc4EE149Fcc994' 20 | - '0x11d39a6EeC5EBe11A3BA2899510e4e7D11A2670c' 21 | - '0x0F9751D42d67708fd7a480929f603E2f2200B3a2' 22 | - '0x99F103FE54DD01238e0678d0578c3581a318b53a' 23 | - '0x3e47fc95744f7C58d5d4BcefBc1b5986A1aBE40C' 24 | - '0x1c65CED4f2Eb94baB3687B8b36996d45e0BB5a7d' 25 | quorum: 1 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-present Mario Juárez (http://www.mjp.one) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/lib/src/flow/FlowManager.ts: -------------------------------------------------------------------------------- 1 | import { EndStatus, FlowStep, IFlowManager, StepType } from './namespace'; 2 | 3 | export const timeFlow: FlowStep[] = ['time']; 4 | export const dateFlow: FlowStep[] = ['date']; 5 | export const dateTimeFlow: FlowStep[] = ['date', 'time']; 6 | 7 | export const flowEndStatus: EndStatus = 'end'; 8 | 9 | class FlowManager implements IFlowManager { 10 | private readonly flow: FlowStep[]; 11 | 12 | private readonly endStatus: EndStatus = flowEndStatus; 13 | 14 | private diversionNext: StepType | null; 15 | 16 | constructor(flow: FlowStep[] = []) { 17 | this.flow = flow; 18 | this.diversionNext = null; 19 | } 20 | 21 | step(index: number): StepType { 22 | return (index >= 0 && this.flow.length > index) ? this.flow[index] : this.endStatus; 23 | } 24 | 25 | first(): StepType { 26 | return this.step(0); 27 | } 28 | 29 | next(current: FlowStep): StepType { 30 | if (this.diversionNext) { 31 | const next = this.diversionNext; 32 | this.diversionNext = null; 33 | 34 | return next; 35 | } 36 | 37 | return this.step(this.flow.indexOf(current) + 1); 38 | } 39 | 40 | diversion(next: StepType): void { 41 | this.diversionNext = next; 42 | } 43 | } 44 | 45 | export default FlowManager; 46 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions are **welcome** and will be fully **credited**. 4 | 5 | We accept contributions via Pull Requests on [Github](https://github.com/mariomka/vue-datetime). 6 | 7 | 8 | ## Pull Requests 9 | 10 | - **Keep the same style** - eslint will automatically be ran before committing 11 | 12 | - **Tip** to pass lint tests easier use the `yarn lint` command 13 | 14 | - **Add tests!** - Your patch won't be accepted if it doesn't have tests. 15 | 16 | - **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. 17 | 18 | - **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. 19 | 20 | - **Create feature branches** - Don't ask us to pull from your master branch. 21 | 22 | - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. 23 | 24 | - **Send coherent history** - Make sure your commits message means something 25 | 26 | 27 | ## Running Tests 28 | 29 | Launch tests 30 | 31 | ``` bash 32 | $ yarn test 33 | ``` 34 | 35 | Launch visual tests and watch the components at the same time 36 | 37 | ``` bash 38 | $ yarn dev 39 | ``` 40 | 41 | 42 | **Happy coding**! 43 | -------------------------------------------------------------------------------- /packages/lib/vite.config.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { fileURLToPath } from 'node:url'; 3 | import { resolve } from 'path'; 4 | 5 | import { defineConfig } from 'vite'; 6 | 7 | // eslint-disable-next-line 8 | import getBaseViteConfig from '../../viteBaseConfig'; 9 | 10 | export default defineConfig(getBaseViteConfig({ 11 | build: { 12 | target: 'es2015', 13 | lib: { 14 | entry: resolve(__dirname, 'src/index.ts'), 15 | fileName: 'vue-datetime', 16 | name: 'vue-datetime.[name]', 17 | }, 18 | rollupOptions: { 19 | external: ['luxon', 'vue', 'weekstart'], 20 | output: { 21 | globals: { 22 | vue: 'vue', 23 | luxon: 'luxon', 24 | weekstart: 'weekstart', 25 | }, 26 | exports: 'named', 27 | }, 28 | }, 29 | }, 30 | resolve: { 31 | alias: { 32 | // @ts-ignore 33 | '~': fileURLToPath(new URL('../../node_modules', import.meta.url)), 34 | // @ts-ignore 35 | '@': fileURLToPath(new URL('./src', import.meta.url)), 36 | }, 37 | extensions: [ 38 | '.js', 39 | '.ts', 40 | '.vue', 41 | '.json', 42 | '.css', 43 | ], 44 | }, 45 | test: { 46 | include: ['./src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], 47 | exclude: ['./test/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], 48 | globals: true, 49 | environment: 'jsdom', 50 | useAtomics: true, // eliminate tests hang at the end (https://github.com/vitest-dev/vitest/issues/2008) 51 | }, 52 | })); 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-datetime3-newdemo", 3 | "version": "1.0.7", 4 | "homepage": "https://github.com/0xhuhu/vue-datetime3-newdemo.git", 5 | "description": "Datepicker component for Vue 3", 6 | "workspaces": [ 7 | "packages/*" 8 | ], 9 | "scripts": { 10 | "dev": "npm run dev -ws --if-present", 11 | "demo": "concurrently \"npm run demo --w demo\" \"npm run watch -w vue-datetime3\"", 12 | "build": "cp README.md packages/lib && npm run build -ws --if-present", 13 | "test": "npm run test -ws --if-present", 14 | "tsc": "vue-tsc --noEmit -p tsconfig.tsc.json", 15 | "version": "npm run version -ws --if-present" 16 | }, 17 | "devDependencies": { 18 | "@babel/types": "^7.21.4", 19 | "concurrently": "^8.0.1", 20 | "pre-commit": "^1.2.0", 21 | "typescript": "^4.9.5", 22 | "vue-datepicker-minitest": "^8.2.3", 23 | "web-scheduler": "^1.5.0" 24 | }, 25 | "dependencies": { 26 | "date-fns": "^3.3.1", 27 | "vue-datepicker-minitest": "^9.0.1", 28 | "react-day-picker-trial": "^9.0.0", 29 | "web-scheduler": "^1.5.0" 30 | }, 31 | "pre-commit": "--no-verify", 32 | "engines": { 33 | "node": "^18.10.0", 34 | "npm": "^9.2.0" 35 | }, 36 | "repository": { 37 | "type": "git", 38 | "url": "https://github.com/0xhuhu/vue-datetime3-newdemo.git" 39 | }, 40 | "eslintConfig": { 41 | "extends": [ 42 | "velis" 43 | ], 44 | "rules": { 45 | "vuejs-accessibility/click-events-have-key-events": "off", 46 | "vuejs-accessibility/form-control-has-label": "off", 47 | "vuejs-accessibility/label-has-for": "off" 48 | }, 49 | "ignorePatterns": [ 50 | "coverage/*", 51 | "node_modules/*", 52 | "build/*" 53 | ] 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /packages/lib/src/DatetimeYearPicker.spec.ts: -------------------------------------------------------------------------------- 1 | import { shallowMount, VueWrapper } from '@vue/test-utils'; 2 | import { DateTime } from 'luxon'; 3 | 4 | import DatetimeYearPicker from './DatetimeYearPicker.vue'; 5 | 6 | describe('DatetimeYearPicker', () => { 7 | let wrapper: VueWrapper; 8 | 9 | beforeEach(() => { 10 | const minDate = DateTime.fromObject({ year: 2000 }); 11 | const maxDate = DateTime.fromObject({ year: 2030 }); 12 | 13 | wrapper = shallowMount(DatetimeYearPicker, { 14 | props: { 15 | year: 2023, 16 | minDate, 17 | maxDate, 18 | }, 19 | }); 20 | }); 21 | 22 | afterEach(() => { 23 | wrapper.unmount(); 24 | }); 25 | 26 | // let tmp: VueWrapper; 27 | test('Renders The Correct Year', () => { 28 | const yearLabel = wrapper.find('.selected'); 29 | expect(yearLabel.text()).toBe('2023'); 30 | }); 31 | 32 | test('renders the correct range of years', () => { 33 | const allOptions = wrapper.findAll('.item'); 34 | expect(allOptions.length).toBe(201); // Number of years between 2000 and 2030 (inclusive) 35 | const options = wrapper.findAll('.item:not(.disabled)'); 36 | expect(options.length).toBe(31); 37 | 38 | const firstYear = options[0].text(); 39 | const lastYear = options[options.length - 1].text(); 40 | expect(firstYear).toBe('2000'); 41 | expect(lastYear).toBe('2030'); 42 | }); 43 | 44 | test('emits the selected year when clicked', async () => { 45 | const yearOption = wrapper.find('.item:not(.disabled)'); 46 | await yearOption.trigger('click'); 47 | expect(wrapper.emitted('change')).toBeTruthy(); 48 | expect(wrapper.emitted('change')?.[0]?.[0]).toBe(2000); // Assuming the first year is selected 49 | }); 50 | 51 | test('clicking disabled element should not emit', async () => { 52 | const disabledOption = wrapper.find('.item.disabled'); 53 | await disabledOption.trigger('click'); 54 | expect(wrapper.emitted('change')).toBeUndefined(); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /packages/demo/src/app.css: -------------------------------------------------------------------------------- 1 | *, 2 | *::after, 3 | *::before { 4 | box-sizing: border-box; 5 | margin: 0; 6 | padding: 0; 7 | } 8 | 9 | body { 10 | background-color: #eee; 11 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; 12 | font-size: 16px; 13 | padding: 1em; 14 | color: #444; 15 | } 16 | 17 | .page { 18 | background-color: #fff; 19 | margin: 0 auto; 20 | padding: 2em 3em; 21 | width: 100%; 22 | max-width: 900px; 23 | box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); 24 | } 25 | 26 | h1 { 27 | margin: 0 0 1em; 28 | font-weight: 200; 29 | font-size: 52px; 30 | } 31 | 32 | h1 > a { 33 | color: #333; 34 | text-decoration: none; 35 | } 36 | 37 | h2 { 38 | margin: 0 0 1em; 39 | border-bottom: solid 1px #ddd; 40 | font-weight: 200; 41 | font-size: 26px; 42 | color: #666; 43 | } 44 | 45 | p.description { 46 | margin: 0 0 1em; 47 | font-style: italic; 48 | font-size: 14px; 49 | color: #aaa; 50 | } 51 | 52 | .example { 53 | margin: 0 0 2em; 54 | } 55 | 56 | @media screen and (min-width: 900px) { 57 | .example { 58 | display: flex; 59 | } 60 | 61 | .example > .example-inputs { 62 | width: 32%; 63 | } 64 | 65 | .example > .example-code { 66 | margin-top: 0; 67 | width: 68%; 68 | } 69 | } 70 | 71 | .example > .example-inputs input { 72 | padding: 8px 10px; 73 | font-size: 16px; 74 | border: solid 1px #ddd; 75 | color: #444; 76 | } 77 | 78 | .example > .example-code > pre > code { 79 | padding: 1.5em; 80 | } 81 | 82 | .example > .example-code > pre { 83 | margin-bottom: 15px; 84 | width: 100%; 85 | font-size: 14px; 86 | overflow: scroll; 87 | } 88 | 89 | .values { 90 | margin-top: 20px; 91 | font-size: 14px; 92 | } 93 | 94 | footer > a { 95 | color: #aaa; 96 | text-decoration: none; 97 | } 98 | 99 | footer > a:hover { 100 | text-decoration: underline; 101 | } 102 | 103 | footer { 104 | margin: 50px 0 0; 105 | font-size: 14px; 106 | font-weight: lighter; 107 | color: #aaa; 108 | } 109 | -------------------------------------------------------------------------------- /packages/lib/src/utils/generators.spec.ts: -------------------------------------------------------------------------------- 1 | import { expectTypeOf } from 'vitest'; 2 | 3 | import { hoursGenerator, minutesGenerator, monthsGenerator, weekdaysGenerator, yearsGenerator } from './generators'; 4 | 5 | describe('Generators', () => { 6 | it('Weekdays Generator', () => { 7 | expectTypeOf(weekdaysGenerator(1)).toMatchTypeOf(); 8 | 9 | expect(weekdaysGenerator(1).length).toBe(7); 10 | expect(weekdaysGenerator(1).length).toBe(weekdaysGenerator(3).length); 11 | 12 | const weekDays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; 13 | expect(weekdaysGenerator(1)).toEqual(weekDays); 14 | expect(weekdaysGenerator(3)).toEqual(weekDays.concat(weekDays.splice(0, 2))); 15 | }); 16 | 17 | it('Month Generator', () => { 18 | expectTypeOf(monthsGenerator()).toMatchTypeOf(); 19 | 20 | expect(monthsGenerator().length).toBe(12); 21 | 22 | const months = [ 23 | 'January', 24 | 'February', 25 | 'March', 26 | 'April', 27 | 'May', 28 | 'June', 29 | 'July', 30 | 'August', 31 | 'September', 32 | 'October', 33 | 'November', 34 | 'December', 35 | ]; 36 | expect(monthsGenerator()).toEqual(months); 37 | }); 38 | 39 | it('Hours Generator', () => { 40 | expectTypeOf(hoursGenerator(1)).toMatchTypeOf(); 41 | 42 | expect(hoursGenerator(1)).toHaveLength(24); 43 | expect(hoursGenerator(2)).toHaveLength(12); 44 | 45 | hoursGenerator(1).forEach((element: number) => { 46 | expect(element).toBeGreaterThanOrEqual(0); 47 | expect(element).toBeLessThanOrEqual(24); 48 | }); 49 | }); 50 | 51 | it('Minutes Generator', () => { 52 | expectTypeOf(minutesGenerator(1)).toMatchTypeOf(); 53 | 54 | expect(minutesGenerator(1)).toHaveLength(60); 55 | expect(minutesGenerator(2)).toHaveLength(30); 56 | expect(minutesGenerator(5)).toHaveLength(12); 57 | 58 | minutesGenerator(1).forEach((element: number) => { 59 | expect(element).toBeGreaterThanOrEqual(0); 60 | expect(element).toBeLessThanOrEqual(60); 61 | }); 62 | }); 63 | 64 | it('Years Generator', () => { 65 | expectTypeOf(yearsGenerator(2023)).toMatchTypeOf(); 66 | 67 | expect(yearsGenerator(2023)).toHaveLength(201); 68 | expect(yearsGenerator(2023)).toContain(2023); 69 | }); 70 | }); 71 | -------------------------------------------------------------------------------- /packages/lib/src/DatetimeCalendar.spec.ts: -------------------------------------------------------------------------------- 1 | import { shallowMount, VueWrapper } from '@vue/test-utils'; 2 | import { DateTime } from 'luxon'; 3 | 4 | import DatetimeCalendar from './DatetimeCalendar.vue'; 5 | import { ChangeEvent } from './namespace'; 6 | 7 | describe('Datetime Calendar', () => { 8 | let wrapper: VueWrapper; 9 | 10 | beforeEach(() => { 11 | wrapper = shallowMount(DatetimeCalendar, { 12 | props: { 13 | year: 2023, 14 | month: 9, 15 | day: 21, 16 | minDate: DateTime.fromISO('2023-01-01'), 17 | maxDate: DateTime.fromISO('2023-09-30'), 18 | }, 19 | }); 20 | }); 21 | 22 | afterEach(() => { 23 | wrapper.unmount(); 24 | }); 25 | 26 | it('Renders correct month and year', () => { 27 | const element = wrapper.find('.current--month'); 28 | expect(element.text()).toBe('September 2023'); 29 | }); 30 | 31 | it('Renders weekdays correctly', () => { 32 | const elements = wrapper.findAll('.month .month__weekday').map((element) => element.text()); 33 | const weekDays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; 34 | 35 | expect(elements).toEqual(weekDays); 36 | }); 37 | 38 | it('Renders days correctly', () => { 39 | const elements = wrapper.findAll('.month .month__day'); 40 | expect(elements).toHaveLength(42); 41 | }); 42 | 43 | it('Renders date correctly', () => { 44 | const selectedDate = wrapper.find('.month .month__day.selected'); 45 | expect(selectedDate.text()).toBe('21'); 46 | }); 47 | 48 | it('Clicking on enabled date should trigger change event', () => { 49 | const dateOption = wrapper.find('.month .month__day:not(.disabled)'); 50 | dateOption.trigger('click'); 51 | expect(wrapper.emitted('change')?.[0]?.[0]).toEqual({ year: 2023, month: 9, day: 1 }); 52 | }); 53 | 54 | it('Clicking on next month should change month value', async () => { 55 | const newMonth = wrapper.find('.navigation--next'); 56 | await newMonth.trigger('click'); 57 | 58 | const monthYear = wrapper.find('.current--month'); 59 | expect(monthYear.text()).toBe('October 2023'); 60 | }); 61 | 62 | it('Clicking on previous month should change month value', async () => { 63 | const newMonth = wrapper.find('.navigation--previous'); 64 | await newMonth.trigger('click'); 65 | await wrapper.vm.$nextTick(); 66 | const monthYear = wrapper.find('.current--month'); 67 | expect(monthYear.text()).toBe('August 2023'); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /packages/lib/src/DatetimeMonthPicker.spec.ts: -------------------------------------------------------------------------------- 1 | import { shallowMount, VueWrapper } from '@vue/test-utils'; 2 | import { DateTime } from 'luxon'; 3 | 4 | import DatetimeMonthPicker from './DatetimeMonthPicker.vue'; 5 | 6 | describe('DatetimeMonthPicker', () => { 7 | let wrapper: VueWrapper; 8 | 9 | beforeEach(() => { 10 | wrapper = shallowMount(DatetimeMonthPicker, { 11 | props: { 12 | year: 2023, 13 | month: 2, 14 | minDate: DateTime.fromISO('2023-01-01'), 15 | maxDate: DateTime.fromISO('2023-09-30'), 16 | }, 17 | }); 18 | }); 19 | 20 | afterEach(() => { 21 | wrapper.unmount(); 22 | }); 23 | 24 | // let tmp: VueWrapper; 25 | test('Renders The Correct Month', () => { 26 | const yearLabel = wrapper.find('.selected'); 27 | expect(yearLabel.text()).toBe('February'); 28 | }); 29 | 30 | test('Renders The Correct Range of Months', () => { 31 | const allOptions = wrapper.findAll('.item'); 32 | expect(allOptions.length).toBe(12); // Number of years between 2000 and 2030 (inclusive) 33 | const options = wrapper.findAll('.item:not(.disabled)'); 34 | expect(options.length).toBe(9); 35 | 36 | const firstMonth = allOptions[0].text(); 37 | const lastMonth = allOptions[allOptions.length - 1].text(); 38 | expect(firstMonth).toBe('January'); 39 | expect(lastMonth).toBe('December'); 40 | 41 | const firstEnabledMonth = options[0].text(); 42 | const lastEnabledMonth = options[options.length - 1].text(); 43 | expect(firstEnabledMonth).toBe('January'); 44 | expect(lastEnabledMonth).toBe('September'); 45 | 46 | const months = [ 47 | 'January', 'February', 'March', 'April', 'May', 'June', 48 | 'July', 'August', 'September', 'October', 'November', 'December', 49 | ]; 50 | allOptions.forEach((option, index) => { 51 | expect(option.text()).toBe(months[index]); 52 | }); 53 | options.forEach((option, index) => { 54 | expect(option.text()).toBe(months[index]); 55 | }); 56 | }); 57 | 58 | test('Emits the Selected Month When Clicked', async () => { 59 | const yearOption = wrapper.find('.item:not(.disabled)'); 60 | await yearOption.trigger('click'); 61 | expect(wrapper.emitted('change')).toBeTruthy(); 62 | expect(wrapper.emitted('change')?.[0]?.[0]).toBe(1); // assuming January (1 index) is selected 63 | }); 64 | 65 | test('Clicking Disabled Month Should Not Emit', async () => { 66 | const disabledOption = wrapper.find('.item.disabled'); 67 | await disabledOption.trigger('click'); 68 | expect(wrapper.emitted('change')).toBeUndefined(); 69 | }); 70 | }); 71 | -------------------------------------------------------------------------------- /packages/lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-datetime3", 3 | "version": "1.0.15", 4 | "description": "Mobile friendly datetime picker for Vue. Supports date, datetime and time modes, i18n and disabling dates.", 5 | "keywords": [ 6 | "datetime", 7 | "datetime-picker", 8 | "picker", 9 | "date", 10 | "vue" 11 | ], 12 | "author": "Mario Juárez ", 13 | "main": "dist/vue-datetime.umd.js", 14 | "types": "dist/index.d.ts", 15 | "module": "dist/vue-datetime.mjs", 16 | "style": "dist/style.css", 17 | "files": [ 18 | "dist" 19 | ], 20 | "exports": { 21 | ".": { 22 | "types": "./dist/index.d.ts", 23 | "import": "./dist/vue-datetime.mjs", 24 | "require": "./dist/vue-datetime.umd.js" 25 | }, 26 | "./style.css": "./dist/style.css" 27 | }, 28 | "scripts": { 29 | "build": "vite build", 30 | "watch": "vite build --watch", 31 | "clean": "rimraf dist && rimraf build/dist", 32 | "lint": "yon run lint:js && yon run lint:css", 33 | "test": "vitest run --coverage", 34 | "version": "auto-changelog -p --starting-commit 975d478b80b8e1ed3663f55b34c3a35521a43bdb --commit-limit false && mv CHANGELOG.md .. && git add ../CHANGELOG.md" 35 | }, 36 | "devDependencies": { 37 | "@types/jest": "^29.2.5", 38 | "@types/luxon": "^3.2.0", 39 | "@types/node": "^18.15.11", 40 | "@vitejs/plugin-vue": "^4.0.0", 41 | "@vitest/coverage-c8": "^0.31.1", 42 | "@vue/test-utils": "^2.3.2", 43 | "@vue/tsconfig": "^0.3.2", 44 | "auto-changelog": "^1.3.0", 45 | "clean-css": "^4.0.0", 46 | "eslint-config-velis": "^1.1.14", 47 | "gh-pages": "^1.1.0", 48 | "jsdom": "^22.0.0", 49 | "sass": "^1.62.1", 50 | "typescript": "^4.9.5", 51 | "vite": "^4.1.4", 52 | "vite-plugin-dts": "^2.2.0", 53 | "vitest": "^0.31.1", 54 | "vue-tsc": "^1.2.0" 55 | }, 56 | "peerDependencies": { 57 | "luxon": "^3.3.0", 58 | "vue": "^3.2.47", 59 | "weekstart": "^2.0.0" 60 | }, 61 | "repository": { 62 | "type": "git", 63 | "url": "git+https://github.com/velis74/vue-datetime.git" 64 | }, 65 | "bugs": { 66 | "url": "https://github.com/velis74/vue-datetime/issues" 67 | }, 68 | "homepage": "https://github.com/velis74/vue-datetime#readme", 69 | "license": "MIT", 70 | "eslintConfig": { 71 | "extends": [ 72 | "velis" 73 | ], 74 | "rules": { 75 | "vuejs-accessibility/click-events-have-key-events": "off", 76 | "vuejs-accessibility/form-control-has-label": "off", 77 | "vuejs-accessibility/label-has-for": "off" 78 | }, 79 | "ignorePatterns": [ 80 | "coverage/*", 81 | "node_modules/*", 82 | "build/*" 83 | ] 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /packages/lib/src/DatetimeYearPicker.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 56 | 57 | 120 | -------------------------------------------------------------------------------- /packages/lib/src/DatetimeMonthPicker.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 61 | 62 | 124 | -------------------------------------------------------------------------------- /packages/lib/src/flow/FlowManager.spec.ts: -------------------------------------------------------------------------------- 1 | import { expectTypeOf } from 'vitest'; 2 | 3 | import type { FlowStep, IFlowManager } from './namespace'; 4 | 5 | import FlowManager, { createFlowManager, createFlowManagerFromType, flowEndStatus } from './index'; 6 | 7 | describe('Flow Manager', () => { 8 | const flowManager = new FlowManager(['date', 'time']); 9 | const addDiversion = (name: FlowStep) => { flowManager.diversion(name); }; 10 | const emptyManager = () => (new FlowManager([])); 11 | 12 | it('Create Flow Manager', () => { 13 | expectTypeOf(flowManager).toEqualTypeOf(); 14 | expectTypeOf(flowManager).toMatchTypeOf(); 15 | expectTypeOf(new FlowManager([])).toEqualTypeOf(); 16 | }); 17 | 18 | it('Flow Manager First', () => { 19 | expect(flowManager.first()).toBe('date'); 20 | expect(emptyManager().first()).toBe(flowEndStatus); 21 | expect(emptyManager().first()).toBe(flowEndStatus); 22 | }); 23 | 24 | it('Flow Manager Step', () => { 25 | expect(flowManager.step(-1)).toBe(flowEndStatus); 26 | expect(flowManager.step(0)).toBe('date'); 27 | expect(flowManager.step(1)).toBe('time'); 28 | expect(flowManager.step(2)).toBe(flowEndStatus); 29 | }); 30 | 31 | it('Flow Manager Next', () => { 32 | expect(flowManager.next('date')).toBe('time'); 33 | expect(flowManager.next('time')).toBe(flowEndStatus); 34 | // @ts-ignore 35 | expect(flowManager.next(flowEndStatus)).toBe('date'); 36 | // @ts-ignore 37 | expect(flowManager.next('somethingcomepletlybogus')).toBe('date'); 38 | 39 | expect(emptyManager().next('date')).toBe(flowEndStatus); 40 | // @ts-ignore 41 | expect(emptyManager().next('somethingcomepletlybogus')).toBe(flowEndStatus); 42 | }); 43 | 44 | it('Flow Manager Diversion', () => { 45 | // @ts-ignore 46 | addDiversion('test'); 47 | expect(flowManager.next('date')).toBe('test'); 48 | expect(flowManager.next('date')).toBe('time'); 49 | 50 | const manager = emptyManager(); 51 | // @ts-ignore 52 | manager.diversion('test'); 53 | expect(manager.next('date')).toBe('test'); 54 | expect(manager.next('date')).toBe(flowEndStatus); 55 | }); 56 | }); 57 | 58 | describe('Flow Manager Factory Functions', () => { 59 | it('Create Flow Manager', () => { 60 | const manager = createFlowManager(['date', 'time']); 61 | expect(manager.step(0)).toBe('date'); 62 | expect(manager.step(1)).toBe('time'); 63 | expect(manager.step(2)).toBe(flowEndStatus); 64 | }); 65 | 66 | it('Create Flow Manager From Flow Type', () => { 67 | let manager = createFlowManagerFromType('datetime'); 68 | expect(manager.step(0)).toBe('date'); 69 | expect(manager.step(1)).toBe('time'); 70 | expect(manager.step(2)).toBe(flowEndStatus); 71 | 72 | manager = createFlowManagerFromType('date'); 73 | expect(manager.step(0)).toBe('date'); 74 | expect(manager.step(2)).toBe(flowEndStatus); 75 | 76 | manager = createFlowManagerFromType('time'); 77 | expect(manager.step(0)).toBe('time'); 78 | expect(manager.step(2)).toBe(flowEndStatus); 79 | 80 | // @ts-ignore 81 | expect(() => createFlowManagerFromType('sometotallybogustype')).toThrow(TypeError); 82 | }); 83 | }); 84 | -------------------------------------------------------------------------------- /packages/lib/src/utils/datetime.ts: -------------------------------------------------------------------------------- 1 | import { DateTime, Settings, WeekdayNumbers } from 'luxon'; 2 | import { getWeekStartByLocale } from 'weekstart'; 3 | 4 | import { DateElement } from '../namespace'; 5 | 6 | export function datetimeFromISO(string: string): DateTime | undefined { 7 | const datetime = DateTime.fromISO(string); 8 | 9 | return datetime.isValid ? datetime : undefined; 10 | } 11 | 12 | export const startOfDay = (datetime: DateTime | undefined): DateTime | undefined => (datetime?.startOf('day')); 13 | 14 | export function validDatetimeRange(minDate: DateTime | undefined, maxDate: DateTime | undefined): boolean { 15 | // Valid range is whatever either date is null or when minDate is lesser then maxDate 16 | return !minDate || !maxDate || minDate <= maxDate; 17 | } 18 | 19 | export function yearIsDisabled(minDate: DateTime | undefined, maxDate: DateTime | undefined, year: number): boolean { 20 | const minYear = minDate?.year; 21 | const maxYear = maxDate?.year; 22 | 23 | return !validDatetimeRange(minDate, maxDate) || (!!minYear && year < minYear) || (!!maxYear && year > maxYear); 24 | } 25 | 26 | export function monthIsDisabled( 27 | minDate: DateTime | undefined, 28 | maxDate: DateTime | undefined, 29 | year: number, 30 | month: number, 31 | ): boolean { 32 | const minMonth = minDate?.month; 33 | const maxMonth = maxDate?.month; 34 | 35 | return yearIsDisabled(minDate, maxDate, year) || 36 | (!!minMonth && minDate.year === year && month < minDate.month) || 37 | (!!maxMonth && maxDate.year === year && month > maxDate.month); 38 | } 39 | 40 | export function dateIsDisabled( 41 | minDate: DateTime | undefined, 42 | maxDate: DateTime | undefined, 43 | year: number, 44 | month: number, 45 | day: number, 46 | ): boolean { 47 | const minDay = minDate?.day; 48 | const maxDay = maxDate?.day; 49 | 50 | return monthIsDisabled(minDate, maxDate, year, month) || 51 | (!!minDay && (minDate.month === month && minDate.year === year && day < minDate.day)) || 52 | (!!maxDay && (maxDate.month === month && maxDate.year === year && day > maxDate.day)); 53 | } 54 | 55 | export function timeComponentIsDisabled(min: number | null, max: number | null, component: number): boolean { 56 | return (min !== null && component < min) || (max !== null && component > max); 57 | } 58 | 59 | export function monthDays(year: number, month: number, weekStart: WeekdayNumbers): DateElement[] { 60 | const monthDate = DateTime.local(year, month, 1); 61 | if (!monthDate.isValid) { 62 | return []; 63 | } 64 | const calendarRows = 6; 65 | const calendarSize = 7 * (calendarRows - 1); 66 | 67 | const daysInFirstRow = (7 - monthDate.weekday + weekStart) % 7; 68 | const paddingFront = (7 - daysInFirstRow) % 7; 69 | const daysInMonth = monthDate.daysInMonth!; 70 | const paddingBack = calendarSize - (daysInMonth - daysInFirstRow - (daysInFirstRow ? 0 : 7)); 71 | 72 | const daysInMonthPrevious = monthDate.minus({ month: 1 }).daysInMonth!; 73 | const prevMonth = monthDate.minus({ month: 1 }); 74 | const nextMonth = monthDate.plus({ month: 1 }); 75 | 76 | return [...Array(daysInMonth + paddingFront + paddingBack)] 77 | .map( 78 | (_, index) => { 79 | if (index + 1 <= paddingFront) { 80 | return { 81 | year: prevMonth.year, 82 | month: prevMonth.month, 83 | day: daysInMonthPrevious + (index + 1 - paddingFront), 84 | }; 85 | } 86 | if (index >= paddingFront + daysInMonth) { 87 | return { 88 | year: nextMonth.year, 89 | month: nextMonth.month, 90 | day: index + 1 - (paddingFront + daysInMonth), 91 | }; 92 | } 93 | return { year, month, day: (index + 1 - paddingFront) }; 94 | }, 95 | ); 96 | } 97 | 98 | export function calculateWeekStart(): WeekdayNumbers { 99 | const firstDay = getWeekStartByLocale(Settings.defaultLocale); 100 | 101 | return firstDay || 7; 102 | } 103 | -------------------------------------------------------------------------------- /packages/lib/src/DatetimeCalendar.vue: -------------------------------------------------------------------------------- 1 | 43 | 44 | 105 | 106 | 220 | -------------------------------------------------------------------------------- /packages/lib/src/DatetimeTimePicker.vue: -------------------------------------------------------------------------------- 1 | 49 | 50 | 152 | 153 | 215 | -------------------------------------------------------------------------------- /packages/lib/src/DateTime.spec.ts: -------------------------------------------------------------------------------- 1 | import { mount, shallowMount, VueWrapper } from '@vue/test-utils'; 2 | import { DateTime } from 'luxon'; 3 | import { ref } from 'vue'; 4 | 5 | import DateTimeVue from './DateTime.vue'; 6 | 7 | describe('DateTime', () => { 8 | let wrapper: VueWrapper; 9 | const dateTime = ref(DateTime.fromObject({ year: 2023, month: 9, day: 12 })); 10 | 11 | const defaultProps = { 12 | modelValue: dateTime.value.toISO(), 13 | type: 'datetime', 14 | }; 15 | 16 | beforeEach(() => { 17 | wrapper = mount(DateTimeVue, { props: defaultProps }); 18 | }); 19 | 20 | afterEach(() => { 21 | wrapper.unmount(); 22 | }); 23 | 24 | it('Test if dialog opens on focus', async () => { 25 | expect(wrapper.find('.popup').exists()).toBe(false); 26 | 27 | const input = wrapper.find('input'); 28 | await input.trigger('focus'); 29 | 30 | expect(wrapper.find('.popup').exists()).toBe(true); 31 | }); 32 | 33 | it('Test input event on different types', () => { 34 | const emit = (vueWrapper: VueWrapper) => (vueWrapper.emitted('input')?.[0]?.[0]); 35 | expect(DateTime.fromISO(emit(wrapper) ?? '')).toEqual(dateTime.value); 36 | 37 | const timeWrapper = shallowMount(DateTimeVue, { 38 | props: { 39 | ...defaultProps, 40 | type: 'time', 41 | }, 42 | }); 43 | expect(DateTime.fromISO(emit(timeWrapper) ?? '')).toEqual(dateTime.value); 44 | 45 | const dateWrapper = shallowMount(DateTimeVue, { 46 | props: { 47 | ...defaultProps, 48 | zone: 'UTC-8', 49 | type: 'date', 50 | }, 51 | }); 52 | 53 | expect(DateTime.fromISO(emit(dateWrapper) ?? '')).toEqual(dateTime.value.startOf('day')); 54 | 55 | const fakeWrapper = shallowMount(DateTimeVue, { 56 | props: { 57 | ...defaultProps, 58 | type: 'fakedatainput', 59 | }, 60 | }); 61 | expect(DateTime.fromISO(emit(fakeWrapper) ?? '')).toEqual(dateTime.value); 62 | }); 63 | 64 | it('Test format on input field value', () => { 65 | const inputField = (vueWrapper: VueWrapper) => vueWrapper.find('.vdatetime-input'); 66 | // @ts-ignore 67 | expect(inputField(wrapper).element.value) 68 | .toBe(dateTime.value.setZone('local').toLocaleString(DateTime.DATETIME_MED)); 69 | 70 | const timeWrapper = shallowMount(DateTimeVue, { 71 | props: { 72 | ...defaultProps, 73 | type: 'time', 74 | }, 75 | }); 76 | // @ts-ignore 77 | expect(inputField(timeWrapper).element.value) 78 | .toBe(dateTime.value.setZone('local').toLocaleString(DateTime.TIME_24_SIMPLE)); 79 | 80 | const dateWrapper = shallowMount(DateTimeVue, { 81 | props: { 82 | ...defaultProps, 83 | type: 'date', 84 | }, 85 | }); 86 | // @ts-ignore 87 | expect(inputField(dateWrapper).element.value) 88 | .toBe(dateTime.value.toLocaleString(DateTime.DATE_MED)); 89 | 90 | const formatWrapper = shallowMount(DateTimeVue, { 91 | props: { 92 | ...defaultProps, 93 | format: 'HH:mm', 94 | }, 95 | }); 96 | // @ts-ignore 97 | expect(inputField(formatWrapper).element.value) 98 | .toBe(dateTime.value.setZone('local').toLocaleString(DateTime.TIME_24_SIMPLE)); 99 | }); 100 | 101 | it('Test datetime without a valid datetime', async () => { 102 | const popupDatetime = async (vueWrapper: VueWrapper) => { 103 | const input = vueWrapper.find('input'); 104 | await input.trigger('click'); 105 | const popup = vueWrapper.find('datetime-popup-stub'); 106 | return popup.attributes('datetime') ?? ''; 107 | }; 108 | 109 | const minDatetime = DateTime.local().plus({ hour: 1 }).set({ minute: 27 }); 110 | const maxDatetime = DateTime.local().minus({ hour: 1 }).set({ minute: 59 }); 111 | 112 | const invalidWrapper = shallowMount(DateTimeVue, { 113 | props: { 114 | ...defaultProps, 115 | modelValue: '', 116 | }, 117 | }); 118 | 119 | expect(await popupDatetime(invalidWrapper)).toEqual(DateTime.local().startOf('minute').toISO()); 120 | 121 | const invalidMinTime = shallowMount(DateTimeVue, { 122 | props: { 123 | ...defaultProps, 124 | modelValue: '', 125 | minDatetime: minDatetime.toISO(), 126 | }, 127 | }); 128 | 129 | expect(await popupDatetime(invalidMinTime)).toEqual(minDatetime.startOf('minute').toISO()); 130 | 131 | const invalidMaxTime = shallowMount(DateTimeVue, { 132 | props: { 133 | ...defaultProps, 134 | modelValue: '', 135 | maxDatetime: maxDatetime.toISO(), 136 | }, 137 | }); 138 | 139 | expect(await popupDatetime(invalidMaxTime)).toEqual(maxDatetime.startOf('minute').toISO()); 140 | 141 | const invalidMinuteStep = shallowMount(DateTimeVue, { 142 | props: { 143 | ...defaultProps, 144 | modelValue: '', 145 | maxDatetime: maxDatetime.toISO(), 146 | minuteStep: 5, 147 | }, 148 | }); 149 | 150 | expect(await popupDatetime(invalidMinuteStep)).toBe(maxDatetime.plus({ hour: 1 }).startOf('hour').toISO()); 151 | 152 | const invalidMinuteStep2 = shallowMount(DateTimeVue, { 153 | props: { 154 | ...defaultProps, 155 | modelValue: '', 156 | minDatetime: minDatetime.toISO(), 157 | minuteStep: 5, 158 | }, 159 | }); 160 | 161 | expect(await popupDatetime(invalidMinuteStep2)).toBe(minDatetime.set({ minute: 25 }).startOf('minute').toISO()); 162 | }); 163 | 164 | it('Test closing popup on cancel button', async () => { 165 | await wrapper.find('input').trigger('focus'); 166 | 167 | await wrapper.find('.cancel').trigger('click'); 168 | 169 | expect(wrapper.find('.popup').exists()).toBe(false); 170 | }); 171 | 172 | it('Test pressing confirm should close popup and emit input event', async () => { 173 | await wrapper.find('input').trigger('focus'); 174 | 175 | await wrapper.find('.confirm').trigger('click'); 176 | await wrapper.find('.confirm').trigger('click'); 177 | 178 | expect(wrapper.find('.popup').exists()).toBe(false); 179 | 180 | expect(wrapper.emitted('input')).toHaveLength(2); 181 | }); 182 | 183 | it('Test clicking outside', async () => { 184 | await wrapper.find('input').trigger('focus'); 185 | 186 | await wrapper.find('.vdatetime-overlay').trigger('click'); 187 | 188 | expect(wrapper.find('.popup').exists()).toBe(false); 189 | }); 190 | }); 191 | -------------------------------------------------------------------------------- /packages/lib/src/DateTime.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 225 | 226 | 229 | 230 | 252 | -------------------------------------------------------------------------------- /packages/demo/src/views/DemoApp.vue: -------------------------------------------------------------------------------- 1 | 201 | 202 | 218 | 219 | 222 | 223 | 226 | -------------------------------------------------------------------------------- /packages/lib/src/DatetimePopup.vue: -------------------------------------------------------------------------------- 1 | 56 | 57 | 218 | 219 | 293 | -------------------------------------------------------------------------------- /packages/lib/src/DatetimeTimePicker.spec.ts: -------------------------------------------------------------------------------- 1 | import { shallowMount, VueWrapper } from '@vue/test-utils'; 2 | 3 | import DatetimeTimePicker from './DatetimeTimePicker.vue'; 4 | import type { ChangeEvent } from './namespace'; 5 | 6 | describe('Datetime Time Picker Rendering', () => { 7 | let wrapper: VueWrapper; 8 | const defaultProps = { 9 | hour: 12, 10 | minute: 30, 11 | minTime: '5:00', 12 | maxTime: '23:00', 13 | }; 14 | 15 | beforeEach(() => { 16 | wrapper = shallowMount(DatetimeTimePicker, { props: defaultProps }); 17 | }); 18 | 19 | afterEach(() => { 20 | wrapper.unmount(); 21 | }); 22 | 23 | it('Renders Correct Time', () => { 24 | const selected = wrapper.findAll('.selected'); 25 | expect(selected[0].text()).toBe('12'); 26 | expect(selected[1].text()).toBe('30'); 27 | 28 | let selectedHour = wrapper.find('.list--hour .selected'); 29 | expect(selectedHour.text()).toBe('12'); 30 | 31 | const selectedMinute = wrapper.find('.list--minute .selected'); 32 | expect(selectedMinute.text()).toBe('30'); 33 | 34 | // test for 12hours 35 | const hour12wrapper = shallowMount(DatetimeTimePicker, { 36 | props: { 37 | ...defaultProps, 38 | use12Hour: true, 39 | }, 40 | }); 41 | selectedHour = hour12wrapper.find('.list--hour .selected'); 42 | expect(selectedHour.text()).toBe('12'); 43 | 44 | let selectedSuffix = hour12wrapper.find('.list--suffix .selected'); 45 | expect(selectedSuffix.text()).toBe('pm'); 46 | 47 | const hour12wrapperAm = shallowMount(DatetimeTimePicker, { 48 | props: { 49 | ...defaultProps, 50 | hour: 9, 51 | use12Hour: true, 52 | }, 53 | }); 54 | 55 | selectedHour = hour12wrapperAm.find('.list--hour .selected'); 56 | expect(selectedHour.text()).toBe('09'); 57 | 58 | selectedSuffix = hour12wrapperAm.find('.list--suffix .selected'); 59 | expect(selectedSuffix.text()).toBe('am'); 60 | }); 61 | 62 | it('Correct Number Of Rendered Hours', () => { 63 | let hourOptions = wrapper.findAll('.list--hour .item'); 64 | expect(hourOptions).toHaveLength(24); 65 | 66 | expect(hourOptions[0].text()).toBe('00'); 67 | expect(hourOptions[hourOptions.length - 1].text()).toBe('23'); 68 | 69 | // test for 12hour format as well 70 | const hour12Wrapper = shallowMount(DatetimeTimePicker, { 71 | props: { 72 | ...defaultProps, 73 | use12Hour: true, 74 | }, 75 | }); 76 | 77 | hourOptions = hour12Wrapper.findAll('.list--hour .item'); 78 | expect(hourOptions).toHaveLength(12); 79 | 80 | expect(hourOptions[0].text()).toBe('12'); 81 | expect(hourOptions[hourOptions.length - 1].text()).toBe('11'); 82 | 83 | // test for step configuration 84 | const step2Wrapper = shallowMount(DatetimeTimePicker, { 85 | props: { 86 | ...defaultProps, 87 | hourStep: 2, 88 | }, 89 | }); 90 | 91 | hourOptions = step2Wrapper.findAll('.list--hour .item'); 92 | expect(hourOptions).toHaveLength(12); 93 | 94 | expect(hourOptions[0].text()).toBe('00'); 95 | expect(hourOptions[hourOptions.length - 1].text()).toBe('22'); 96 | 97 | // test step for 12 hour configuration 98 | const step212Wrapper = shallowMount(DatetimeTimePicker, { 99 | props: { 100 | ...defaultProps, 101 | use12Hour: true, 102 | hourStep: 2, 103 | }, 104 | }); 105 | 106 | hourOptions = step212Wrapper.findAll('.list--hour .item'); 107 | expect(hourOptions).toHaveLength(6); 108 | 109 | expect(hourOptions[0].text()).toBe('12'); 110 | expect(hourOptions[hourOptions.length - 1].text()).toBe('10'); 111 | }); 112 | 113 | it('Correct Render Min/Max time', () => { 114 | const nonLimitedTimeWrapper = shallowMount(DatetimeTimePicker, { 115 | props: { 116 | ...defaultProps, 117 | minTime: undefined, 118 | maxTime: undefined, 119 | }, 120 | }); 121 | 122 | const hourOptions = nonLimitedTimeWrapper.findAll('.list--hour .item:not(.disabled)'); 123 | expect(hourOptions).toHaveLength(24); 124 | 125 | let minuteOptions = nonLimitedTimeWrapper.findAll('.list--minute .item:not(.disabled)'); 126 | expect(minuteOptions).toHaveLength(60); 127 | 128 | const limitedMinutesWrapper = shallowMount(DatetimeTimePicker, { 129 | props: { 130 | ...defaultProps, 131 | minTime: '12:00', 132 | maxTime: '12:40', 133 | }, 134 | }); 135 | 136 | minuteOptions = limitedMinutesWrapper.findAll('.list--minute .item:not(.disabled)'); 137 | expect(minuteOptions).toHaveLength(41); 138 | }); 139 | 140 | it('Correct Number Of Rendered Minutes', () => { 141 | let minuteOptions = wrapper.findAll('.list--minute .item'); 142 | expect(minuteOptions).toHaveLength(60); 143 | 144 | expect(minuteOptions[0].text()).toBe('00'); 145 | expect(minuteOptions[minuteOptions.length - 1].text()).toBe('59'); 146 | 147 | // test 12 hours 148 | const hour12Wrapper = shallowMount(DatetimeTimePicker, { 149 | props: { 150 | ...defaultProps, 151 | use12Hour: true, 152 | }, 153 | }); 154 | minuteOptions = hour12Wrapper.findAll('.list--minute .item'); 155 | expect(minuteOptions).toHaveLength(60); 156 | 157 | expect(minuteOptions[0].text()).toBe('00'); 158 | expect(minuteOptions[minuteOptions.length - 1].text()).toBe('59'); 159 | 160 | // test steps 161 | const step2Wrapper = shallowMount(DatetimeTimePicker, { 162 | props: { 163 | ...defaultProps, 164 | minuteStep: 2, 165 | }, 166 | }); 167 | minuteOptions = step2Wrapper.findAll('.list--minute .item'); 168 | expect(minuteOptions).toHaveLength(30); 169 | 170 | expect(minuteOptions[0].text()).toBe('00'); 171 | expect(minuteOptions[minuteOptions.length - 1].text()).toBe('58'); 172 | }); 173 | 174 | it('Clicking on Time Emits Change Event', () => { 175 | const hourOptions = wrapper.findAll('.list--hour .item:not(.disabled)'); 176 | hourOptions.forEach((element, index) => { 177 | element.trigger('click'); 178 | const events = wrapper.emitted('change'); 179 | const event = events?.at(-1)?.[0]; 180 | expect(event?.hour).toBe(index + 5); 181 | }); 182 | 183 | const minuteOptions = wrapper.findAll('.list--minute .item:not(.disabled)'); 184 | minuteOptions.forEach((element, index) => { 185 | element.trigger('click'); 186 | const events = wrapper.emitted('change'); 187 | const event = events?.at(-1)?.[0]; 188 | expect(event?.minute).toBe(index); 189 | }); 190 | }); 191 | 192 | it('Clicking on Unselected Time Suffix Emits Change Event', () => { 193 | const hour12wrapper = shallowMount(DatetimeTimePicker, { 194 | props: { 195 | ...defaultProps, 196 | use12Hour: true, 197 | hour: 10, 198 | }, 199 | }); 200 | 201 | let element = hour12wrapper.find('.list--suffix .item:not(.selected)'); 202 | (() => { 203 | element.trigger('click'); 204 | const events = hour12wrapper.emitted('change'); 205 | const event = events?.at(-1)?.[0]; 206 | expect(event).toEqual({ hour: 22, suffixTouched: true }); 207 | })(); 208 | 209 | const hour12wrapperPm = shallowMount(DatetimeTimePicker, { 210 | props: { 211 | ...defaultProps, 212 | use12Hour: true, 213 | hour: 22, 214 | }, 215 | }); 216 | element = hour12wrapperPm.find('.list--suffix .item:not(.selected)'); 217 | (() => { 218 | element.trigger('click'); 219 | const events = hour12wrapperPm.emitted('change'); 220 | const event = events?.at(-1)?.[0]; 221 | expect(event).toEqual({ hour: 10, suffixTouched: true }); 222 | })(); 223 | }); 224 | 225 | it('Clicking on Selected Time Suffix Does Not Emit Change Event', () => { 226 | const hour12wrapper = shallowMount(DatetimeTimePicker, { 227 | props: { 228 | ...defaultProps, 229 | use12Hour: true, 230 | hour: 10, 231 | }, 232 | }); 233 | 234 | let element = hour12wrapper.find('.list--suffix .item.selected'); 235 | (() => { 236 | element.trigger('click'); 237 | const events = hour12wrapper.emitted('change'); 238 | const event = events?.at(-1)?.[0]; 239 | expect(event).toBeUndefined(); 240 | })(); 241 | 242 | const hour12wrapperPm = shallowMount(DatetimeTimePicker, { 243 | props: { 244 | ...defaultProps, 245 | use12Hour: true, 246 | hour: 22, 247 | }, 248 | }); 249 | element = hour12wrapperPm.find('.list--suffix .item.selected'); 250 | (() => { 251 | element.trigger('click'); 252 | const events = hour12wrapperPm.emitted('change'); 253 | const event = events?.at(-1)?.[0]; 254 | expect(event).toBeUndefined(); 255 | })(); 256 | }); 257 | }); 258 | -------------------------------------------------------------------------------- /packages/lib/src/utils/datetime.spec.ts: -------------------------------------------------------------------------------- 1 | import { DateTime, WeekdayNumbers } from 'luxon'; 2 | import { expectTypeOf } from 'vitest'; 3 | 4 | import { 5 | calculateWeekStart, 6 | datetimeFromISO, 7 | dateIsDisabled, monthDays, 8 | monthIsDisabled, 9 | startOfDay, 10 | timeComponentIsDisabled, validDatetimeRange, 11 | yearIsDisabled, 12 | } from './datetime'; 13 | 14 | describe('Datetime Utilities', () => { 15 | const { year, month, day } = { year: 2023, month: 10, day: 13 }; 16 | const datetimeObject = { year, month, day }; 17 | const datetime = DateTime.fromObject(datetimeObject); 18 | const weekstart = 1; 19 | 20 | it('Datetime From ISO', () => { 21 | expect(datetimeFromISO('')).toBeUndefined(); 22 | // @ts-ignore 23 | expectTypeOf(datetimeFromISO('')).toEqualTypeOf(); 24 | expect(datetimeFromISO('2018-05-12T00:00:00.000Z')).not.toBeUndefined(); 25 | expect(datetimeFromISO('2018-05-12T')).toBeUndefined(); 26 | }); 27 | 28 | it('Start Of Day', () => { 29 | // @ts-ignore 30 | expectTypeOf(startOfDay(datetime)).toEqualTypeOf(); 31 | // @ts-ignore 32 | expectTypeOf(startOfDay(undefined)).toEqualTypeOf(); 33 | // @ts-ignore 34 | expectTypeOf(startOfDay(null)).toEqualTypeOf(); 35 | const tmp = startOfDay(datetime)!.toObject(); 36 | expect({ minute: tmp.minute, seconds: tmp.second, millisecond: tmp.millisecond }) 37 | .toEqual({ minute: 0, seconds: 0, millisecond: 0 }); 38 | }); 39 | 40 | it('Date Is Disabled', () => { 41 | const datetimeBefore = datetime.minus({ day: 1 }); 42 | const datetimeAfter = datetime.plus({ day: 1 }); 43 | 44 | expect(dateIsDisabled(undefined, undefined, year, month, day)).toBe(false); 45 | expect(dateIsDisabled(datetimeBefore, undefined, year, month, day)).toBe(false); 46 | expect(dateIsDisabled(undefined, datetimeAfter, year, month, day)).toBe(false); 47 | expect(dateIsDisabled(datetimeBefore, datetimeAfter, year, month, day)).toBe(false); 48 | 49 | expect(dateIsDisabled(undefined, datetimeBefore, year, month, day)).toBe(true); 50 | expect(dateIsDisabled(datetimeAfter, undefined, year, month, day)).toBe(true); 51 | expect(dateIsDisabled(datetimeAfter, datetimeBefore, year, month, day)).toBe(true); 52 | expect(dateIsDisabled(datetimeBefore, datetimeBefore, year, month, day)).toBe(true); 53 | expect(dateIsDisabled(datetimeAfter, datetimeAfter, year, month, day)).toBe(true); 54 | 55 | expect(dateIsDisabled(datetime.minus({ year: 1 }), undefined, year, month, day)).toBe(false); 56 | expect(dateIsDisabled(undefined, datetime.plus({ year: 1 }), year, month, day)).toBe(false); 57 | 58 | expect(dateIsDisabled(datetime.minus({ month: 1 }), undefined, year, month, day)).toBe(false); 59 | expect(dateIsDisabled(undefined, datetime.plus({ month: 1 }), year, month, day)).toBe(false); 60 | 61 | const dateBefore = DateTime.fromObject({ year: 2023, month: 9, day: 25 }); 62 | const dateAfter = DateTime.fromObject({ year: 2023, month: 10, day: 10 }); 63 | 64 | expect(dateIsDisabled(dateBefore, dateAfter, 2023, 9, 29)).toBe(false); 65 | expect(dateIsDisabled(dateBefore, dateAfter, 2023, 10, 5)).toBe(false); 66 | 67 | expect(dateIsDisabled(dateBefore, dateAfter, 2023, 9, 5)).toBe(true); 68 | expect(dateIsDisabled(dateBefore, dateAfter, 2023, 10, 29)).toBe(true); 69 | }); 70 | 71 | it('Month Is Disabled', () => { 72 | const datetimeBefore = datetime.minus({ month: 1 }); 73 | const datetimeAfter = datetime.plus({ month: 1 }); 74 | 75 | // obvious true statements 76 | expect(monthIsDisabled(undefined, undefined, year, month)).toBe(false); 77 | expect(monthIsDisabled(datetimeBefore, undefined, year, month)).toBe(false); 78 | expect(monthIsDisabled(undefined, datetimeAfter, year, month)).toBe(false); 79 | expect(monthIsDisabled(datetimeBefore, datetimeAfter, year, month)).toBe(false); 80 | 81 | // obvious false 82 | expect(monthIsDisabled(datetimeAfter, undefined, year, month)).toBe(true); 83 | expect(monthIsDisabled(undefined, datetimeBefore, year, month)).toBe(true); 84 | expect(monthIsDisabled(datetimeAfter, datetimeBefore, year, month)).toBe(true); 85 | 86 | // date within the month 87 | const monthBegin = DateTime.fromObject({ ...datetimeObject, day: 1 }); 88 | const monthEnd = DateTime.fromObject({ ...datetimeObject, day: DateTime.utc(year, month).daysInMonth ?? 31 }); 89 | 90 | expect(monthIsDisabled(monthBegin, undefined, year, month)).toBe(false); 91 | expect(monthIsDisabled(undefined, monthBegin, year, month)).toBe(false); 92 | expect(monthIsDisabled(monthEnd, undefined, year, month)).toBe(false); 93 | expect(monthIsDisabled(undefined, monthEnd, year, month)).toBe(false); 94 | expect(monthIsDisabled(monthBegin, monthEnd, year, month)).toBe(false); 95 | expect(monthIsDisabled(monthEnd, monthBegin, year, month)).toBe(true); 96 | 97 | const monthPreviousYear = DateTime.fromObject({ year: 2022, month: 10 }); 98 | const monthNextYear = DateTime.fromObject({ year: 2023, month: 3 }); 99 | 100 | expect(monthIsDisabled(monthPreviousYear, monthNextYear, 2022, 11)).toBe(false); 101 | expect(monthIsDisabled(monthPreviousYear, monthNextYear, 2023, 1)).toBe(false); 102 | 103 | expect(monthIsDisabled(monthPreviousYear, monthNextYear, 2022, 1)).toBe(true); 104 | expect(monthIsDisabled(monthPreviousYear, monthNextYear, 2023, 11)).toBe(true); 105 | }); 106 | 107 | it('Year Is Disabled', () => { 108 | const datetimeBefore = datetime.minus({ year: 1 }); 109 | const datetimeAfter = datetime.plus({ year: 1 }); 110 | 111 | // obvious true statements 112 | expect(yearIsDisabled(undefined, undefined, year)).toBe(false); 113 | expect(yearIsDisabled(datetimeBefore, undefined, year)).toBe(false); 114 | expect(yearIsDisabled(undefined, datetimeAfter, year)).toBe(false); 115 | expect(yearIsDisabled(datetimeBefore, datetimeAfter, year)).toBe(false); 116 | 117 | // obvious false 118 | expect(yearIsDisabled(datetimeAfter, undefined, year)).toBe(true); 119 | expect(yearIsDisabled(undefined, datetimeBefore, year)).toBe(true); 120 | expect(yearIsDisabled(datetimeAfter, datetimeBefore, year)).toBe(true); 121 | 122 | const yearBegin = DateTime.fromObject({ ...datetimeObject, month: 1, day: 1 }); 123 | const yearEnd = DateTime.fromObject({ ...datetimeObject, month: 12, day: 31 }); 124 | expect(yearIsDisabled(yearBegin, undefined, year)).toBe(false); 125 | expect(yearIsDisabled(undefined, yearBegin, year)).toBe(false); 126 | expect(yearIsDisabled(yearEnd, undefined, year)).toBe(false); 127 | expect(yearIsDisabled(undefined, yearEnd, year)).toBe(false); 128 | expect(yearIsDisabled(yearBegin, yearEnd, year)).toBe(false); 129 | expect(yearIsDisabled(yearEnd, yearBegin, year)).toBe(true); 130 | }); 131 | 132 | it('Valid Datetime Range', () => { 133 | const datetimeBefore = datetime.minus({ year: 1 }); 134 | const datetimeAfter = datetime.plus({ year: 1 }); 135 | 136 | expect(validDatetimeRange(undefined, undefined)).toBe(true); 137 | expect(validDatetimeRange(datetimeBefore, undefined)).toBe(true); 138 | expect(validDatetimeRange(undefined, datetimeAfter)).toBe(true); 139 | expect(validDatetimeRange(datetimeBefore, datetimeAfter)).toBe(true); 140 | expect(validDatetimeRange(datetimeAfter, datetimeBefore)).toBe(false); 141 | }); 142 | 143 | it('Time Component Is Disabled', () => { 144 | const component: number = 7; 145 | 146 | const lower: number = component - 1; 147 | const higher: number = component + 1; 148 | 149 | // obvious true 150 | expect(timeComponentIsDisabled(null, null, component)).toBe(false); 151 | expect(timeComponentIsDisabled(lower, null, component)).toBe(false); 152 | expect(timeComponentIsDisabled(null, higher, component)).toBe(false); 153 | expect(timeComponentIsDisabled(lower, higher, component)).toBe(false); 154 | 155 | // obvious false 156 | expect(timeComponentIsDisabled(higher, null, component)).toBe(true); 157 | expect(timeComponentIsDisabled(null, lower, component)).toBe(true); 158 | expect(timeComponentIsDisabled(higher, lower, component)).toBe(true); 159 | }); 160 | 161 | it('Month Days', () => { 162 | // TODO: write in-depth test for this 163 | // @ts-ignore 164 | expectTypeOf(monthDays(year, month, weekstart)).toEqualTypeOf(); 165 | // @ts-ignore 166 | expectTypeOf(monthDays(-1, -1, weekstart)).toEqualTypeOf(); 167 | 168 | expect(monthDays(year, month, weekstart).length).toEqual(42); 169 | expect(monthDays(2023, 5, weekstart).length).toEqual(42); 170 | }); 171 | 172 | it('Calculate Week Start', () => { 173 | // @ts-ignore 174 | expectTypeOf(calculateWeekStart()).toEqualTypeOf(); 175 | expectTypeOf(calculateWeekStart()).toEqualTypeOf(); 176 | expect(calculateWeekStart()).toBeLessThanOrEqual(7); 177 | expect(calculateWeekStart()).toBeGreaterThanOrEqual(1); 178 | }); 179 | }); 180 | -------------------------------------------------------------------------------- /packages/lib/src/DatetimePopup.spec.ts: -------------------------------------------------------------------------------- 1 | import { shallowMount, VueWrapper, enableAutoUnmount, mount } from '@vue/test-utils'; 2 | import { DateTime } from 'luxon'; 3 | 4 | import { DatetimePopup } from './index'; 5 | 6 | describe('Datetime Popup', () => { 7 | let wrapper: VueWrapper; 8 | const defaultProps = { 9 | datetime: DateTime.fromObject({ year: 2023, month: 9, day: 21 }), 10 | type: 'datetime', 11 | }; 12 | 13 | beforeEach(() => { 14 | wrapper = shallowMount(DatetimePopup, { props: defaultProps }); 15 | }); 16 | 17 | enableAutoUnmount(afterEach); 18 | 19 | it('Check flow type rendering correctly', () => { 20 | // flowtype == 'datetime' 21 | expect(wrapper.find('datetime-calendar-stub').exists()).toBe(true); 22 | 23 | expect(wrapper.find('datetime-year-picker-stub').exists()).toBe(false); 24 | expect(wrapper.find('datetime-month-picker-stub').exists()).toBe(false); 25 | expect(wrapper.find('datetime-time-picker-stub').exists()).toBe(false); 26 | 27 | // flowtype == 'date' 28 | const dateWrapper = shallowMount(DatetimePopup, { 29 | props: { 30 | ...defaultProps, 31 | type: 'date', 32 | }, 33 | }); 34 | 35 | expect(dateWrapper.find('datetime-calendar-stub').exists()).toBe(true); 36 | 37 | expect(dateWrapper.find('datetime-year-picker-stub').exists()).toBe(false); 38 | expect(dateWrapper.find('datetime-month-picker-stub').exists()).toBe(false); 39 | expect(dateWrapper.find('datetime-time-picker-stub').exists()).toBe(false); 40 | 41 | // flowtype == 'time' 42 | const timeWrapper = shallowMount(DatetimePopup, { 43 | props: { 44 | ...defaultProps, 45 | type: 'time', 46 | }, 47 | }); 48 | 49 | expect(timeWrapper.find('datetime-time-picker-stub').exists()).toBe(true); 50 | 51 | expect(timeWrapper.find('datetime-calendar-stub').exists()).toBe(false); 52 | expect(timeWrapper.find('datetime-year-picker-stub').exists()).toBe(false); 53 | expect(timeWrapper.find('datetime-month-picker-stub').exists()).toBe(false); 54 | }); 55 | 56 | it('Test flow for each type', async () => { 57 | // datetime -> [date, time, end] 58 | let confirmButton = wrapper.find('.confirm'); 59 | await confirmButton.trigger('click'); 60 | 61 | expect(wrapper.find('datetime-calendar-stub').exists()).toBe(false); 62 | expect(wrapper.find('datetime-time-picker-stub').exists()).toBe(true); 63 | expect(wrapper.find('datetime-year-picker-stub').exists()).toBe(false); 64 | expect(wrapper.find('datetime-month-picker-stub').exists()).toBe(false); 65 | 66 | await confirmButton.trigger('click'); 67 | 68 | expect(wrapper.find('datetime-calendar-stub').exists()).toBe(false); 69 | expect(wrapper.find('datetime-time-picker-stub').exists()).toBe(false); 70 | expect(wrapper.find('datetime-year-picker-stub').exists()).toBe(false); 71 | expect(wrapper.find('datetime-month-picker-stub').exists()).toBe(false); 72 | 73 | expect(wrapper.emitted('confirm')?.[0]).not.toBeUndefined(); 74 | 75 | // date -> [date, end] 76 | const dateWrapper = shallowMount(DatetimePopup, { 77 | props: { 78 | ...defaultProps, 79 | type: 'date', 80 | }, 81 | }); 82 | 83 | confirmButton = dateWrapper.find('.confirm'); 84 | await confirmButton.trigger('click'); 85 | 86 | expect(dateWrapper.find('datetime-calendar-stub').exists()).toBe(false); 87 | expect(dateWrapper.find('datetime-time-picker-stub').exists()).toBe(false); 88 | expect(dateWrapper.find('datetime-year-picker-stub').exists()).toBe(false); 89 | expect(dateWrapper.find('datetime-month-picker-stub').exists()).toBe(false); 90 | 91 | expect(dateWrapper.emitted('confirm')?.[0]).not.toBeUndefined(); 92 | 93 | // time -> [time, end] 94 | const timeWrapper = shallowMount(DatetimePopup, { 95 | props: { 96 | ...defaultProps, 97 | type: 'time', 98 | }, 99 | }); 100 | 101 | confirmButton = timeWrapper.find('.confirm'); 102 | await confirmButton.trigger('click'); 103 | 104 | expect(timeWrapper.find('datetime-calendar-stub').exists()).toBe(false); 105 | expect(timeWrapper.find('datetime-time-picker-stub').exists()).toBe(false); 106 | expect(timeWrapper.find('datetime-year-picker-stub').exists()).toBe(false); 107 | expect(timeWrapper.find('datetime-month-picker-stub').exists()).toBe(false); 108 | 109 | expect(timeWrapper.emitted('confirm')?.[0]).not.toBeUndefined(); 110 | }); 111 | 112 | it('Pressing cancel button should emit cancel event', async () => { 113 | const cancelButton = wrapper.find('.cancel'); 114 | await cancelButton.trigger('click'); 115 | 116 | expect(wrapper.emitted('confirm')?.[0]).toBeUndefined(); 117 | expect(wrapper.emitted('cancel')?.[0]).not.toBeUndefined(); 118 | }); 119 | 120 | it('Clicking on Month should open month picker', async () => { 121 | const monthButton = wrapper.find('.month'); 122 | await monthButton.trigger('click'); 123 | 124 | expect(wrapper.find('datetime-calendar-stub').exists()).toBe(false); 125 | expect(wrapper.find('datetime-time-picker-stub').exists()).toBe(false); 126 | expect(wrapper.find('datetime-year-picker-stub').exists()).toBe(false); 127 | expect(wrapper.find('datetime-month-picker-stub').exists()).toBe(true); 128 | }); 129 | 130 | it('Clicking on Year should open month picker', async () => { 131 | const yearButton = wrapper.find('.year'); 132 | await yearButton.trigger('click'); 133 | 134 | expect(wrapper.find('datetime-calendar-stub').exists()).toBe(false); 135 | expect(wrapper.find('datetime-time-picker-stub').exists()).toBe(false); 136 | expect(wrapper.find('datetime-year-picker-stub').exists()).toBe(true); 137 | expect(wrapper.find('datetime-month-picker-stub').exists()).toBe(false); 138 | }); 139 | 140 | it('Boundaries for datetime', () => { 141 | const mindate = DateTime.fromObject({ year: 2023, month: 9, day: 21, hour: 21, minute: 20 }); 142 | const maxdate = DateTime.fromObject({ year: 2023, month: 9, day: 21, hour: 23, minute: 20 }); 143 | const dateWrapper = shallowMount(DatetimePopup, { 144 | props: { 145 | ...defaultProps, 146 | minDatetime: mindate, 147 | maxDatetime: maxdate, 148 | }, 149 | }); 150 | 151 | const calendar = dateWrapper.find('datetime-calendar-stub'); 152 | expect(calendar.attributes('mindate')).toBe(mindate.toISO()); 153 | expect(calendar.attributes('maxdate')).toBe(maxdate.toISO()); 154 | 155 | const timeWrapper = shallowMount(DatetimePopup, { 156 | props: { 157 | ...defaultProps, 158 | type: 'time', 159 | minDatetime: mindate, 160 | maxDatetime: maxdate, 161 | }, 162 | }); 163 | 164 | const timePicker = timeWrapper.find('datetime-time-picker-stub'); 165 | expect(timePicker.attributes('mintime')).toBe(mindate.toFormat('HH:mm')); 166 | expect(timePicker.attributes('maxtime')).toBe(maxdate.toFormat('HH:mm')); 167 | }); 168 | 169 | it('Change Year', async () => { 170 | const mountWrapper = mount(DatetimePopup, { props: { ...defaultProps, auto: true } }); 171 | const yearButton = mountWrapper.find('.year'); 172 | await yearButton.trigger('click'); 173 | 174 | const yearOption = mountWrapper.find('.list .item'); 175 | await yearOption.trigger('click'); 176 | 177 | expect(yearButton.text()).toBe(yearOption.text()); 178 | }); 179 | 180 | it('Change Month', async () => { 181 | const mountWrapper = mount(DatetimePopup, { props: { ...defaultProps, auto: true } }); 182 | const monthButton = mountWrapper.find('.month'); 183 | await monthButton.trigger('click'); 184 | 185 | const monthOption = mountWrapper.find('.list .item'); 186 | await monthOption.trigger('click'); 187 | 188 | expect(monthButton.text()).toBe(`${monthOption.text()} 21`); 189 | }); 190 | 191 | it('Change Date', async () => { 192 | const mountWrapper = mount(DatetimePopup, { props: { ...defaultProps, auto: true } }); 193 | 194 | const dateOption = mountWrapper.find('.month__day:not(.disabled)'); 195 | await dateOption.trigger('click'); 196 | 197 | const monthButton = mountWrapper.find('.month'); 198 | expect(monthButton.text()).toEqual(`September ${dateOption.text()}`); 199 | }); 200 | 201 | it('Change Time', async () => { 202 | const mountWrapper = mount(DatetimePopup, { 203 | props: { 204 | ...defaultProps, 205 | auto: true, 206 | type: 'time', 207 | use12Hour: true, 208 | }, 209 | }); 210 | 211 | const hourElement = mountWrapper.find('.list--hour .item:not(.selected)'); 212 | const minuteElement = mountWrapper.find('.list--minute .item:not(.selected)'); 213 | const suffixElement = mountWrapper.find('.list--suffix .item:not(.selected)'); 214 | 215 | await hourElement.trigger('click'); 216 | expect(mountWrapper.find('.list--hour .item.selected').text()).toBe(hourElement.text()); 217 | 218 | await minuteElement.trigger('click'); 219 | expect(mountWrapper.find('.list--minute .item.selected').text()).toBe(minuteElement.text()); 220 | 221 | await suffixElement.trigger('click'); 222 | expect(mountWrapper.find('.list--suffix .item.selected').text()).toBe(suffixElement.text()); 223 | 224 | expect(mountWrapper.emitted('change')?.[0]).toBeUndefined(); 225 | }); 226 | }); 227 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### Changelog 2 | 3 | All notable changes to this project will be documented in this file. Dates are displayed in UTC. 4 | 5 | Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). 6 | 7 | #### [v1.0.3](https://github.com/velis74/vue-datetime/compare/v1.0.2...v1.0.3) 8 | 9 | > 7 March 2023 10 | 11 | - Add configuration for np to stop nagging about default branch [`4ec466a`](https://github.com/velis74/vue-datetime/commit/4ec466ad2a626831a0c0b7b0f2fdb1f8721dcce0) 12 | - Fix files setting to publish the actual build files [`79e0d36`](https://github.com/velis74/vue-datetime/commit/79e0d3626618c7967f5f433e4f265b45c5bb2e83) 13 | 14 | #### [v1.0.2](https://github.com/velis74/vue-datetime/compare/v1.0.1...v1.0.2) 15 | 16 | > 7 March 2023 17 | 18 | - change repository URLs [`e645a17`](https://github.com/velis74/vue-datetime/commit/e645a17b62ac5fac34cbbad97262d3c07e5a3a66) 19 | 20 | #### [v1.0.1](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.13...v1.0.1) 21 | 22 | > 7 March 2023 23 | 24 | - Remove unneeded files [`0d13c28`](https://github.com/velis74/vue-datetime/commit/0d13c28ee03a304f2973aa226d26fa2d2fdd3a72) 25 | - Use datetime plugin in demo app [`2f3ade7`](https://github.com/velis74/vue-datetime/commit/2f3ade715e7e0fb32aac6188d77498365bcc8bd1) 26 | - Remove stale building utils [`5af5d47`](https://github.com/velis74/vue-datetime/commit/5af5d47fd3bb63747c420dd7cbb16c184b31c93a) 27 | - Introduce vite [`3a23c90`](https://github.com/velis74/vue-datetime/commit/3a23c90ed9209f3f17e90a539aeb4e23f84ebba7) 28 | - Rework Popup to composition API, ts and velis styling [`ab22b91`](https://github.com/velis74/vue-datetime/commit/ab22b91e79e4a688c5538e52330dcefb864a3f7e) 29 | - Rework DateTime to composition API, ts and velis styling [`4b0d05b`](https://github.com/velis74/vue-datetime/commit/4b0d05be51c962eedbe45637bea306c6c751febd) 30 | - Rework time picker to composition API, ts and velis styling [`eed9b6e`](https://github.com/velis74/vue-datetime/commit/eed9b6e2515636e4f8750f23fcaf81a80f3eac64) 31 | - Refactor plugin to vue3 syntax [`af257cb`](https://github.com/velis74/vue-datetime/commit/af257cb822b9fde3956c17fac5deaaf53ff574b9) 32 | - Fix veu style into plain css [`bcf1a83`](https://github.com/velis74/vue-datetime/commit/bcf1a8333050a61e8542e5b41d9ac62d4fbc4bf4) 33 | - Rework DatetimeCalendar to composition API, ts and velis eslint rules [`49c1f87`](https://github.com/velis74/vue-datetime/commit/49c1f8721f3a32d3f9d407fd0893bafab27f174d) 34 | - Cleanup package.json [`b35563c`](https://github.com/velis74/vue-datetime/commit/b35563ca0a80563f260f6e031fcab1daec181686) 35 | - Fix example page [`c5a97d9`](https://github.com/velis74/vue-datetime/commit/c5a97d93dc685cd0aa6217cecc7e03fb6abbd518) 36 | - Rework YearPicker to composition API, ts and velis styling [`10096f7`](https://github.com/velis74/vue-datetime/commit/10096f71623f60fb36dd9ad8cb4e3b3fffbe2f6f) 37 | - Rework MonthPicker to composition API, ts and velis styling [`6551465`](https://github.com/velis74/vue-datetime/commit/65514652d875f7e8df6493e8155f9926dbc0770c) 38 | - Add packaging utilities [`38f8c22`](https://github.com/velis74/vue-datetime/commit/38f8c227546456fd367081f35e72778d1f68a681) 39 | - Fix time picker, DRY scrolling concept [`52eae4f`](https://github.com/velis74/vue-datetime/commit/52eae4fea9f8c01dca28e30292c723805331d57b) 40 | - Fix v-model reactivity [`ebab314`](https://github.com/velis74/vue-datetime/commit/ebab3141d230679d61b9b86a645a14930324ddb4) 41 | - Prepare package building utilities [`21e7d78`](https://github.com/velis74/vue-datetime/commit/21e7d785fbb5b162fc141b73f327cb7ce8757cd0) 42 | - Remove auto moving on 12 hour time picker when touching all 3 params [`5534287`](https://github.com/velis74/vue-datetime/commit/5534287f4f3675d7cfe9cc09ff8eecdd6fa7bd7c) 43 | - Added new props for backdrop-click [`8af46c1`](https://github.com/velis74/vue-datetime/commit/8af46c10daaf88a7dd6ae3840ec6d164a3640008) 44 | - preparing to publish [`9d33af5`](https://github.com/velis74/vue-datetime/commit/9d33af5e22e83851a2b4ee40362055d5280c7246) 45 | - Added new props for and hide backdrop [`d6770a1`](https://github.com/velis74/vue-datetime/commit/d6770a126fbf7c8c3e4c0aa100e97620e1cfde9d) 46 | - Update gitignore [`40ceddf`](https://github.com/velis74/vue-datetime/commit/40ceddfe7b8cf43f72f5ad1851bb927d6873637d) 47 | - Fix month picker [`4a5a59b`](https://github.com/velis74/vue-datetime/commit/4a5a59b25a48adddffb1d2514e6323ec57dc323b) 48 | - Fix last commit bug [`15dd190`](https://github.com/velis74/vue-datetime/commit/15dd190663feb226c0a1ff2b886d741d14badf87) 49 | - Fix build warnings [`324725f`](https://github.com/velis74/vue-datetime/commit/324725fbad087114e61e3aebc3c10c366dc21653) 50 | - Add unmaintained notice [`1286b6c`](https://github.com/velis74/vue-datetime/commit/1286b6c9d3b4dc37d64b529dcc9f5adda050cace) 51 | 52 | #### [v1.0.0-beta.13](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.12...v1.0.0-beta.13) 53 | 54 | > 1 May 2020 55 | 56 | - Revert `rollup-plugin-vue` update. It doesn't output the same files. We should work on it deeper. [`91818e5`](https://github.com/velis74/vue-datetime/commit/91818e5650cd9377976e1f56c93b6ae810cf6601) 57 | 58 | #### [v1.0.0-beta.12](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.11...v1.0.0-beta.12) 59 | 60 | > 1 May 2020 61 | 62 | - Readme - register component when using CDN [`#193`](https://github.com/velis74/vue-datetime/pull/193) 63 | - Update `yarn.lock` [`ddde993`](https://github.com/velis74/vue-datetime/commit/ddde9938ee0d9cea4fc8075ae23f40ee29ec2e6f) 64 | - Fix max-datetime when time is midnight. Fixes: #215. [`599faf8`](https://github.com/velis74/vue-datetime/commit/599faf8a3f603aebf245452bd965710908cf32f7) 65 | - Don't add the `id` attribute when it is empty. Fixes: #202. [`d9f45b7`](https://github.com/velis74/vue-datetime/commit/d9f45b7261540ee4ab0302cf19330a9a7049d339) 66 | - Fix travis config [`b8084aa`](https://github.com/velis74/vue-datetime/commit/b8084aab6872d4b638f8a3788af7288ea4e030c7) 67 | - Update readme [`de01b03`](https://github.com/velis74/vue-datetime/commit/de01b0370c97f009873a2f2b935c0d18943eb7b3) 68 | - FIX: Update dependency version of the rollup-plugin-vue since the latest 2.x is not compatible with newer vue stack (see https://github.com/vuejs/rollup-plugin-vue/issues/273) [`77f1826`](https://github.com/velis74/vue-datetime/commit/77f1826522bfad27cbb943b9255d7ba8fca3dcbc) 69 | 70 | #### [v1.0.0-beta.11](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.10...v1.0.0-beta.11) 71 | 72 | > 13 November 2019 73 | 74 | - add curly brackets export name [`#178`](https://github.com/velis74/vue-datetime/pull/178) 75 | - Add type=time to the time example [`#172`](https://github.com/velis74/vue-datetime/pull/172) 76 | - Update util.js [`#164`](https://github.com/velis74/vue-datetime/pull/164) 77 | - improve pickers scrolling experience on mobile devices [`#162`](https://github.com/velis74/vue-datetime/pull/162) 78 | - added a check to see if yearList ref exists [`#131`](https://github.com/velis74/vue-datetime/pull/131) 79 | - replaced usage of Array.fill to work on old versions on Chrome [`#129`](https://github.com/velis74/vue-datetime/pull/129) 80 | - Fix min/max dates when picker zone isn't UTC [`0576c01`](https://github.com/velis74/vue-datetime/commit/0576c015c4b0906081ea1218a278f8af34fec13c) 81 | - Expose the popup. [`ad7d42f`](https://github.com/velis74/vue-datetime/commit/ad7d42fb2f64d8725465cfd2b91eba22a534000d) 82 | - Added height to month selection arrows. [`55d3ac4`](https://github.com/velis74/vue-datetime/commit/55d3ac432ece6a965a52567eabedef65e9dc2038) 83 | 84 | #### [v1.0.0-beta.10](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.9...v1.0.0-beta.10) 85 | 86 | > 13 January 2019 87 | 88 | - Add title property. Based on #118 [`0da317c`](https://github.com/velis74/vue-datetime/commit/0da317c4be5ef8c3c21642d0db5bcd17f9d27840) 89 | - Set `line-height` for popup [`04db82b`](https://github.com/velis74/vue-datetime/commit/04db82bc12753b9a60ce3b8a2ff36bc31c6e9c43) 90 | - Remove 0.x notice [`3ba3ea8`](https://github.com/velis74/vue-datetime/commit/3ba3ea8df943e239c927a4fb2ea38b39f2605c89) 91 | 92 | #### [v1.0.0-beta.9](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.8...v1.0.0-beta.9) 93 | 94 | > 12 January 2019 95 | 96 | - Added new custom slots for Buttons [`#97`](https://github.com/velis74/vue-datetime/pull/97) 97 | - fix: docs typo [`#99`](https://github.com/velis74/vue-datetime/pull/99) 98 | - Update `yarn.lock` [`24830ab`](https://github.com/velis74/vue-datetime/commit/24830ab587044fe34162054947af796cb5eaeed0) 99 | - months selector [`5e093d5`](https://github.com/velis74/vue-datetime/commit/5e093d5f6539f64914894498208d1cc202fd18db) 100 | - specs for DatetimeMonthsPicker [`38f96d7`](https://github.com/velis74/vue-datetime/commit/38f96d74f90feaa7368326f010d8b4a34ef04928) 101 | - Add property to customize the flow [`408720a`](https://github.com/velis74/vue-datetime/commit/408720a400956d8ea4fd1e5df63f61b599368160) 102 | - Update readme [`1f5accd`](https://github.com/velis74/vue-datetime/commit/1f5accd58a19cbab64bc0adceaf4aa28ccb3ea2b) 103 | - Revert split date for being compatible with all locales. So, month picker will be shown when clicking on the date. [`7892362`](https://github.com/velis74/vue-datetime/commit/78923624c1e1c97a07aae0e201b1e32a38f75206) 104 | - Add `input-style` property and accept `Object` and `Array` besides to `String` for the property `input-class`. [`e5653b5`](https://github.com/velis74/vue-datetime/commit/e5653b5cf7715b44530a9171880ebd53b4247b15) 105 | - Update readme [`0b79ce9`](https://github.com/velis74/vue-datetime/commit/0b79ce95f21d99ff7c8c684b7f1d3a7bf92332d6) 106 | - Fix disabled months. Month could be enabled even if it first and last day is disabled. [`26493f4`](https://github.com/velis74/vue-datetime/commit/26493f44b323935690556c225b6e6ddd30418f53) 107 | - Add `month` to flow [`84589b8`](https://github.com/velis74/vue-datetime/commit/84589b864c185e904458c8597f64cf10ceb22df3) 108 | - Code style [`8a2a0bb`](https://github.com/velis74/vue-datetime/commit/8a2a0bbaf11cd25783305595d085ece5b6773b76) 109 | - Update DatetimePopup.vue [`aa89e7f`](https://github.com/velis74/vue-datetime/commit/aa89e7fa3589470d098366b218effe0b9bcca02d) 110 | - Set `inheritAttrs` to prevent apply not recognized props to the root element. [`a1ff9ee`](https://github.com/velis74/vue-datetime/commit/a1ff9ee8e0f64409865856b51baa378c892f0f2e) 111 | - Set cursor pointer to header date [`1eb7125`](https://github.com/velis74/vue-datetime/commit/1eb7125373d1fa7dfdf2775631db911d5440120c) 112 | - Fix demo [`395f9db`](https://github.com/velis74/vue-datetime/commit/395f9dbdad4f4b8180e44eaf358c52aef5a3a899) 113 | - Update DatetimePopup.vue [`b80f55b`](https://github.com/velis74/vue-datetime/commit/b80f55bf5c49918d821c9349738d3a7d103c5222) 114 | - fix disabling [`dbefc2f`](https://github.com/velis74/vue-datetime/commit/dbefc2f009280f15d9c2a096208fd0f689aa817d) 115 | - fix comma-spacing [`9a330e0`](https://github.com/velis74/vue-datetime/commit/9a330e03af02308e264be739151b94d127c3d474) 116 | - fix comma-dangle [`68c70c2`](https://github.com/velis74/vue-datetime/commit/68c70c229e18dabe818bbe75f544ca2274496b48) 117 | - fix comma-spacing [`44c69b8`](https://github.com/velis74/vue-datetime/commit/44c69b83a204296fb1dd30417cfdd224d61caf1a) 118 | 119 | #### [v1.0.0-beta.8](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.7...v1.0.0-beta.8) 120 | 121 | > 14 October 2018 122 | 123 | - Fix min/max [`0466724`](https://github.com/velis74/vue-datetime/commit/0466724360d90083cede24c940711691d7a4fd68) 124 | - Fix code style [`caa4cd2`](https://github.com/velis74/vue-datetime/commit/caa4cd2d7d56a9ab2e2634cede7d14635be20d6d) 125 | - Fix min/max + [`bc28704`](https://github.com/velis74/vue-datetime/commit/bc28704958199177cc63864d669029a8a83d04e8) 126 | 127 | #### [v1.0.0-beta.7](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.6...v1.0.0-beta.7) 128 | 129 | > 13 October 2018 130 | 131 | - Tweak time picker [`3068f46`](https://github.com/velis74/vue-datetime/commit/3068f46c3ab3dfb42e312b0200d26916a6429129) 132 | - time only spec [`1d2454c`](https://github.com/velis74/vue-datetime/commit/1d2454c553375e7c3193bfa9cfa6639c2e2feb03) 133 | - Add tests [`00a2603`](https://github.com/velis74/vue-datetime/commit/00a2603d9695cc1b85588618b2b6c324c5af42a6) 134 | - Update tests [`ae5ef11`](https://github.com/velis74/vue-datetime/commit/ae5ef118cc408c9788a6d9d3ddef35f51a7c5776) 135 | - Added tests [`84f2b04`](https://github.com/velis74/vue-datetime/commit/84f2b041d578b3a212f8314898f625cfcdb8ffd4) 136 | - Disable invalid year in yearpicker [`76fd1d9`](https://github.com/velis74/vue-datetime/commit/76fd1d99f747032b150e76a5eff67d9807a65d6a) 137 | - Respect min date on default selection [`f8e40ea`](https://github.com/velis74/vue-datetime/commit/f8e40ead674b7d52a6e9dc7c75b221bd27daf23f) 138 | - Added support for named slots [`13ad825`](https://github.com/velis74/vue-datetime/commit/13ad825dd980dfe70abc723e740ca1dde09d0552) 139 | - added setting value via hidden input [`56eb53e`](https://github.com/velis74/vue-datetime/commit/56eb53eeac48d2df579ee07f622e94af3a942985) 140 | - time support [`35a0a13`](https://github.com/velis74/vue-datetime/commit/35a0a1377cea97e3eeb2e5477bb25b14b244941c) 141 | - Fix code style [`87f650f`](https://github.com/velis74/vue-datetime/commit/87f650f72130d4f4c6ca2b51342a49010de2dbcd) 142 | - fix specs and dupe headers [`077e82a`](https://github.com/velis74/vue-datetime/commit/077e82af109755da8f204bd741c1ae9ebe385aa4) 143 | - Simplify test [`93f08e2`](https://github.com/velis74/vue-datetime/commit/93f08e2796a4563009dbdf32a06d730efe5d3d87) 144 | - Fix datetime popup display bug when using UTC zone [`598253e`](https://github.com/velis74/vue-datetime/commit/598253e48c8f7e0b8ae96a7d7fe96c102ae5cc4a) 145 | - Fix case [`fc4a5fb`](https://github.com/velis74/vue-datetime/commit/fc4a5fb76b50c6b802c92b113d763794d43261db) 146 | - Fix min/max calendar test [`fb48c1c`](https://github.com/velis74/vue-datetime/commit/fb48c1c6226d6ecabccb9974bad9aa495f5b6cd7) 147 | - tweaks [`2b8ebed`](https://github.com/velis74/vue-datetime/commit/2b8ebed08764ba39099212b63b4a532f2785acd6) 148 | - Removed forgotten comments :( [`bc583bf`](https://github.com/velis74/vue-datetime/commit/bc583bf2556feac6f8e0da80ab73f1ba4bc95b07) 149 | 150 | #### [v1.0.0-beta.6](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.5...v1.0.0-beta.6) 151 | 152 | > 9 July 2018 153 | 154 | - Add empty days at the end of the month to complete the week [`#72`](https://github.com/velis74/vue-datetime/pull/72) 155 | - Merge branch 'v1.x' of https://github.com/coreycoburn/vue-datetime into coreycoburn-v1.x [`#56`](https://github.com/velis74/vue-datetime/issues/56) 156 | - Add test `should pass datetime to popup` [`9a22b1e`](https://github.com/velis74/vue-datetime/commit/9a22b1e4c18175d24ea9961994a877bbd9e1dafb) 157 | - Add `input-id` parameter to avoid id collisions [`d3d9797`](https://github.com/velis74/vue-datetime/commit/d3d979771b5d51b5c0f961a758bb7eef04597107) 158 | - Simplify roundMinute code [`3e28c20`](https://github.com/velis74/vue-datetime/commit/3e28c2064d1cbe01dbc5ee1986bdacf4eebac6ed) 159 | - Remove seconds and milliseconds when new date is created [`4895a21`](https://github.com/velis74/vue-datetime/commit/4895a2189717aa526a33c0b99d7d779a4212e8ff) 160 | 161 | #### [v1.0.0-beta.5](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.4...v1.0.0-beta.5) 162 | 163 | > 8 July 2018 164 | 165 | - Add close event [`5fe6a20`](https://github.com/velis74/vue-datetime/commit/5fe6a20f31d5c29190e0c4ef998a9e50f0d2e7b6) 166 | - Update luxon to v1.x [`06783cf`](https://github.com/velis74/vue-datetime/commit/06783cf1716d3eda92c820f0da4d880389199aa7) 167 | - Fix test [`2d93a6e`](https://github.com/velis74/vue-datetime/commit/2d93a6e129847b652c20557e2950a539f1a37f6b) 168 | 169 | #### [v1.0.0-beta.4](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.3...v1.0.0-beta.4) 170 | 171 | > 8 July 2018 172 | 173 | - apply default rounded time when using minute step - resolves #56 [`#56`](https://github.com/velis74/vue-datetime/issues/56) 174 | - Generate hidden input with raw value when name is passed [`32f8744`](https://github.com/velis74/vue-datetime/commit/32f87444285396152f04fc2cc4b10dce31c437a3) 175 | - macro tokens are supported. [`5db1a70`](https://github.com/velis74/vue-datetime/commit/5db1a70b532476e1481123a792bf3dd4ffd39844) 176 | - Add test for macro tokens format [`d995e02`](https://github.com/velis74/vue-datetime/commit/d995e02a9a9c86915a25ed83993f286b3fdc1a1c) 177 | - Fix value formatting with `type=date` and specified time zone [`522b19d`](https://github.com/velis74/vue-datetime/commit/522b19d5c3780b26a1158dd794c249eb51a75dd8) 178 | - Rename `name` attribute by `hidden-name` [`f06fc41`](https://github.com/velis74/vue-datetime/commit/f06fc41ff4b4377793f6541c9ca0af63e2359e91) 179 | - Update readme [`4bcbeef`](https://github.com/velis74/vue-datetime/commit/4bcbeef72201ea899903ec4eb9d59ec75d0bad1b) 180 | - Fix time zone for macro tokens format [`f868eb6`](https://github.com/velis74/vue-datetime/commit/f868eb636472bdf059d832b95cf71dc7a9559f66) 181 | - fix format describe [`c2a3456`](https://github.com/velis74/vue-datetime/commit/c2a34563d7b8b3015dd4437d5f76d1473f87ee89) 182 | - fix format describe [`5f44166`](https://github.com/velis74/vue-datetime/commit/5f441666159a1c98cf65b59ec1fe749e14af173c) 183 | - Macro tokens are supported. [`74deb7d`](https://github.com/velis74/vue-datetime/commit/74deb7dc264ff7342e6595ebc1d02159208d8b72) 184 | 185 | #### [v1.0.0-beta.3](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.2...v1.0.0-beta.3) 186 | 187 | > 3 February 2018 188 | 189 | - Add 12/24 hour format option to the time picker. [`#39`](https://github.com/velis74/vue-datetime/pull/39) 190 | - Update issue template [`4c5de6d`](https://github.com/velis74/vue-datetime/commit/4c5de6d79a8d56f9ee41fef5001035bcf7ce446e) 191 | - Fix demo example code [`2a5944f`](https://github.com/velis74/vue-datetime/commit/2a5944f4fd1f0393147367ef9e80477529e7d2bd) 192 | 193 | #### [v1.0.0-beta.2](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.1...v1.0.0-beta.2) 194 | 195 | > 23 January 2018 196 | 197 | - Add `week-start` parameter [`6cb9279`](https://github.com/velis74/vue-datetime/commit/6cb92797ec9140b02adb5566bdd9dfd5b4869b0c) 198 | - Update demo [`057f87a`](https://github.com/velis74/vue-datetime/commit/057f87a13d66890df4cc967134f193147acd53ea) 199 | - Fix issue with value time zone [`035d4da`](https://github.com/velis74/vue-datetime/commit/035d4daeb7d6bd8d051f97458c68707941c9870b) 200 | - Refactoring calendar new date [`d82d09c`](https://github.com/velis74/vue-datetime/commit/d82d09c82cabb90dda2d7fc876f106edc8c2af5f) 201 | - Rename `date` by `datetime` in `Datetime.vue` [`296f2c0`](https://github.com/velis74/vue-datetime/commit/296f2c01b92e14dd628e5d667963cd79d1f63705) 202 | - Refactoring [`7d40f6f`](https://github.com/velis74/vue-datetime/commit/7d40f6fd4d55e1b37b9fa2f4332b758b464f93f5) 203 | - Rename and improve `clearTime` util [`ccd80f5`](https://github.com/velis74/vue-datetime/commit/ccd80f5ed1f7453993fc11e441b941c13d3c312d) 204 | - Fix demo webpack [`579096d`](https://github.com/velis74/vue-datetime/commit/579096ddb528e6a7db4c2ad157a13995f5c9a775) 205 | - Add `luxon` in rollup globals config [`46551bf`](https://github.com/velis74/vue-datetime/commit/46551bfb6680605c24f9731896224977af378801) 206 | - Add demo link to readme [`44c667f`](https://github.com/velis74/vue-datetime/commit/44c667fcd9ee5927581f886902ae438488567296) 207 | - Remove auto-changelog limit [`f972692`](https://github.com/velis74/vue-datetime/commit/f9726929820e3666a9d968c080277c0e0673c0a1) 208 | 209 | #### [v1.0.0-beta.1](https://github.com/velis74/vue-datetime/compare/v1.0.0-alpha.8...v1.0.0-beta.1) 210 | 211 | > 19 January 2018 212 | 213 | - Cancel popup on key down ESC or TAB [`47c8fca`](https://github.com/velis74/vue-datetime/commit/47c8fcaf21bf53779f6549bf955ba27baddefd0a) 214 | - Close popup on press ESC key [`072063f`](https://github.com/velis74/vue-datetime/commit/072063fbab008a1d9c0081b5418a385b40de3623) 215 | - Continue or confirm popup on key down ENTER [`ff281ca`](https://github.com/velis74/vue-datetime/commit/ff281cab340bc34e2bd7098f72a3ac9ef912aace) 216 | - Fix auto on select time [`69edaaa`](https://github.com/velis74/vue-datetime/commit/69edaaa3403a664779c026b72a7b1beec06e115c) 217 | - On open popup blur input [`5155ac7`](https://github.com/velis74/vue-datetime/commit/5155ac7651922bab7a245886df1cafc81d4d1f3a) 218 | 219 | #### [v1.0.0-alpha.8](https://github.com/velis74/vue-datetime/compare/v1.0.0-alpha.7...v1.0.0-alpha.8) 220 | 221 | > 18 January 2018 222 | 223 | - Value will be an empty string instead of null when the date is empty or invalid because value type is a string. [`3fa3463`](https://github.com/velis74/vue-datetime/commit/3fa346337cc6266b532c4373142429431fe9972e) 224 | - Update luxon peer dependency version [`2dd13b2`](https://github.com/velis74/vue-datetime/commit/2dd13b2f8f445c1994d1e4afddedb31006c4417b) 225 | 226 | #### [v1.0.0-alpha.7](https://github.com/velis74/vue-datetime/compare/v1.0.0-alpha.6...v1.0.0-alpha.7) 227 | 228 | > 18 January 2018 229 | 230 | - Watch value changes [`d58b910`](https://github.com/velis74/vue-datetime/commit/d58b9109197fcef0334c783130df002760270bd7) 231 | - Update readme and issue template [`8adff3d`](https://github.com/velis74/vue-datetime/commit/8adff3df24f009048ae0d8beb07b78ef14d1a5f2) 232 | - Ignore all vue devtools globals in mocha [`7daee98`](https://github.com/velis74/vue-datetime/commit/7daee98d505f683ae7d8cd31035676ab5b03097b) 233 | - Update issue template [`b525ff6`](https://github.com/velis74/vue-datetime/commit/b525ff62f2ae855eb4a9e5ccda96972821b06b59) 234 | 235 | #### [v1.0.0-alpha.6](https://github.com/velis74/vue-datetime/compare/v1.0.0-alpha.5...v1.0.0-alpha.6) 236 | 237 | > 16 January 2018 238 | 239 | - Add `auto` property [`8d6cec3`](https://github.com/velis74/vue-datetime/commit/8d6cec3a45e8ce26e7eb0a5ffef7a410167b3809) 240 | - Update readme [`cef7afe`](https://github.com/velis74/vue-datetime/commit/cef7afe4a4ef7db80209bf48f5dff4bfddbc8254) 241 | - Fix local time zone test [`e35cec1`](https://github.com/velis74/vue-datetime/commit/e35cec180762fd15adf359a31eb47eac07a13970) 242 | - Update luxon to v0.3.1 [`635be46`](https://github.com/velis74/vue-datetime/commit/635be467a24f760a76e46414660d306f328ea671) 243 | - Add travis config [`f0289e9`](https://github.com/velis74/vue-datetime/commit/f0289e96278ddfa2997be8f2bd7812a6784b77f5) 244 | - Fix Datetime types tests [`0e6663c`](https://github.com/velis74/vue-datetime/commit/0e6663c07c9b40e21646e32dee16982a9a8cd8d5) 245 | - Add shields to readme [`a0af5e3`](https://github.com/velis74/vue-datetime/commit/a0af5e3ebe242c217bd35b313f3af0839ddd7444) 246 | - Fix license and coverage link [`109a5be`](https://github.com/velis74/vue-datetime/commit/109a5be52020d7d49dd376bd6a6b36af53470d9e) 247 | - Fix shields [`9356b3f`](https://github.com/velis74/vue-datetime/commit/9356b3f1b29f14310dd739d12fa9bf181b0339af) 248 | - Add `codecov` to travis configuration [`122a301`](https://github.com/velis74/vue-datetime/commit/122a3010b86cfec4b9abd243b40297c63e229dfd) 249 | - Add demo gif [`e528f9e`](https://github.com/velis74/vue-datetime/commit/e528f9e3f9c90a0627326cec293e63fa78e01b16) 250 | 251 | #### [v1.0.0-alpha.5](https://github.com/velis74/vue-datetime/compare/v1.0.0-alpha.4...v1.0.0-alpha.5) 252 | 253 | > 15 January 2018 254 | 255 | - Fix popup time zone [`787752f`](https://github.com/velis74/vue-datetime/commit/787752f1f48f5a52a55e6440ed86a844d0a49870) 256 | - Add `input-class` property [`b94c355`](https://github.com/velis74/vue-datetime/commit/b94c3554731b2323a4b3050b873737a02773b71b) 257 | - Add issue template [`c0c6057`](https://github.com/velis74/vue-datetime/commit/c0c605734295413c5135d194f8dd3eb8c1985168) 258 | 259 | #### [v1.0.0-alpha.4](https://github.com/velis74/vue-datetime/compare/v1.0.0-alpha.3...v1.0.0-alpha.4) 260 | 261 | > 15 January 2018 262 | 263 | - Reformat code [`6391d30`](https://github.com/velis74/vue-datetime/commit/6391d30f3d778bd55d9e72fd4ad89c60190a8660) 264 | - Add minimum and maximum datetimes. [`5467eec`](https://github.com/velis74/vue-datetime/commit/5467eec5125b8f3eea605bca3fc57fafb9d473e2) 265 | - Clear time when type is date [`317d0b4`](https://github.com/velis74/vue-datetime/commit/317d0b4f2b1a3f53daa35fcc1f1589ed80c89f7d) 266 | - Add notice and todo to readme [`6a8855b`](https://github.com/velis74/vue-datetime/commit/6a8855b0a970972b0992c8e840efcb13637f2ca8) 267 | - Refactor utils [`45a82a3`](https://github.com/velis74/vue-datetime/commit/45a82a3db8cdb61cd89aa354e1cfd8cc1d899851) 268 | - Update readme parameters section [`4461ab5`](https://github.com/velis74/vue-datetime/commit/4461ab5340d69b4c959fa4b7007659ef7e0f81e3) 269 | - Add `__VUE_DEVTOOLS_TOAST__` to accepted global variables names in mocha. [`1b40d2f`](https://github.com/velis74/vue-datetime/commit/1b40d2f0f515c65ee5bc49e6ab9c676ea35a7d96) 270 | 271 | #### [v1.0.0-alpha.3](https://github.com/velis74/vue-datetime/compare/v1.0.0-alpha.2...v1.0.0-alpha.3) 272 | 273 | > 25 December 2017 274 | 275 | #### [v1.0.0-alpha.2](https://github.com/velis74/vue-datetime/compare/v1.0.0-alpha.1...v1.0.0-alpha.2) 276 | 277 | > 25 December 2017 278 | 279 | - Add year picker [`c7766c8`](https://github.com/velis74/vue-datetime/commit/c7766c837bb54ccadbfa6007a7891c7ddea6426d) 280 | - Update `phrases` test [`c056826`](https://github.com/velis74/vue-datetime/commit/c056826b5876f5355d02830600b5670b68628614) 281 | - Pass time steps from date picker to time picker through the popup. [`fd2d338`](https://github.com/velis74/vue-datetime/commit/fd2d338a731bb3a659fb5ed754b4f87c053d9b7d) 282 | - Fix tests [`539a5cf`](https://github.com/velis74/vue-datetime/commit/539a5cfc094b0c980e3d40844d2f5a8f6c7c1f0f) 283 | - Refactor flow [`7b19f2f`](https://github.com/velis74/vue-datetime/commit/7b19f2ffaa2106eb81a84c54e443c9405c3ed679) 284 | - Rename `i18n` prop by `phrases` and add it to `Datetime` component [`46e10ff`](https://github.com/velis74/vue-datetime/commit/46e10ffff0bded97554a99836c512f8da99546a1) 285 | - Add `auto-changelog` package to auto generate changelog on every version [`db2b5ea`](https://github.com/velis74/vue-datetime/commit/db2b5eab7678fee07c0fa97f4084d9b3468fbac2) 286 | - Update readme [`d882209`](https://github.com/velis74/vue-datetime/commit/d8822092c9cd99f1748f0faf5eb0ed758ab19da1) 287 | - Remove `wrapper-class` and `input-class` props. Use `class` attribute instead. [`5017b63`](https://github.com/velis74/vue-datetime/commit/5017b6374486f0cd78f3b508fc495fbdc6185390) 288 | - Refactor how years, hours and minutes are generated. [`e3e5429`](https://github.com/velis74/vue-datetime/commit/e3e54296b0e9ef7dceed7bba4661d8b6c9f2e532) 289 | - Update readme [`5d60ed3`](https://github.com/velis74/vue-datetime/commit/5d60ed3bc0f937dc6e380c0dc25d8b9b4677812e) 290 | - Update readme [`63c1c43`](https://github.com/velis74/vue-datetime/commit/63c1c43d0d91edf8c4f437317a1fb6e06a1ec194) 291 | - Fix transition z-index issue [`9ac6aa9`](https://github.com/velis74/vue-datetime/commit/9ac6aa9d9b6ab23d826e913a998ae3cac466bccc) 292 | - Remove unused prop [`c709478`](https://github.com/velis74/vue-datetime/commit/c7094782a9b24702f2ae12f8c99441336837e746) 293 | - Remove duplicated year from header [`f2ba651`](https://github.com/velis74/vue-datetime/commit/f2ba651edad9392759883482f8d53d84bebe252c) 294 | - Update readme [`d04236a`](https://github.com/velis74/vue-datetime/commit/d04236ac20954901eb9808c07d754514d53f97f4) 295 | 296 | #### v1.0.0-alpha.1 297 | 298 | > 20 December 2017 299 | -------------------------------------------------------------------------------- /packages/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### Changelog 2 | 3 | All notable changes to this project will be documented in this file. Dates are displayed in UTC. 4 | 5 | Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). 6 | 7 | #### [v1.0.15](https://github.com/velis74/vue-datetime/compare/1.0.12...v1.0.15) 8 | 9 | > 18 January 2024 10 | 11 | - Add type definitions to package exports [`#3`](https://github.com/velis74/vue-datetime/pull/3) 12 | 13 | #### [1.0.12](https://github.com/velis74/vue-datetime/compare/1.0.11...1.0.12) 14 | 15 | > 20 September 2023 16 | 17 | - Remove legacy unittests [`3dcb173`](https://github.com/velis74/vue-datetime/commit/3dcb173639f9fa8d6b421d4327fa9cf1b91667eb) 18 | - Add Time picker unit tests [`65cf4d2`](https://github.com/velis74/vue-datetime/commit/65cf4d2afb7177e3a13584538234fa78ed8635aa) 19 | - Add unit tests for Popup component [`7a901c8`](https://github.com/velis74/vue-datetime/commit/7a901c8a918c2ef77ce4c8c898f1119881866ad9) 20 | - Add unit test for Datetime [`c364290`](https://github.com/velis74/vue-datetime/commit/c36429016bf02310c4b10c0cd07ff9250e214935) 21 | - Add unittests for calendar picker [`f5205cf`](https://github.com/velis74/vue-datetime/commit/f5205cf7677f8b3f6b2398f0e1a7b10d2b552f0d) 22 | - Add test for the rest of utility functions [`faf5e77`](https://github.com/velis74/vue-datetime/commit/faf5e77fb991a0c5eacfb0f36dccfb4629645bc5) 23 | - Add Month picker tests [`b14aafe`](https://github.com/velis74/vue-datetime/commit/b14aafeeed355913d627d0d5571079300395ed72) 24 | - Add Year picker tests [`d63dcae`](https://github.com/velis74/vue-datetime/commit/d63dcaec4adec90d6da56320aee81ae6d6880c7d) 25 | - Add plugin tests [`67f8c94`](https://github.com/velis74/vue-datetime/commit/67f8c94b111d6edbdf34ebe9404b72617cd9fde4) 26 | - Update theming section in readme [`1ad17a2`](https://github.com/velis74/vue-datetime/commit/1ad17a2a709351163e18a70709833d66d2facd49) 27 | - Fix over leaping problems with min/max datetime [`0ccc874`](https://github.com/velis74/vue-datetime/commit/0ccc87414752646344d54b91efd1b8c044f1e188) 28 | - Update package information [`1839c72`](https://github.com/velis74/vue-datetime/commit/1839c72bc02b34175e1926f8d1a66a9d1cba3dc9) 29 | - Add Year picker disabled year click [`a7ce574`](https://github.com/velis74/vue-datetime/commit/a7ce574a9c3cd2d060dea2af3cbbc5c163c12c38) 30 | - Add readme for added props [`2210562`](https://github.com/velis74/vue-datetime/commit/221056214307e05aa3e884355596c5abaf975d38) 31 | - Prevent header from wrapping month title [`f7d5f1d`](https://github.com/velis74/vue-datetime/commit/f7d5f1d1b06d3868d481307612a097c3a4737c1b) 32 | 33 | #### [1.0.11](https://github.com/velis74/vue-datetime/compare/1.0.10...1.0.11) 34 | 35 | > 26 May 2023 36 | 37 | - Create datetime utils test and fix calendar size [`47bce6a`](https://github.com/velis74/vue-datetime/commit/47bce6a4e36be829315ad569729fe2defb83f6ae) 38 | - Break utils into module [`9c257c1`](https://github.com/velis74/vue-datetime/commit/9c257c142d4c61b75f8c1e55e159d4ffb30fb6f6) 39 | - Add previous and next month date to calendar to fill empty space [`1fbe253`](https://github.com/velis74/vue-datetime/commit/1fbe253d10b26c9773ae96586dbbc34955b75e4b) 40 | - Refactor Datetime props [`4f564fc`](https://github.com/velis74/vue-datetime/commit/4f564fc71360710b2c8e63a2b9a763926176ac61) 41 | - Add flowEndStatus constant [`e76c51a`](https://github.com/velis74/vue-datetime/commit/e76c51a9a2205c118a7bbf6b80641e45b5d45550) 42 | - Fix typescript errors [`b4fe21e`](https://github.com/velis74/vue-datetime/commit/b4fe21e1213b57a5fb4fe8308bb03a1f3ff767e5) 43 | - Type clean datetime tests [`d939b94`](https://github.com/velis74/vue-datetime/commit/d939b947da5d0a5c812471fc0b9051d6f74e9d72) 44 | - Introduce fixed time and fixed date for datetime [`3447bd7`](https://github.com/velis74/vue-datetime/commit/3447bd7548c083f2307544de720a50ae724174e8) 45 | - Lint vite config [`0d89334`](https://github.com/velis74/vue-datetime/commit/0d89334d53f47969d499017e2d4d801470fc9bfb) 46 | - Refactor Year Picker props [`a37fc55`](https://github.com/velis74/vue-datetime/commit/a37fc5597609ae2b6e7837127e9d5c3ef0d2aeb8) 47 | - Cleanup [`d0a09fb`](https://github.com/velis74/vue-datetime/commit/d0a09fbf45a6f854402bcb181afa1301447a1eb9) 48 | - Add jest types [`d74ed76`](https://github.com/velis74/vue-datetime/commit/d74ed7635ec73203728a23bee6c032495816a45f) 49 | - Typo in README title [`904e39a`](https://github.com/velis74/vue-datetime/commit/904e39a6539a91c562e624542c79de36d4997656) 50 | 51 | #### [1.0.10](https://github.com/velis74/vue-datetime/compare/v1.0.3...1.0.10) 52 | 53 | > 23 May 2023 54 | 55 | - Mono repo [`#1`](https://github.com/velis74/vue-datetime/pull/1) 56 | - Add easy color scheming through the color property [`dad6f58`](https://github.com/velis74/vue-datetime/commit/dad6f584ad74485882fd88b21ae8e13301863953) 57 | - Restructure test, introduce vitest, create flow manager tests [`0cc1b6a`](https://github.com/velis74/vue-datetime/commit/0cc1b6ab2568a6ec2532a757c6501a8fd5d53e7b) 58 | - Refactor FlowManager [`f48b20c`](https://github.com/velis74/vue-datetime/commit/f48b20ce82ff90b25780a91d973979098ad55286) 59 | - Refactor popup props [`7d5dd0c`](https://github.com/velis74/vue-datetime/commit/7d5dd0c6e4d1775ba2dd87dcf463aa5d3362087c) 60 | - Split between demo and development demo running [`39d4e21`](https://github.com/velis74/vue-datetime/commit/39d4e2148fc7ebe91d346761a51d04c067bd9428) 61 | - update versions [`e39cb38`](https://github.com/velis74/vue-datetime/commit/e39cb38bbe1ca905f38698c8868aaace6ba8ea6a) 62 | - Remove legacy theming code [`dc3ba79`](https://github.com/velis74/vue-datetime/commit/dc3ba79fbd4468bd6bd4f31eef4be33cc43fc5d5) 63 | - update versions [`6187dc0`](https://github.com/velis74/vue-datetime/commit/6187dc0c54f41e5e158b6dfdd621c6e87c878ddf) 64 | - update versions [`604e2a2`](https://github.com/velis74/vue-datetime/commit/604e2a2c54b2ee34128222e5237f24c4ee253c4b) 65 | 66 | #### [v1.0.3](https://github.com/velis74/vue-datetime/compare/v1.0.2...v1.0.3) 67 | 68 | > 7 March 2023 69 | 70 | - Add configuration for np to stop nagging about default branch [`4ec466a`](https://github.com/velis74/vue-datetime/commit/4ec466ad2a626831a0c0b7b0f2fdb1f8721dcce0) 71 | - Fix files setting to publish the actual build files [`79e0d36`](https://github.com/velis74/vue-datetime/commit/79e0d3626618c7967f5f433e4f265b45c5bb2e83) 72 | 73 | #### [v1.0.2](https://github.com/velis74/vue-datetime/compare/v1.0.1...v1.0.2) 74 | 75 | > 7 March 2023 76 | 77 | - change repository URLs [`e645a17`](https://github.com/velis74/vue-datetime/commit/e645a17b62ac5fac34cbbad97262d3c07e5a3a66) 78 | 79 | #### [v1.0.1](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.13...v1.0.1) 80 | 81 | > 7 March 2023 82 | 83 | - Remove unneeded files [`0d13c28`](https://github.com/velis74/vue-datetime/commit/0d13c28ee03a304f2973aa226d26fa2d2fdd3a72) 84 | - Use datetime plugin in demo app [`2f3ade7`](https://github.com/velis74/vue-datetime/commit/2f3ade715e7e0fb32aac6188d77498365bcc8bd1) 85 | - Remove stale building utils [`5af5d47`](https://github.com/velis74/vue-datetime/commit/5af5d47fd3bb63747c420dd7cbb16c184b31c93a) 86 | - Introduce vite [`3a23c90`](https://github.com/velis74/vue-datetime/commit/3a23c90ed9209f3f17e90a539aeb4e23f84ebba7) 87 | - Rework Popup to composition API, ts and velis styling [`ab22b91`](https://github.com/velis74/vue-datetime/commit/ab22b91e79e4a688c5538e52330dcefb864a3f7e) 88 | - Rework DateTime to composition API, ts and velis styling [`4b0d05b`](https://github.com/velis74/vue-datetime/commit/4b0d05be51c962eedbe45637bea306c6c751febd) 89 | - Rework time picker to composition API, ts and velis styling [`eed9b6e`](https://github.com/velis74/vue-datetime/commit/eed9b6e2515636e4f8750f23fcaf81a80f3eac64) 90 | - Refactor plugin to vue3 syntax [`af257cb`](https://github.com/velis74/vue-datetime/commit/af257cb822b9fde3956c17fac5deaaf53ff574b9) 91 | - Fix veu style into plain css [`bcf1a83`](https://github.com/velis74/vue-datetime/commit/bcf1a8333050a61e8542e5b41d9ac62d4fbc4bf4) 92 | - Rework DatetimeCalendar to composition API, ts and velis eslint rules [`49c1f87`](https://github.com/velis74/vue-datetime/commit/49c1f8721f3a32d3f9d407fd0893bafab27f174d) 93 | - Cleanup package.json [`b35563c`](https://github.com/velis74/vue-datetime/commit/b35563ca0a80563f260f6e031fcab1daec181686) 94 | - Fix example page [`c5a97d9`](https://github.com/velis74/vue-datetime/commit/c5a97d93dc685cd0aa6217cecc7e03fb6abbd518) 95 | - Rework YearPicker to composition API, ts and velis styling [`10096f7`](https://github.com/velis74/vue-datetime/commit/10096f71623f60fb36dd9ad8cb4e3b3fffbe2f6f) 96 | - Rework MonthPicker to composition API, ts and velis styling [`6551465`](https://github.com/velis74/vue-datetime/commit/65514652d875f7e8df6493e8155f9926dbc0770c) 97 | - Add packaging utilities [`38f8c22`](https://github.com/velis74/vue-datetime/commit/38f8c227546456fd367081f35e72778d1f68a681) 98 | - Fix time picker, DRY scrolling concept [`52eae4f`](https://github.com/velis74/vue-datetime/commit/52eae4fea9f8c01dca28e30292c723805331d57b) 99 | - Fix v-model reactivity [`ebab314`](https://github.com/velis74/vue-datetime/commit/ebab3141d230679d61b9b86a645a14930324ddb4) 100 | - Prepare package building utilities [`21e7d78`](https://github.com/velis74/vue-datetime/commit/21e7d785fbb5b162fc141b73f327cb7ce8757cd0) 101 | - Remove auto moving on 12 hour time picker when touching all 3 params [`5534287`](https://github.com/velis74/vue-datetime/commit/5534287f4f3675d7cfe9cc09ff8eecdd6fa7bd7c) 102 | - Added new props for backdrop-click [`8af46c1`](https://github.com/velis74/vue-datetime/commit/8af46c10daaf88a7dd6ae3840ec6d164a3640008) 103 | - preparing to publish [`9d33af5`](https://github.com/velis74/vue-datetime/commit/9d33af5e22e83851a2b4ee40362055d5280c7246) 104 | - Added new props for and hide backdrop [`d6770a1`](https://github.com/velis74/vue-datetime/commit/d6770a126fbf7c8c3e4c0aa100e97620e1cfde9d) 105 | - Update gitignore [`40ceddf`](https://github.com/velis74/vue-datetime/commit/40ceddfe7b8cf43f72f5ad1851bb927d6873637d) 106 | - Fix month picker [`4a5a59b`](https://github.com/velis74/vue-datetime/commit/4a5a59b25a48adddffb1d2514e6323ec57dc323b) 107 | - Fix last commit bug [`15dd190`](https://github.com/velis74/vue-datetime/commit/15dd190663feb226c0a1ff2b886d741d14badf87) 108 | - Fix build warnings [`324725f`](https://github.com/velis74/vue-datetime/commit/324725fbad087114e61e3aebc3c10c366dc21653) 109 | - Add unmaintained notice [`1286b6c`](https://github.com/velis74/vue-datetime/commit/1286b6c9d3b4dc37d64b529dcc9f5adda050cace) 110 | 111 | #### [v1.0.0-beta.13](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.12...v1.0.0-beta.13) 112 | 113 | > 1 May 2020 114 | 115 | - Revert `rollup-plugin-vue` update. It doesn't output the same files. We should work on it deeper. [`91818e5`](https://github.com/velis74/vue-datetime/commit/91818e5650cd9377976e1f56c93b6ae810cf6601) 116 | 117 | #### [v1.0.0-beta.12](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.11...v1.0.0-beta.12) 118 | 119 | > 1 May 2020 120 | 121 | - Readme - register component when using CDN [`#193`](https://github.com/velis74/vue-datetime/pull/193) 122 | - Update `yarn.lock` [`ddde993`](https://github.com/velis74/vue-datetime/commit/ddde9938ee0d9cea4fc8075ae23f40ee29ec2e6f) 123 | - Fix max-datetime when time is midnight. Fixes: #215. [`599faf8`](https://github.com/velis74/vue-datetime/commit/599faf8a3f603aebf245452bd965710908cf32f7) 124 | - Don't add the `id` attribute when it is empty. Fixes: #202. [`d9f45b7`](https://github.com/velis74/vue-datetime/commit/d9f45b7261540ee4ab0302cf19330a9a7049d339) 125 | - Fix travis config [`b8084aa`](https://github.com/velis74/vue-datetime/commit/b8084aab6872d4b638f8a3788af7288ea4e030c7) 126 | - Update readme [`de01b03`](https://github.com/velis74/vue-datetime/commit/de01b0370c97f009873a2f2b935c0d18943eb7b3) 127 | - FIX: Update dependency version of the rollup-plugin-vue since the latest 2.x is not compatible with newer vue stack (see https://github.com/vuejs/rollup-plugin-vue/issues/273) [`77f1826`](https://github.com/velis74/vue-datetime/commit/77f1826522bfad27cbb943b9255d7ba8fca3dcbc) 128 | 129 | #### [v1.0.0-beta.11](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.10...v1.0.0-beta.11) 130 | 131 | > 13 November 2019 132 | 133 | - add curly brackets export name [`#178`](https://github.com/velis74/vue-datetime/pull/178) 134 | - Add type=time to the time example [`#172`](https://github.com/velis74/vue-datetime/pull/172) 135 | - Update util.js [`#164`](https://github.com/velis74/vue-datetime/pull/164) 136 | - improve pickers scrolling experience on mobile devices [`#162`](https://github.com/velis74/vue-datetime/pull/162) 137 | - added a check to see if yearList ref exists [`#131`](https://github.com/velis74/vue-datetime/pull/131) 138 | - replaced usage of Array.fill to work on old versions on Chrome [`#129`](https://github.com/velis74/vue-datetime/pull/129) 139 | - Fix min/max dates when picker zone isn't UTC [`0576c01`](https://github.com/velis74/vue-datetime/commit/0576c015c4b0906081ea1218a278f8af34fec13c) 140 | - Expose the popup. [`ad7d42f`](https://github.com/velis74/vue-datetime/commit/ad7d42fb2f64d8725465cfd2b91eba22a534000d) 141 | - Added height to month selection arrows. [`55d3ac4`](https://github.com/velis74/vue-datetime/commit/55d3ac432ece6a965a52567eabedef65e9dc2038) 142 | 143 | #### [v1.0.0-beta.10](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.9...v1.0.0-beta.10) 144 | 145 | > 13 January 2019 146 | 147 | - Add title property. Based on #118 [`0da317c`](https://github.com/velis74/vue-datetime/commit/0da317c4be5ef8c3c21642d0db5bcd17f9d27840) 148 | - Set `line-height` for popup [`04db82b`](https://github.com/velis74/vue-datetime/commit/04db82bc12753b9a60ce3b8a2ff36bc31c6e9c43) 149 | - Remove 0.x notice [`3ba3ea8`](https://github.com/velis74/vue-datetime/commit/3ba3ea8df943e239c927a4fb2ea38b39f2605c89) 150 | 151 | #### [v1.0.0-beta.9](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.8...v1.0.0-beta.9) 152 | 153 | > 12 January 2019 154 | 155 | - Added new custom slots for Buttons [`#97`](https://github.com/velis74/vue-datetime/pull/97) 156 | - fix: docs typo [`#99`](https://github.com/velis74/vue-datetime/pull/99) 157 | - Update `yarn.lock` [`24830ab`](https://github.com/velis74/vue-datetime/commit/24830ab587044fe34162054947af796cb5eaeed0) 158 | - months selector [`5e093d5`](https://github.com/velis74/vue-datetime/commit/5e093d5f6539f64914894498208d1cc202fd18db) 159 | - specs for DatetimeMonthsPicker [`38f96d7`](https://github.com/velis74/vue-datetime/commit/38f96d74f90feaa7368326f010d8b4a34ef04928) 160 | - Add property to customize the flow [`408720a`](https://github.com/velis74/vue-datetime/commit/408720a400956d8ea4fd1e5df63f61b599368160) 161 | - Update readme [`1f5accd`](https://github.com/velis74/vue-datetime/commit/1f5accd58a19cbab64bc0adceaf4aa28ccb3ea2b) 162 | - Revert split date for being compatible with all locales. So, month picker will be shown when clicking on the date. [`7892362`](https://github.com/velis74/vue-datetime/commit/78923624c1e1c97a07aae0e201b1e32a38f75206) 163 | - Add `input-style` property and accept `Object` and `Array` besides to `String` for the property `input-class`. [`e5653b5`](https://github.com/velis74/vue-datetime/commit/e5653b5cf7715b44530a9171880ebd53b4247b15) 164 | - Update readme [`0b79ce9`](https://github.com/velis74/vue-datetime/commit/0b79ce95f21d99ff7c8c684b7f1d3a7bf92332d6) 165 | - Fix disabled months. Month could be enabled even if it first and last day is disabled. [`26493f4`](https://github.com/velis74/vue-datetime/commit/26493f44b323935690556c225b6e6ddd30418f53) 166 | - Add `month` to flow [`84589b8`](https://github.com/velis74/vue-datetime/commit/84589b864c185e904458c8597f64cf10ceb22df3) 167 | - Code style [`8a2a0bb`](https://github.com/velis74/vue-datetime/commit/8a2a0bbaf11cd25783305595d085ece5b6773b76) 168 | - Update DatetimePopup.vue [`aa89e7f`](https://github.com/velis74/vue-datetime/commit/aa89e7fa3589470d098366b218effe0b9bcca02d) 169 | - Set `inheritAttrs` to prevent apply not recognized props to the root element. [`a1ff9ee`](https://github.com/velis74/vue-datetime/commit/a1ff9ee8e0f64409865856b51baa378c892f0f2e) 170 | - Set cursor pointer to header date [`1eb7125`](https://github.com/velis74/vue-datetime/commit/1eb7125373d1fa7dfdf2775631db911d5440120c) 171 | - Fix demo [`395f9db`](https://github.com/velis74/vue-datetime/commit/395f9dbdad4f4b8180e44eaf358c52aef5a3a899) 172 | - Update DatetimePopup.vue [`b80f55b`](https://github.com/velis74/vue-datetime/commit/b80f55bf5c49918d821c9349738d3a7d103c5222) 173 | - fix disabling [`dbefc2f`](https://github.com/velis74/vue-datetime/commit/dbefc2f009280f15d9c2a096208fd0f689aa817d) 174 | - fix comma-spacing [`9a330e0`](https://github.com/velis74/vue-datetime/commit/9a330e03af02308e264be739151b94d127c3d474) 175 | - fix comma-dangle [`68c70c2`](https://github.com/velis74/vue-datetime/commit/68c70c229e18dabe818bbe75f544ca2274496b48) 176 | - fix comma-spacing [`44c69b8`](https://github.com/velis74/vue-datetime/commit/44c69b83a204296fb1dd30417cfdd224d61caf1a) 177 | 178 | #### [v1.0.0-beta.8](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.7...v1.0.0-beta.8) 179 | 180 | > 14 October 2018 181 | 182 | - Fix min/max [`0466724`](https://github.com/velis74/vue-datetime/commit/0466724360d90083cede24c940711691d7a4fd68) 183 | - Fix code style [`caa4cd2`](https://github.com/velis74/vue-datetime/commit/caa4cd2d7d56a9ab2e2634cede7d14635be20d6d) 184 | - Fix min/max + [`bc28704`](https://github.com/velis74/vue-datetime/commit/bc28704958199177cc63864d669029a8a83d04e8) 185 | 186 | #### [v1.0.0-beta.7](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.6...v1.0.0-beta.7) 187 | 188 | > 13 October 2018 189 | 190 | - Tweak time picker [`3068f46`](https://github.com/velis74/vue-datetime/commit/3068f46c3ab3dfb42e312b0200d26916a6429129) 191 | - time only spec [`1d2454c`](https://github.com/velis74/vue-datetime/commit/1d2454c553375e7c3193bfa9cfa6639c2e2feb03) 192 | - Add tests [`00a2603`](https://github.com/velis74/vue-datetime/commit/00a2603d9695cc1b85588618b2b6c324c5af42a6) 193 | - Update tests [`ae5ef11`](https://github.com/velis74/vue-datetime/commit/ae5ef118cc408c9788a6d9d3ddef35f51a7c5776) 194 | - Added tests [`84f2b04`](https://github.com/velis74/vue-datetime/commit/84f2b041d578b3a212f8314898f625cfcdb8ffd4) 195 | - Disable invalid year in yearpicker [`76fd1d9`](https://github.com/velis74/vue-datetime/commit/76fd1d99f747032b150e76a5eff67d9807a65d6a) 196 | - Respect min date on default selection [`f8e40ea`](https://github.com/velis74/vue-datetime/commit/f8e40ead674b7d52a6e9dc7c75b221bd27daf23f) 197 | - Added support for named slots [`13ad825`](https://github.com/velis74/vue-datetime/commit/13ad825dd980dfe70abc723e740ca1dde09d0552) 198 | - added setting value via hidden input [`56eb53e`](https://github.com/velis74/vue-datetime/commit/56eb53eeac48d2df579ee07f622e94af3a942985) 199 | - time support [`35a0a13`](https://github.com/velis74/vue-datetime/commit/35a0a1377cea97e3eeb2e5477bb25b14b244941c) 200 | - Fix code style [`87f650f`](https://github.com/velis74/vue-datetime/commit/87f650f72130d4f4c6ca2b51342a49010de2dbcd) 201 | - fix specs and dupe headers [`077e82a`](https://github.com/velis74/vue-datetime/commit/077e82af109755da8f204bd741c1ae9ebe385aa4) 202 | - Simplify test [`93f08e2`](https://github.com/velis74/vue-datetime/commit/93f08e2796a4563009dbdf32a06d730efe5d3d87) 203 | - Fix datetime popup display bug when using UTC zone [`598253e`](https://github.com/velis74/vue-datetime/commit/598253e48c8f7e0b8ae96a7d7fe96c102ae5cc4a) 204 | - Fix case [`fc4a5fb`](https://github.com/velis74/vue-datetime/commit/fc4a5fb76b50c6b802c92b113d763794d43261db) 205 | - Fix min/max calendar test [`fb48c1c`](https://github.com/velis74/vue-datetime/commit/fb48c1c6226d6ecabccb9974bad9aa495f5b6cd7) 206 | - tweaks [`2b8ebed`](https://github.com/velis74/vue-datetime/commit/2b8ebed08764ba39099212b63b4a532f2785acd6) 207 | - Removed forgotten comments :( [`bc583bf`](https://github.com/velis74/vue-datetime/commit/bc583bf2556feac6f8e0da80ab73f1ba4bc95b07) 208 | 209 | #### [v1.0.0-beta.6](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.5...v1.0.0-beta.6) 210 | 211 | > 9 July 2018 212 | 213 | - Add empty days at the end of the month to complete the week [`#72`](https://github.com/velis74/vue-datetime/pull/72) 214 | - Merge branch 'v1.x' of https://github.com/coreycoburn/vue-datetime into coreycoburn-v1.x [`#56`](https://github.com/velis74/vue-datetime/issues/56) 215 | - Add test `should pass datetime to popup` [`9a22b1e`](https://github.com/velis74/vue-datetime/commit/9a22b1e4c18175d24ea9961994a877bbd9e1dafb) 216 | - Add `input-id` parameter to avoid id collisions [`d3d9797`](https://github.com/velis74/vue-datetime/commit/d3d979771b5d51b5c0f961a758bb7eef04597107) 217 | - Simplify roundMinute code [`3e28c20`](https://github.com/velis74/vue-datetime/commit/3e28c2064d1cbe01dbc5ee1986bdacf4eebac6ed) 218 | - Remove seconds and milliseconds when new date is created [`4895a21`](https://github.com/velis74/vue-datetime/commit/4895a2189717aa526a33c0b99d7d779a4212e8ff) 219 | 220 | #### [v1.0.0-beta.5](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.4...v1.0.0-beta.5) 221 | 222 | > 8 July 2018 223 | 224 | - Add close event [`5fe6a20`](https://github.com/velis74/vue-datetime/commit/5fe6a20f31d5c29190e0c4ef998a9e50f0d2e7b6) 225 | - Update luxon to v1.x [`06783cf`](https://github.com/velis74/vue-datetime/commit/06783cf1716d3eda92c820f0da4d880389199aa7) 226 | - Fix test [`2d93a6e`](https://github.com/velis74/vue-datetime/commit/2d93a6e129847b652c20557e2950a539f1a37f6b) 227 | 228 | #### [v1.0.0-beta.4](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.3...v1.0.0-beta.4) 229 | 230 | > 8 July 2018 231 | 232 | - apply default rounded time when using minute step - resolves #56 [`#56`](https://github.com/velis74/vue-datetime/issues/56) 233 | - Generate hidden input with raw value when name is passed [`32f8744`](https://github.com/velis74/vue-datetime/commit/32f87444285396152f04fc2cc4b10dce31c437a3) 234 | - macro tokens are supported. [`5db1a70`](https://github.com/velis74/vue-datetime/commit/5db1a70b532476e1481123a792bf3dd4ffd39844) 235 | - Add test for macro tokens format [`d995e02`](https://github.com/velis74/vue-datetime/commit/d995e02a9a9c86915a25ed83993f286b3fdc1a1c) 236 | - Fix value formatting with `type=date` and specified time zone [`522b19d`](https://github.com/velis74/vue-datetime/commit/522b19d5c3780b26a1158dd794c249eb51a75dd8) 237 | - Rename `name` attribute by `hidden-name` [`f06fc41`](https://github.com/velis74/vue-datetime/commit/f06fc41ff4b4377793f6541c9ca0af63e2359e91) 238 | - Update readme [`4bcbeef`](https://github.com/velis74/vue-datetime/commit/4bcbeef72201ea899903ec4eb9d59ec75d0bad1b) 239 | - Fix time zone for macro tokens format [`f868eb6`](https://github.com/velis74/vue-datetime/commit/f868eb636472bdf059d832b95cf71dc7a9559f66) 240 | - fix format describe [`c2a3456`](https://github.com/velis74/vue-datetime/commit/c2a34563d7b8b3015dd4437d5f76d1473f87ee89) 241 | - fix format describe [`5f44166`](https://github.com/velis74/vue-datetime/commit/5f441666159a1c98cf65b59ec1fe749e14af173c) 242 | - Macro tokens are supported. [`74deb7d`](https://github.com/velis74/vue-datetime/commit/74deb7dc264ff7342e6595ebc1d02159208d8b72) 243 | 244 | #### [v1.0.0-beta.3](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.2...v1.0.0-beta.3) 245 | 246 | > 3 February 2018 247 | 248 | - Add 12/24 hour format option to the time picker. [`#39`](https://github.com/velis74/vue-datetime/pull/39) 249 | - Update issue template [`4c5de6d`](https://github.com/velis74/vue-datetime/commit/4c5de6d79a8d56f9ee41fef5001035bcf7ce446e) 250 | - Fix demo example code [`2a5944f`](https://github.com/velis74/vue-datetime/commit/2a5944f4fd1f0393147367ef9e80477529e7d2bd) 251 | 252 | #### [v1.0.0-beta.2](https://github.com/velis74/vue-datetime/compare/v1.0.0-beta.1...v1.0.0-beta.2) 253 | 254 | > 23 January 2018 255 | 256 | - Add `week-start` parameter [`6cb9279`](https://github.com/velis74/vue-datetime/commit/6cb92797ec9140b02adb5566bdd9dfd5b4869b0c) 257 | - Update demo [`057f87a`](https://github.com/velis74/vue-datetime/commit/057f87a13d66890df4cc967134f193147acd53ea) 258 | - Fix issue with value time zone [`035d4da`](https://github.com/velis74/vue-datetime/commit/035d4daeb7d6bd8d051f97458c68707941c9870b) 259 | - Refactoring calendar new date [`d82d09c`](https://github.com/velis74/vue-datetime/commit/d82d09c82cabb90dda2d7fc876f106edc8c2af5f) 260 | - Rename `date` by `datetime` in `Datetime.vue` [`296f2c0`](https://github.com/velis74/vue-datetime/commit/296f2c01b92e14dd628e5d667963cd79d1f63705) 261 | - Refactoring [`7d40f6f`](https://github.com/velis74/vue-datetime/commit/7d40f6fd4d55e1b37b9fa2f4332b758b464f93f5) 262 | - Rename and improve `clearTime` util [`ccd80f5`](https://github.com/velis74/vue-datetime/commit/ccd80f5ed1f7453993fc11e441b941c13d3c312d) 263 | - Fix demo webpack [`579096d`](https://github.com/velis74/vue-datetime/commit/579096ddb528e6a7db4c2ad157a13995f5c9a775) 264 | - Add `luxon` in rollup globals config [`46551bf`](https://github.com/velis74/vue-datetime/commit/46551bfb6680605c24f9731896224977af378801) 265 | - Add demo link to readme [`44c667f`](https://github.com/velis74/vue-datetime/commit/44c667fcd9ee5927581f886902ae438488567296) 266 | - Remove auto-changelog limit [`f972692`](https://github.com/velis74/vue-datetime/commit/f9726929820e3666a9d968c080277c0e0673c0a1) 267 | 268 | #### [v1.0.0-beta.1](https://github.com/velis74/vue-datetime/compare/v1.0.0-alpha.8...v1.0.0-beta.1) 269 | 270 | > 19 January 2018 271 | 272 | - Cancel popup on key down ESC or TAB [`47c8fca`](https://github.com/velis74/vue-datetime/commit/47c8fcaf21bf53779f6549bf955ba27baddefd0a) 273 | - Close popup on press ESC key [`072063f`](https://github.com/velis74/vue-datetime/commit/072063fbab008a1d9c0081b5418a385b40de3623) 274 | - Continue or confirm popup on key down ENTER [`ff281ca`](https://github.com/velis74/vue-datetime/commit/ff281cab340bc34e2bd7098f72a3ac9ef912aace) 275 | - Fix auto on select time [`69edaaa`](https://github.com/velis74/vue-datetime/commit/69edaaa3403a664779c026b72a7b1beec06e115c) 276 | - On open popup blur input [`5155ac7`](https://github.com/velis74/vue-datetime/commit/5155ac7651922bab7a245886df1cafc81d4d1f3a) 277 | 278 | #### [v1.0.0-alpha.8](https://github.com/velis74/vue-datetime/compare/v1.0.0-alpha.7...v1.0.0-alpha.8) 279 | 280 | > 18 January 2018 281 | 282 | - Value will be an empty string instead of null when the date is empty or invalid because value type is a string. [`3fa3463`](https://github.com/velis74/vue-datetime/commit/3fa346337cc6266b532c4373142429431fe9972e) 283 | - Update luxon peer dependency version [`2dd13b2`](https://github.com/velis74/vue-datetime/commit/2dd13b2f8f445c1994d1e4afddedb31006c4417b) 284 | 285 | #### [v1.0.0-alpha.7](https://github.com/velis74/vue-datetime/compare/v1.0.0-alpha.6...v1.0.0-alpha.7) 286 | 287 | > 18 January 2018 288 | 289 | - Watch value changes [`d58b910`](https://github.com/velis74/vue-datetime/commit/d58b9109197fcef0334c783130df002760270bd7) 290 | - Update readme and issue template [`8adff3d`](https://github.com/velis74/vue-datetime/commit/8adff3df24f009048ae0d8beb07b78ef14d1a5f2) 291 | - Ignore all vue devtools globals in mocha [`7daee98`](https://github.com/velis74/vue-datetime/commit/7daee98d505f683ae7d8cd31035676ab5b03097b) 292 | - Update issue template [`b525ff6`](https://github.com/velis74/vue-datetime/commit/b525ff62f2ae855eb4a9e5ccda96972821b06b59) 293 | 294 | #### [v1.0.0-alpha.6](https://github.com/velis74/vue-datetime/compare/v1.0.0-alpha.5...v1.0.0-alpha.6) 295 | 296 | > 16 January 2018 297 | 298 | - Add `auto` property [`8d6cec3`](https://github.com/velis74/vue-datetime/commit/8d6cec3a45e8ce26e7eb0a5ffef7a410167b3809) 299 | - Update readme [`cef7afe`](https://github.com/velis74/vue-datetime/commit/cef7afe4a4ef7db80209bf48f5dff4bfddbc8254) 300 | - Fix local time zone test [`e35cec1`](https://github.com/velis74/vue-datetime/commit/e35cec180762fd15adf359a31eb47eac07a13970) 301 | - Update luxon to v0.3.1 [`635be46`](https://github.com/velis74/vue-datetime/commit/635be467a24f760a76e46414660d306f328ea671) 302 | - Add travis config [`f0289e9`](https://github.com/velis74/vue-datetime/commit/f0289e96278ddfa2997be8f2bd7812a6784b77f5) 303 | - Fix Datetime types tests [`0e6663c`](https://github.com/velis74/vue-datetime/commit/0e6663c07c9b40e21646e32dee16982a9a8cd8d5) 304 | - Add shields to readme [`a0af5e3`](https://github.com/velis74/vue-datetime/commit/a0af5e3ebe242c217bd35b313f3af0839ddd7444) 305 | - Fix license and coverage link [`109a5be`](https://github.com/velis74/vue-datetime/commit/109a5be52020d7d49dd376bd6a6b36af53470d9e) 306 | - Fix shields [`9356b3f`](https://github.com/velis74/vue-datetime/commit/9356b3f1b29f14310dd739d12fa9bf181b0339af) 307 | - Add `codecov` to travis configuration [`122a301`](https://github.com/velis74/vue-datetime/commit/122a3010b86cfec4b9abd243b40297c63e229dfd) 308 | - Add demo gif [`e528f9e`](https://github.com/velis74/vue-datetime/commit/e528f9e3f9c90a0627326cec293e63fa78e01b16) 309 | 310 | #### [v1.0.0-alpha.5](https://github.com/velis74/vue-datetime/compare/v1.0.0-alpha.4...v1.0.0-alpha.5) 311 | 312 | > 15 January 2018 313 | 314 | - Fix popup time zone [`787752f`](https://github.com/velis74/vue-datetime/commit/787752f1f48f5a52a55e6440ed86a844d0a49870) 315 | - Add `input-class` property [`b94c355`](https://github.com/velis74/vue-datetime/commit/b94c3554731b2323a4b3050b873737a02773b71b) 316 | - Add issue template [`c0c6057`](https://github.com/velis74/vue-datetime/commit/c0c605734295413c5135d194f8dd3eb8c1985168) 317 | 318 | #### [v1.0.0-alpha.4](https://github.com/velis74/vue-datetime/compare/v1.0.0-alpha.3...v1.0.0-alpha.4) 319 | 320 | > 15 January 2018 321 | 322 | - Reformat code [`6391d30`](https://github.com/velis74/vue-datetime/commit/6391d30f3d778bd55d9e72fd4ad89c60190a8660) 323 | - Add minimum and maximum datetimes. [`5467eec`](https://github.com/velis74/vue-datetime/commit/5467eec5125b8f3eea605bca3fc57fafb9d473e2) 324 | - Clear time when type is date [`317d0b4`](https://github.com/velis74/vue-datetime/commit/317d0b4f2b1a3f53daa35fcc1f1589ed80c89f7d) 325 | - Add notice and todo to readme [`6a8855b`](https://github.com/velis74/vue-datetime/commit/6a8855b0a970972b0992c8e840efcb13637f2ca8) 326 | - Refactor utils [`45a82a3`](https://github.com/velis74/vue-datetime/commit/45a82a3db8cdb61cd89aa354e1cfd8cc1d899851) 327 | - Update readme parameters section [`4461ab5`](https://github.com/velis74/vue-datetime/commit/4461ab5340d69b4c959fa4b7007659ef7e0f81e3) 328 | - Add `__VUE_DEVTOOLS_TOAST__` to accepted global variables names in mocha. [`1b40d2f`](https://github.com/velis74/vue-datetime/commit/1b40d2f0f515c65ee5bc49e6ab9c676ea35a7d96) 329 | 330 | #### [v1.0.0-alpha.3](https://github.com/velis74/vue-datetime/compare/v1.0.0-alpha.2...v1.0.0-alpha.3) 331 | 332 | > 25 December 2017 333 | 334 | #### [v1.0.0-alpha.2](https://github.com/velis74/vue-datetime/compare/v1.0.0-alpha.1...v1.0.0-alpha.2) 335 | 336 | > 25 December 2017 337 | 338 | - Add year picker [`c7766c8`](https://github.com/velis74/vue-datetime/commit/c7766c837bb54ccadbfa6007a7891c7ddea6426d) 339 | - Update `phrases` test [`c056826`](https://github.com/velis74/vue-datetime/commit/c056826b5876f5355d02830600b5670b68628614) 340 | - Pass time steps from date picker to time picker through the popup. [`fd2d338`](https://github.com/velis74/vue-datetime/commit/fd2d338a731bb3a659fb5ed754b4f87c053d9b7d) 341 | - Fix tests [`539a5cf`](https://github.com/velis74/vue-datetime/commit/539a5cfc094b0c980e3d40844d2f5a8f6c7c1f0f) 342 | - Refactor flow [`7b19f2f`](https://github.com/velis74/vue-datetime/commit/7b19f2ffaa2106eb81a84c54e443c9405c3ed679) 343 | - Rename `i18n` prop by `phrases` and add it to `Datetime` component [`46e10ff`](https://github.com/velis74/vue-datetime/commit/46e10ffff0bded97554a99836c512f8da99546a1) 344 | - Add `auto-changelog` package to auto generate changelog on every version [`db2b5ea`](https://github.com/velis74/vue-datetime/commit/db2b5eab7678fee07c0fa97f4084d9b3468fbac2) 345 | - Update readme [`d882209`](https://github.com/velis74/vue-datetime/commit/d8822092c9cd99f1748f0faf5eb0ed758ab19da1) 346 | - Remove `wrapper-class` and `input-class` props. Use `class` attribute instead. [`5017b63`](https://github.com/velis74/vue-datetime/commit/5017b6374486f0cd78f3b508fc495fbdc6185390) 347 | - Refactor how years, hours and minutes are generated. [`e3e5429`](https://github.com/velis74/vue-datetime/commit/e3e54296b0e9ef7dceed7bba4661d8b6c9f2e532) 348 | - Update readme [`5d60ed3`](https://github.com/velis74/vue-datetime/commit/5d60ed3bc0f937dc6e380c0dc25d8b9b4677812e) 349 | - Update readme [`63c1c43`](https://github.com/velis74/vue-datetime/commit/63c1c43d0d91edf8c4f437317a1fb6e06a1ec194) 350 | - Fix transition z-index issue [`9ac6aa9`](https://github.com/velis74/vue-datetime/commit/9ac6aa9d9b6ab23d826e913a998ae3cac466bccc) 351 | - Remove unused prop [`c709478`](https://github.com/velis74/vue-datetime/commit/c7094782a9b24702f2ae12f8c99441336837e746) 352 | - Remove duplicated year from header [`f2ba651`](https://github.com/velis74/vue-datetime/commit/f2ba651edad9392759883482f8d53d84bebe252c) 353 | - Update readme [`d04236a`](https://github.com/velis74/vue-datetime/commit/d04236ac20954901eb9808c07d754514d53f97f4) 354 | 355 | #### v1.0.0-alpha.1 356 | 357 | > 20 December 2017 358 | --------------------------------------------------------------------------------