Fixed #1750 - Add responsiveOptions property to Calendar

pull/1751/head
mertsincan 2021-11-12 17:14:10 +03:00
parent 3d343c9cdd
commit d5a26c61ad
3 changed files with 94 additions and 11 deletions

View File

@ -10,6 +10,7 @@ interface CalendarProps {
showIcon?: boolean; showIcon?: boolean;
icon?: string; icon?: string;
numberOfMonths?: number; numberOfMonths?: number;
responsiveOptions?: any[];
view?: string; view?: string;
touchUI?: boolean; touchUI?: boolean;
monthNavigator?: boolean; monthNavigator?: boolean;

View File

@ -11,14 +11,14 @@
<div class="p-datepicker-group" v-for="(month,groupIndex) of months" :key="month.month + month.year"> <div class="p-datepicker-group" v-for="(month,groupIndex) of months" :key="month.month + month.year">
<div class="p-datepicker-header"> <div class="p-datepicker-header">
<slot name="header"></slot> <slot name="header"></slot>
<button class="p-datepicker-prev p-link" v-if="groupIndex === 0" @click="onPrevButtonClick" type="button" @keydown="onContainerButtonKeydown" v-ripple :disabled="$attrs.disabled"> <button class="p-datepicker-prev p-link" v-show="groupIndex === 0" @click="onPrevButtonClick" type="button" @keydown="onContainerButtonKeydown" v-ripple :disabled="$attrs.disabled">
<span class="p-datepicker-prev-icon pi pi-chevron-left"></span> <span class="p-datepicker-prev-icon pi pi-chevron-left"></span>
</button> </button>
<div class="p-datepicker-title"> <div class="p-datepicker-title">
<button type="button" @click="switchToMonthView" v-if="currentView === 'date'" class="p-datepicker-month p-link" :disabled="$attrs.disabled"> <button type="button" @click="switchToMonthView" v-if="currentView === 'date'" class="p-datepicker-month p-link" :disabled="switchViewButtonDisabled">
{{getMonthName(month.month)}} {{getMonthName(month.month)}}
</button> </button>
<button type="button" @click="switchToYearView" v-if="currentView !== 'year'" class="p-datepicker-year p-link" :disabled="$attrs.disabled"> <button type="button" @click="switchToYearView" v-if="currentView !== 'year'" class="p-datepicker-year p-link" :disabled="switchViewButtonDisabled">
{{currentYear}} {{currentYear}}
</button> </button>
<span class="p-datepicker-decade" v-if="currentView === 'year'"> <span class="p-datepicker-decade" v-if="currentView === 'year'">
@ -27,7 +27,7 @@
</slot> </slot>
</span> </span>
</div> </div>
<button class="p-datepicker-next p-link" v-if="numberOfMonths === 1 ? true : (groupIndex === numberOfMonths - 1)" <button class="p-datepicker-next p-link" v-show="numberOfMonths === 1 ? true : (groupIndex === numberOfMonths - 1)"
@click="onNextButtonClick" type="button" @keydown="onContainerButtonKeydown" v-ripple :disabled="$attrs.disabled"> @click="onNextButtonClick" type="button" @keydown="onContainerButtonKeydown" v-ripple :disabled="$attrs.disabled">
<span class="p-datepicker-next-icon pi pi-chevron-right"></span> <span class="p-datepicker-next-icon pi pi-chevron-right"></span>
</button> </button>
@ -142,7 +142,7 @@
</template> </template>
<script> <script>
import {ConnectedOverlayScrollHandler,DomHandler,ZIndexUtils} from 'primevue/utils'; import {ConnectedOverlayScrollHandler,DomHandler,ZIndexUtils,UniqueComponentId} from 'primevue/utils';
import OverlayEventBus from 'primevue/overlayeventbus'; import OverlayEventBus from 'primevue/overlayeventbus';
import InputText from 'primevue/inputtext'; import InputText from 'primevue/inputtext';
import Button from 'primevue/button'; import Button from 'primevue/button';
@ -186,6 +186,7 @@ export default {
type: Number, type: Number,
default: 1 default: 1
}, },
responsiveOptions: Array,
view: { view: {
type: String, type: String,
default: 'date' default: 'date'
@ -320,9 +321,15 @@ export default {
this.updateCurrentMetaData(); this.updateCurrentMetaData();
}, },
mounted() { mounted() {
if (this.inline && !this.$attrs.disabled) { this.createResponsiveStyle();
this.initFocusableCell();
this.overlay.style.width = DomHandler.getOuterWidth(this.$el) + 'px'; if (this.inline) {
this.overlay && this.overlay.setAttribute(this.attributeSelector, '');
if (!this.$attrs.disabled) {
this.initFocusableCell();
this.overlay.style.width = DomHandler.getOuterWidth(this.$el) + 'px';
}
} }
}, },
updated() { updated() {
@ -343,8 +350,9 @@ export default {
} }
if (this.mask) { if (this.mask) {
this.destroyMask(); this.destroyMask();
} }
this.destroyResponsiveStyleElement();
this.unbindOutsideClickListener(); this.unbindOutsideClickListener();
this.unbindResizeListener(); this.unbindResizeListener();
@ -383,6 +391,14 @@ export default {
if (this.overlay) { if (this.overlay) {
setTimeout(this.updateFocus, 0); setTimeout(this.updateFocus, 0);
} }
},
numberOfMonths() {
this.destroyResponsiveStyleElement();
this.createResponsiveStyle();
},
responsiveOptions() {
this.destroyResponsiveStyleElement();
this.createResponsiveStyle();
} }
}, },
methods: { methods: {
@ -551,12 +567,15 @@ export default {
return validMin && validMax && validDate && validDay; return validMin && validMax && validDate && validDay;
}, },
onOverlayEnter(el) { onOverlayEnter(el) {
el.setAttribute(this.attributeSelector, '');
if (this.autoZIndex) { if (this.autoZIndex) {
if (this.touchUI) if (this.touchUI)
ZIndexUtils.set('modal', el, this.baseZIndex || this.$primevue.config.zIndex.modal); ZIndexUtils.set('modal', el, this.baseZIndex || this.$primevue.config.zIndex.modal);
else else
ZIndexUtils.set('overlay', el, this.baseZIndex || this.$primevue.config.zIndex.overlay); ZIndexUtils.set('overlay', el, this.baseZIndex || this.$primevue.config.zIndex.overlay);
} }
this.alignOverlay(); this.alignOverlay();
this.$emit('show'); this.$emit('show');
}, },
@ -756,7 +775,7 @@ export default {
else { else {
this.overlay.style.width = DomHandler.getOuterWidth(this.$el) + 'px'; this.overlay.style.width = DomHandler.getOuterWidth(this.$el) + 'px';
} }
DomHandler.absolutePosition(this.overlay, this.$el); DomHandler.absolutePosition(this.overlay, this.$el);
} }
} }
@ -2116,6 +2135,53 @@ export default {
target: this.$el target: this.$el
}); });
} }
},
createResponsiveStyle() {
if (this.numberOfMonths > 1 && this.responsiveOptions) {
if (!this.responsiveStyleElement) {
this.responsiveStyleElement = document.createElement('style');
this.responsiveStyleElement.type = 'text/css';
document.body.appendChild(this.responsiveStyleElement);
}
let innerHTML = '';
if (this.responsiveOptions) {
let responsiveOptions = [...this.responsiveOptions]
.filter(o => !!(o.breakpoint && o.numMonths))
.sort((o1, o2) => -1 * o1.breakpoint.localeCompare(o2.breakpoint, undefined, { numeric: true }));
for (let i = 0; i < responsiveOptions.length; i++) {
let { breakpoint, numMonths } = responsiveOptions[i];
let styles = `
.p-datepicker[${this.attributeSelector}] .p-datepicker-group:nth-child(${numMonths}) .p-datepicker-next {
display: inline-flex !important;
}
`;
for (let j = numMonths; j < this.numberOfMonths; j++) {
styles += `
.p-datepicker[${this.attributeSelector}] .p-datepicker-group:nth-child(${j + 1}) {
display: none !important;
}
`
}
innerHTML += `
@media screen and (max-width: ${breakpoint}) {
${styles}
}
`
}
}
this.responsiveStyleElement.innerHTML = innerHTML;
}
},
destroyResponsiveStyleElement() {
if (this.responsiveStyleElement) {
this.responsiveStyleElement.remove();
this.responsiveStyleElement = null;
}
} }
}, },
computed: { computed: {
@ -2315,6 +2381,12 @@ export default {
}, },
appendTarget() { appendTarget() {
return this.appendDisabled ? null : this.appendTo; return this.appendDisabled ? null : this.appendTo;
},
attributeSelector() {
return UniqueComponentId();
},
switchViewButtonDisabled() {
return this.numberOfMonths > 1 || this.$attrs.disabled;
} }
}, },
components: { components: {
@ -2331,6 +2403,7 @@ export default {
.p-calendar { .p-calendar {
position: relative; position: relative;
display: inline-flex; display: inline-flex;
max-width: 100%;
} }
.p-calendar .p-inputtext { .p-calendar .p-inputtext {
@ -2372,6 +2445,7 @@ export default {
.p-datepicker-inline { .p-datepicker-inline {
display: inline-block; display: inline-block;
position: static; position: static;
overflow-x: auto;
} }
/* Header */ /* Header */
@ -2400,6 +2474,10 @@ export default {
display: flex; display: flex;
} }
.p-datepicker-multiple-month .p-datepicker-group-container .p-datepicker-group {
flex: 1 1 auto;
}
/* DatePicker Table */ /* DatePicker Table */
.p-datepicker table { .p-datepicker table {
width: 100%; width: 100%;

View File

@ -93,6 +93,10 @@ button {
user-select: none; user-select: none;
} }
.p-link:disabled {
cursor: default;
}
/* Non vue overlay animations */ /* Non vue overlay animations */
.p-connected-overlay { .p-connected-overlay {
opacity: 0; opacity: 0;
@ -161,4 +165,4 @@ button {
position: absolute; position: absolute;
width: 1px; width: 1px;
word-wrap: normal !important; word-wrap: normal !important;
} }