mirror of
https://github.com/primefaces/primevue.git
synced 2025-05-10 01:12:37 +00:00
Refactor #5612 - Calendar / DatePicker
This commit is contained in:
parent
9303e9c3ab
commit
1428cc12df
21 changed files with 4261 additions and 4066 deletions
259
components/lib/datepicker/BaseDatePicker.vue
Normal file
259
components/lib/datepicker/BaseDatePicker.vue
Normal file
|
@ -0,0 +1,259 @@
|
|||
<script>
|
||||
import BaseComponent from 'primevue/basecomponent';
|
||||
import DatePickerStyle from 'primevue/datepicker/style';
|
||||
|
||||
export default {
|
||||
name: 'BaseDatePicker',
|
||||
extends: BaseComponent,
|
||||
props: {
|
||||
modelValue: null,
|
||||
selectionMode: {
|
||||
type: String,
|
||||
default: 'single'
|
||||
},
|
||||
dateFormat: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
inline: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showOtherMonths: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
selectOtherMonths: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showIcon: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
iconDisplay: {
|
||||
type: String,
|
||||
default: 'button'
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
previousIcon: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
nextIcon: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
incrementIcon: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
decrementIcon: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
numberOfMonths: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
responsiveOptions: Array,
|
||||
breakpoint: {
|
||||
type: String,
|
||||
default: '769px'
|
||||
},
|
||||
view: {
|
||||
type: String,
|
||||
default: 'date'
|
||||
},
|
||||
monthNavigator: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
yearNavigator: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
yearRange: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
minDate: {
|
||||
type: Date,
|
||||
value: null
|
||||
},
|
||||
maxDate: {
|
||||
type: Date,
|
||||
value: null
|
||||
},
|
||||
disabledDates: {
|
||||
type: Array,
|
||||
value: null
|
||||
},
|
||||
disabledDays: {
|
||||
type: Array,
|
||||
value: null
|
||||
},
|
||||
maxDateCount: {
|
||||
type: Number,
|
||||
value: null
|
||||
},
|
||||
showOnFocus: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
autoZIndex: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
baseZIndex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
showButtonBar: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
shortYearCutoff: {
|
||||
type: String,
|
||||
default: '+10'
|
||||
},
|
||||
showTime: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
timeOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hourFormat: {
|
||||
type: String,
|
||||
default: '24'
|
||||
},
|
||||
stepHour: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
stepMinute: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
stepSecond: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
showSeconds: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hideOnDateTimeSelect: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hideOnRangeSelection: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
timeSeparator: {
|
||||
type: String,
|
||||
default: ':'
|
||||
},
|
||||
showWeek: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
manualInput: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
appendTo: {
|
||||
type: [String, Object],
|
||||
default: 'body'
|
||||
},
|
||||
variant: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
invalid: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
inputId: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
inputClass: {
|
||||
type: [String, Object],
|
||||
default: null
|
||||
},
|
||||
inputStyle: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
panelClass: {
|
||||
type: [String, Object],
|
||||
default: null
|
||||
},
|
||||
panelStyle: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
todayButtonProps: {
|
||||
type: Object,
|
||||
default() {
|
||||
return { severity: 'secondary', text: true, size: 'small' };
|
||||
}
|
||||
},
|
||||
clearButtonProps: {
|
||||
type: Object,
|
||||
default() {
|
||||
return { severity: 'secondary', text: true, size: 'small' };
|
||||
}
|
||||
},
|
||||
navigatorButtonProps: {
|
||||
type: Object,
|
||||
default() {
|
||||
return { severity: 'secondary', text: true };
|
||||
}
|
||||
},
|
||||
timepickerButtonProps: {
|
||||
type: Object,
|
||||
default() {
|
||||
return { severity: 'secondary', text: true };
|
||||
}
|
||||
},
|
||||
ariaLabelledby: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
ariaLabel: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
style: DatePickerStyle,
|
||||
provide() {
|
||||
return {
|
||||
$parentInstance: this
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
1044
components/lib/datepicker/DatePicker.d.ts
vendored
Executable file
1044
components/lib/datepicker/DatePicker.d.ts
vendored
Executable file
File diff suppressed because it is too large
Load diff
56
components/lib/datepicker/DatePicker.spec.js
Normal file
56
components/lib/datepicker/DatePicker.spec.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import PrimeVue from 'primevue/config';
|
||||
import DatePicker from './DatePicker.vue';
|
||||
|
||||
describe('DatePicker.vue', () => {
|
||||
let wrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = mount(DatePicker, {
|
||||
global: {
|
||||
plugins: [PrimeVue],
|
||||
stubs: {
|
||||
teleport: true
|
||||
}
|
||||
},
|
||||
props: {
|
||||
modelValue: new Date()
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should exist', async () => {
|
||||
expect(wrapper.find('.p-datepicker.p-component').exists()).toBe(true);
|
||||
expect(wrapper.find('.p-inputtext').exists()).toBe(true);
|
||||
|
||||
let input = wrapper.find('.p-inputtext');
|
||||
|
||||
await input.trigger('focus');
|
||||
|
||||
expect(wrapper.find('.p-datepicker.p-component').exists()).toBe(true);
|
||||
expect(wrapper.find('.p-datepicker-today').exists()).toBe(true);
|
||||
expect(wrapper.find('.p-highlight').exists()).toBe(true);
|
||||
expect(wrapper.find('.p-highlight').text()).toEqual(new Date().getDate().toString());
|
||||
});
|
||||
|
||||
it('should select a date', async () => {
|
||||
await wrapper.setProps({ inline: true });
|
||||
|
||||
const event = { day: 8, month: 2, year: 2022, today: false, selectable: true };
|
||||
|
||||
const onDateSelect = vi.spyOn(wrapper.vm, 'onDateSelect');
|
||||
|
||||
await wrapper.vm.onDateSelect({ currentTarget: { focus: () => {} } }, event);
|
||||
expect(onDateSelect).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should calculate the correct view date when in range mode', async () => {
|
||||
const dateOne = new Date();
|
||||
const dateTwo = new Date();
|
||||
|
||||
dateTwo.setFullYear(dateOne.getFullYear(), dateOne.getMonth(), dateOne.getDate() + 1);
|
||||
await wrapper.setProps({ selectionMode: 'range', showTime: true, modelValue: [dateOne, dateTwo] });
|
||||
|
||||
expect(wrapper.vm.viewDate).toEqual(dateTwo);
|
||||
});
|
||||
});
|
2980
components/lib/datepicker/DatePicker.vue
Executable file
2980
components/lib/datepicker/DatePicker.vue
Executable file
File diff suppressed because it is too large
Load diff
9
components/lib/datepicker/package.json
Normal file
9
components/lib/datepicker/package.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"main": "./datepicker.cjs.js",
|
||||
"module": "./datepicker.esm.js",
|
||||
"unpkg": "./datepicker.min.js",
|
||||
"types": "./DatePicker.d.ts",
|
||||
"browser": {
|
||||
"./sfc": "./DatePicker.vue"
|
||||
}
|
||||
}
|
3
components/lib/datepicker/style/DatePickerStyle.d.ts
vendored
Normal file
3
components/lib/datepicker/style/DatePickerStyle.d.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
import { BaseStyle } from '../../base/style';
|
||||
|
||||
export interface DatePickerStyle extends BaseStyle {}
|
68
components/lib/datepicker/style/DatePickerStyle.js
Normal file
68
components/lib/datepicker/style/DatePickerStyle.js
Normal file
|
@ -0,0 +1,68 @@
|
|||
import BaseStyle from 'primevue/base/style';
|
||||
|
||||
const inlineStyles = {
|
||||
root: ({ props }) => ({ position: props.appendTo === 'self' ? 'relative' : undefined })
|
||||
};
|
||||
|
||||
const classes = {
|
||||
root: ({ props, state }) => [
|
||||
'p-datepicker p-component p-inputwrapper',
|
||||
{
|
||||
'p-invalid': props.invalid,
|
||||
'p-inputwrapper-filled': props.modelValue,
|
||||
'p-inputwrapper-focus': state.focused,
|
||||
'p-focus': state.focused || state.overlayVisible
|
||||
}
|
||||
],
|
||||
input: 'p-datepicker-input',
|
||||
dropdownButton: 'p-datepicker-dropdown',
|
||||
inputIconContainer: 'p-datepicker-input-icon-container',
|
||||
inputIcon: 'p-datepicker-input-icon',
|
||||
panel: ({ instance, props }) => [
|
||||
'p-datepicker-panel p-component',
|
||||
{
|
||||
'p-datepicker-panel-inline': props.inline,
|
||||
'p-disabled': props.disabled,
|
||||
'p-datepicker-timeonly': props.timeOnly,
|
||||
'p-ripple-disabled': instance.$primevue.config.ripple === false
|
||||
}
|
||||
],
|
||||
group: 'p-datepicker-calendar-container',
|
||||
calendar: 'p-datepicker-calendar',
|
||||
header: 'p-datepicker-header',
|
||||
previousButton: 'p-datepicker-prev-button',
|
||||
title: 'p-datepicker-title',
|
||||
monthTitle: 'p-datepicker-view-month p-link',
|
||||
yearTitle: 'p-datepicker-view-year p-link',
|
||||
decadeTitle: 'p-datepicker-decade',
|
||||
nextButton: 'p-datepicker-next-button',
|
||||
grid: 'p-datepicker-day-view',
|
||||
weekHeader: 'p-datepicker-weekheader p-disabled',
|
||||
weekNumber: 'p-datepicker-weeknumber',
|
||||
weekLabelContainer: 'p-disabled',
|
||||
weekDay: 'p-datepicker-weekday-cell',
|
||||
weekDayLabel: 'p-date-picker-weekday',
|
||||
day: ({ date }) => ['p-datepicker-day-cell', { 'p-datepicker-other-month': date.otherMonth, 'p-datepicker-today': date.today }],
|
||||
dayLabel: ({ instance, props, date }) => ['p-datepicker-day', { 'p-datepicker-day-selected': instance.isSelected(date) && date.selectable, 'p-disabled': props.disabled || !date.selectable }],
|
||||
monthPicker: 'p-datepicker-month-view',
|
||||
month: ({ instance, props, month, index }) => ['p-datepicker-month', { 'p-datepicker-month-selected': instance.isMonthSelected(index), 'p-disabled': props.disabled || !month.selectable }],
|
||||
yearPicker: 'p-datepicker-year-view',
|
||||
year: ({ instance, props, year }) => ['p-datepicker-year', { 'p-datepicker-year-selected': instance.isYearSelected(year.value), 'p-disabled': props.disabled || !year.selectable }],
|
||||
timePicker: 'p-datepicker-time-picker',
|
||||
hourPicker: 'p-datepicker-hour-picker',
|
||||
incrementButton: 'p-datepicker-increment-button',
|
||||
decrementButton: 'p-datepicker-decrement-button',
|
||||
separatorContainer: 'p-datepicker-separator',
|
||||
minutePicker: 'p-minute-picker',
|
||||
secondPicker: 'p-second-picker',
|
||||
ampmPicker: 'p-ampm-picker',
|
||||
buttonbar: 'p-datepicker-buttonbar',
|
||||
todayButton: 'p-datepicker-today-button',
|
||||
clearButton: 'p-datepicker-clear-button'
|
||||
};
|
||||
|
||||
export default BaseStyle.extend({
|
||||
name: 'datepicker',
|
||||
classes,
|
||||
inlineStyles
|
||||
});
|
6
components/lib/datepicker/style/package.json
Normal file
6
components/lib/datepicker/style/package.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"main": "./datepickerstyle.cjs.js",
|
||||
"module": "./datepickerstyle.esm.js",
|
||||
"unpkg": "./datepickerstyle.min.js",
|
||||
"types": "./DatePickerStyle.d.ts"
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue