diff --git a/demo/sections/components/DateRangeSelect.vue b/demo/sections/components/DateRangeSelect.vue
new file mode 100644
index 000000000..306abd620
--- /dev/null
+++ b/demo/sections/components/DateRangeSelect.vue
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+ value: {{ JSON.stringify(value) }}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demo/sections/components/index.ts b/demo/sections/components/index.ts
index 5c8413e2f..15ae89e13 100644
--- a/demo/sections/components/index.ts
+++ b/demo/sections/components/index.ts
@@ -17,6 +17,7 @@ export const components: Section = {
contextSidebar: () => import('./ContextSidebar.vue'),
dateInput: () => import('./DateInput.vue'),
dateRangeInput: () => import('./DateRangeInput.vue'),
+ dateRangeSelect: () => import('./DateRangeSelect.vue'),
dialog: () => import('./Dialog.vue'),
divider: () => import('./Divider.vue'),
drawer: () => import('./Drawer.vue'),
diff --git a/src/components/DateInput/PDateInput.vue b/src/components/DateInput/PDateInput.vue
index 29970500e..d49e187e4 100644
--- a/src/components/DateInput/PDateInput.vue
+++ b/src/components/DateInput/PDateInput.vue
@@ -21,7 +21,6 @@
@@ -88,13 +87,6 @@
\ No newline at end of file
diff --git a/src/components/DateRangeSelect/PDateRangeSelectOptions.vue b/src/components/DateRangeSelect/PDateRangeSelectOptions.vue
new file mode 100644
index 000000000..9aa308765
--- /dev/null
+++ b/src/components/DateRangeSelect/PDateRangeSelectOptions.vue
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/DateRangeSelect/index.ts b/src/components/DateRangeSelect/index.ts
new file mode 100644
index 000000000..12f04cce1
--- /dev/null
+++ b/src/components/DateRangeSelect/index.ts
@@ -0,0 +1,8 @@
+import { App } from 'vue'
+import PDateRangeSelect from '@/components/DateRangeSelect/PDateRangeSelect.vue'
+
+const install = (app: App): void => {
+ app.component('PDateRangeSelect', PDateRangeSelect)
+}
+
+export { PDateRangeSelect, install }
\ No newline at end of file
diff --git a/src/components/DateRangeSelect/utilities.ts b/src/components/DateRangeSelect/utilities.ts
new file mode 100644
index 000000000..d7c08f954
--- /dev/null
+++ b/src/components/DateRangeSelect/utilities.ts
@@ -0,0 +1,53 @@
+import { addSeconds, endOfDay, format, intervalToDuration, isSameDay, startOfDay } from 'date-fns'
+import { toPluralString } from '@/utilities'
+
+type DateRange = {
+ startDate: Date,
+ endDate: Date,
+}
+
+const dateFormat = 'MMM do, yyyy'
+const timeFormat = 'hh:mm a'
+const dateTimeFormat = `${dateFormat} 'at' ${timeFormat}`
+
+export function getDateSpanLabel(seconds: number): string {
+
+ const now = new Date()
+ const duration = intervalToDuration({
+ start: now,
+ end: addSeconds(now, seconds),
+ })
+
+ const reduced = Object.entries(duration).reduce((durations, [key, value]) => {
+ if (value) {
+ const unit = key.slice(0, -1)
+ durations.push(`${value} ${toPluralString(unit, value)}`)
+ }
+
+ return durations
+ }, [])
+
+ const direction = seconds < 0 ? 'Past' : 'Next'
+
+ return `${direction} ${reduced.join(' ')}`
+}
+
+export function getDateRangeLabel({ startDate, endDate }: DateRange): string {
+ if (isPickerSingleDayRange({ startDate, endDate })) {
+ return format(startDate, dateFormat)
+ }
+
+ if (isFullDateRange({ startDate, endDate })) {
+ return `${format(startDate, dateFormat)} - ${format(endDate, dateFormat)}`
+ }
+
+ return `${format(startDate, dateTimeFormat)} - ${format(endDate, dateTimeFormat)}`
+}
+
+function isPickerSingleDayRange({ startDate, endDate }: DateRange): boolean {
+ return isFullDateRange({ startDate, endDate }) && isSameDay(startDate, endDate)
+}
+
+export function isFullDateRange({ startDate, endDate }: DateRange): boolean {
+ return startOfDay(startDate).getTime() === startDate.getTime() && endOfDay(endDate).getTime() === endDate.getTime()
+}
\ No newline at end of file
diff --git a/src/components/DateTimeInputGroup/PDateTimeInputGroup.vue b/src/components/DateTimeInputGroup/PDateTimeInputGroup.vue
index f679a361f..167434cd9 100644
--- a/src/components/DateTimeInputGroup/PDateTimeInputGroup.vue
+++ b/src/components/DateTimeInputGroup/PDateTimeInputGroup.vue
@@ -10,10 +10,10 @@
-
+
-
+
@@ -38,7 +38,7 @@
(event: 'update:modelValue', value: Date | null): void,
}>()
- const date = computed({
+ const startDate = computed({
get() {
return props.modelValue ?? null
},
@@ -47,6 +47,18 @@
},
})
+ const startTime = computed({
+ get() {
+ return props.modelValue ?? null
+ },
+ set(value) {
+ if (!value) {
+ return
+ }
+
+ emit('update:modelValue', value)
+ },
+ })
const nowOrTodayLabel = computed(() => props.showTime ? 'Now' : 'Today')
function setToTodayOrNow(): void {
diff --git a/src/components/NativeDateInput/PNativeDateInput.vue b/src/components/NativeDateInput/PNativeDateInput.vue
index 85408a9fa..dca50cd0c 100644
--- a/src/components/NativeDateInput/PNativeDateInput.vue
+++ b/src/components/NativeDateInput/PNativeDateInput.vue
@@ -64,7 +64,14 @@
})
const stringMin = computed(() => props.min ? format(props.min, 'yyyy-MM-dd') : undefined)
- const stringMax = computed(() => props.max ? format(props.max, 'yyyy-MM-dd') : undefined)
+ const stringMax = computed(() => {
+ if (props.max) {
+ return format(props.max, 'yyyy-MM-dd')
+ }
+
+ // max date with a 4 digit year
+ return '2999-12-31'
+ })
function showPicker(): void {
inputElement.value?.showPicker()
diff --git a/src/components/SelectOption/PSelectOption.vue b/src/components/SelectOption/PSelectOption.vue
index b2d088115..1d9255a96 100644
--- a/src/components/SelectOption/PSelectOption.vue
+++ b/src/components/SelectOption/PSelectOption.vue
@@ -125,6 +125,7 @@
flex
gap-2
items-center
+ cursor-pointer
}
.p-select-option--selected { @apply
diff --git a/src/components/index.ts b/src/components/index.ts
index e08f47f61..f3e636ff3 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -21,6 +21,7 @@ import { PDateInput, install as installPDateInput } from '@/components/DateInput
import { PDatePicker, install as installPDatePicker } from '@/components/DatePicker'
import { PDateRangeInput, install as installPDateRangeInput } from '@/components/DateRangeInput'
import { PDateRangePicker, install as installPDateRangePicker } from '@/components/DateRangePicker'
+import { PDateRangeSelect, install as installPDateRangeSelect } from '@/components/DateRangeSelect'
import { PDialog, install as installPDialog } from '@/components/Dialog'
import { PDivider, install as installPDivider } from '@/components/Divider'
import { PDrawer, install as installPDrawer } from '@/components/Drawer'
@@ -111,6 +112,7 @@ export {
PDatePicker,
PDateRangeInput,
PDateRangePicker,
+ PDateRangeSelect,
PDialog,
PDivider,
PDrawer,
@@ -212,6 +214,7 @@ export const installs = [
installPDatePicker,
installPDateRangeInput,
installPDateRangePicker,
+ installPDateRangeSelect,
installPDialog,
installPDivider,
installPDrawer,
@@ -303,6 +306,7 @@ declare module '@vue/runtime-core' {
PDatePicker: typeof PDatePicker,
PDateRangeInput: typeof PDateRangeInput,
PDateRangePicker: typeof PDateRangePicker,
+ PDateRangeSelect: typeof PDateRangeSelect,
PDialog: typeof PDialog,
PDivider: typeof PDivider,
PDrawer: typeof PDrawer,