Skip to content

Commit e344c3a

Browse files
committed
feat(NcDateTimePicker): add additional props needed for calendar
Signed-off-by: Grigory Vodyanov <scratchx@gmx.com>
1 parent 7532c0d commit e344c3a

File tree

1 file changed

+109
-1
lines changed

1 file changed

+109
-1
lines changed

src/components/NcDateTimePicker/NcDateTimePicker.vue

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,66 @@ export default {
163163
}
164164
</script>
165165
```
166+
167+
### Restricting to a specific time range
168+
169+
You can optionally restring the selectable time range, for example from 08:00 on Monday to 20:00 on Sunday.
170+
171+
```vue
172+
<template>
173+
<div>
174+
<NcDateTimePicker
175+
v-model="selected"
176+
type="datetime"
177+
:min="min"
178+
:max="max" />
179+
<p>Selected: {{ selected }}</p>
180+
</div>
181+
</template>
182+
<script>
183+
export default {
184+
data() {
185+
const now = new Date()
186+
const day = now.getDay()
187+
const daysSinceMonday = (day + 6) % 7
188+
189+
const startOfWeek = new Date(now)
190+
startOfWeek.setDate(now.getDate() - daysSinceMonday)
191+
startOfWeek.setHours(8, 0, 0, 0)
192+
193+
const endOfWeek = new Date(startOfWeek)
194+
endOfWeek.setDate(startOfWeek.getDate() + 6)
195+
endOfWeek.setHours(20, 0, 0, 0)
196+
197+
return {
198+
selected: null,
199+
min: startOfWeek,
200+
max: endOfWeek,
201+
}
202+
},
203+
}
204+
</script>
205+
```
206+
207+
### Inline calendar
208+
209+
Renders the calendar inline (without the text input) inside your parent component.
210+
211+
```vue
212+
<template>
213+
<div>
214+
<NcDateTimePicker v-model="date" inline />
215+
<p>Selected: {{ date }}</p>
216+
</div>
217+
</template>
218+
<script>
219+
export default {
220+
data() {
221+
return { date: new Date() }
222+
},
223+
}
224+
</script>
225+
```
166226
</docs>
167227

168228
<script setup lang="ts">
@@ -259,6 +319,16 @@ const props = withDefaults(defineProps<{
259319
*/
260320
locale?: string
261321
322+
/**
323+
* The maximum date that can be selected.
324+
*/
325+
max?: Date
326+
327+
/**
328+
* The minimum date that can be selected.
329+
*/
330+
min?: Date
331+
262332
/**
263333
* Default increment step for minutes in the time picker.
264334
*
@@ -306,17 +376,27 @@ const props = withDefaults(defineProps<{
306376
* @default 'date'
307377
*/
308378
type?: 'date' | 'datetime' | 'time' | 'week' | 'month' | 'year' | 'date-range' | 'time-range' | 'datetime-range'
379+
380+
/**
381+
* Render the calendar inline (no input field).
382+
*
383+
* @default false
384+
*/
385+
inline?: boolean
309386
}>(), {
310387
ariaLabel: t('Datepicker input'),
311388
ariaLabelMenu: t('Datepicker menu'),
312389
format: undefined,
313390
locale: getCanonicalLocale(),
391+
max: undefined,
392+
min: undefined,
314393
minuteStep: 10,
315394
timezoneId: 'UTC',
316395
modelValue: null,
317396
// set by fallbackPlaceholder
318397
placeholder: undefined,
319398
type: 'date',
399+
inline: false,
320400
})
321401
322402
const emit = defineEmits<{
@@ -327,6 +407,10 @@ const emit = defineEmits<{
327407
*/
328408
'update:modelValue': [Date | [Date, Date] | null]
329409
'update:timezoneId': [string]
410+
/**
411+
* Input blur
412+
*/
413+
blur: []
330414
}>()
331415
332416
const targetElement = useTemplateRef('target')
@@ -463,6 +547,10 @@ const pickerType = computed(() => ({
463547
: undefined,
464548
}))
465549
550+
// Convert min/max Date into VueDatePicker's time object shape
551+
const minTime = computed(() => props.min && { hours: props.min.getHours(), minutes: props.min.getMinutes(), seconds: props.min.getSeconds() })
552+
const maxTime = computed(() => props.max && { hours: props.max.getHours(), minutes: props.max.getMinutes(), seconds: props.max.getSeconds() })
553+
466554
/**
467555
* Called on model value update of the library.
468556
*
@@ -587,6 +675,20 @@ function selectDate() {
587675
function cancelSelection() {
588676
pickerInstance.value!.closeMenu()
589677
}
678+
679+
/**
680+
* Check if two dates are on the same day.
681+
*
682+
* @param a
683+
* @param b
684+
*/
685+
function sameDay(a: Date, b: Date): boolean {
686+
return (
687+
a.getFullYear() === b.getFullYear()
688+
&& a.getMonth() === b.getMonth()
689+
&& a.getDate() === b.getDate()
690+
)
691+
}
590692
</script>
591693

592694
<template>
@@ -603,18 +705,24 @@ function cancelSelection() {
603705
:placeholder="placeholder ?? placeholderFallback"
604706
:format="realFormat"
605707
:locale
708+
:min-date="min"
709+
:max-date="max"
710+
:min-time="min ? sameDay(min, value) ? minTime : undefined : undefined"
711+
:max-time="max ? sameDay(max, value) ? maxTime : undefined : undefined"
606712
:minutes-increment="minuteStep"
607713
:model-value="value"
608714
:now-button-label="t('Now')"
609715
:select-text="t('Pick')"
610716
six-weeks="fair"
717+
:inline
611718
:teleport="appendToBody ? (targetElement || undefined) : false"
612719
text-input
613720
:week-num-name
614721
:week-numbers="showWeekNumber ? { type: 'iso' } : undefined"
615722
:week-start
616723
v-bind="pickerType"
617-
@update:model-value="onUpdateModelValue">
724+
@update:model-value="onUpdateModelValue"
725+
@blur="emit('blur')">
618726
<template #action-buttons>
619727
<NcButton size="small" variant="tertiary" @click="cancelSelection">
620728
{{ t('Cancel') }}

0 commit comments

Comments
 (0)