@polymarbot/nuxt-layer-shadcn-ui 0.8.6 → 0.8.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -29,7 +29,7 @@ const props = withDefaults(defineProps<DatePickerProps>(), {
29
29
  })
30
30
 
31
31
  const emit = defineEmits<{
32
- 'update:modelValue': [value: Date | string | null]
32
+ 'update:modelValue': [value: Date | string | number | null]
33
33
  }>()
34
34
 
35
35
  const model = computed({
@@ -18,7 +18,7 @@ export interface DatePickerTimeConfig {
18
18
  export type DatePickerType = 'date' | 'month' | 'year'
19
19
 
20
20
  export interface DatePickerProps {
21
- modelValue?: Date | string | null
21
+ modelValue?: Date | string | number | null
22
22
  /** Picker type: date (default), month, or year */
23
23
  type?: DatePickerType
24
24
  /** Enable time selection, or pass DatePickerTimeConfig for fine-grained control */
@@ -33,7 +33,11 @@ export interface DatePickerProps {
33
33
  minDate?: Date | string
34
34
  /** Maximum selectable date */
35
35
  maxDate?: Date | string
36
- /** v-model output format (e.g. 'yyyy-MM-dd', 'timestamp', 'iso') */
36
+ /**
37
+ * v-model output format. Accepts any VueDatePicker `model-type` value:
38
+ * `'iso'`, `'timestamp'`, or a date-fns pattern (e.g. `'yyyy-MM-dd'`).
39
+ * Omit to bind a `Date` object.
40
+ */
37
41
  valueFormat?: string
38
42
  /** Auto apply selection without confirm button */
39
43
  autoApply?: boolean
@@ -1,5 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import type { DateRangePickerProps } from './types'
3
+ import { format as formatDate, parse as parseDate } from 'date-fns'
3
4
 
4
5
  defineOptions({ inheritAttrs: false })
5
6
 
@@ -20,30 +21,65 @@ const props = withDefaults(defineProps<DateRangePickerProps>(), {
20
21
  })
21
22
 
22
23
  const emit = defineEmits<{
23
- 'update:start': [value: Date | string | null]
24
- 'update:end': [value: Date | string | null]
24
+ 'update:start': [value: Date | string | number | null]
25
+ 'update:end': [value: Date | string | number | null]
25
26
  }>()
26
27
 
27
28
  const { t } = useI18n()
28
29
  const T = useTranslations('components.ui.DateRangePicker')
29
30
 
31
+ // Convert a v-model value (whose shape depends on valueFormat) into a Date for manipulation.
32
+ function parseValue (value: Date | string | number): Date | null {
33
+ if (value instanceof Date) return new Date(value)
34
+ if (typeof value === 'number') return new Date(value)
35
+ const fmt = props.valueFormat
36
+ if (!fmt || fmt === 'iso') return new Date(value)
37
+ if (fmt === 'timestamp') return new Date(Number(value))
38
+ if (fmt === 'format') return null // uses VueDatePicker `format` prop, not exposed here
39
+ try {
40
+ return parseDate(value, fmt, new Date())
41
+ } catch {
42
+ return null
43
+ }
44
+ }
45
+
46
+ // Convert a Date back to the same shape as the original value.
47
+ function formatValue (date: Date, original: Date | string | number): Date | string | number {
48
+ if (original instanceof Date) return date
49
+ if (typeof original === 'number') return date.getTime()
50
+ const fmt = props.valueFormat
51
+ if (!fmt || fmt === 'iso') return date.toISOString()
52
+ if (fmt === 'timestamp') return date.getTime()
53
+ if (fmt === 'format') return original
54
+ try {
55
+ return formatDate(date, fmt)
56
+ } catch {
57
+ return original
58
+ }
59
+ }
60
+
61
+ // Normalize the time portion to start/end of day so the range is inclusive.
62
+ // For date-only patterns (e.g. 'yyyy-MM-dd') the output is unchanged since the
63
+ // formatted string carries no time component — the round-trip just preserves it.
64
+ function normalizeTimeOfDay (
65
+ value: Date | string | number | null,
66
+ end: boolean,
67
+ ): Date | string | number | null {
68
+ if (value == null) return value
69
+ const date = parseValue(value)
70
+ if (!date || Number.isNaN(date.getTime())) return value
71
+ date.setHours(end ? 23 : 0, end ? 59 : 0, end ? 59 : 0, end ? 999 : 0)
72
+ return formatValue(date, value)
73
+ }
74
+
30
75
  const start = computed({
31
76
  get: () => props.start,
32
- set: value => emit('update:start', value),
77
+ set: value => emit('update:start', props.showTime ? value : normalizeTimeOfDay(value, false)),
33
78
  })
34
79
 
35
80
  const end = computed({
36
81
  get: () => props.end,
37
- set: value => {
38
- // When time is disabled, normalize end to end of day so range is inclusive
39
- if (value instanceof Date && !props.showTime) {
40
- const adjusted = new Date(value)
41
- adjusted.setHours(23, 59, 59, 999)
42
- emit('update:end', adjusted)
43
- } else {
44
- emit('update:end', value)
45
- }
46
- },
82
+ set: value => emit('update:end', props.showTime ? value : normalizeTimeOfDay(value, true)),
47
83
  })
48
84
 
49
85
  function addDays (date: Date, days: number): Date {
@@ -52,9 +88,10 @@ function addDays (date: Date, days: number): Date {
52
88
  return result
53
89
  }
54
90
 
55
- function toDate (value: Date | string | null | undefined): Date | undefined {
56
- if (!value) return undefined
57
- return value instanceof Date ? value : new Date(value)
91
+ function toDate (value: Date | string | number | null | undefined): Date | undefined {
92
+ if (value == null) return undefined
93
+ if (value instanceof Date) return value
94
+ return parseValue(value) ?? undefined
58
95
  }
59
96
 
60
97
  const startMinDate = computed(() => {
@@ -1,8 +1,16 @@
1
1
  import type { DatePickerTimeConfig } from '../DatePicker/types'
2
2
 
3
3
  export interface DateRangePickerProps {
4
- start?: Date | string | null
5
- end?: Date | string | null
4
+ /**
5
+ * Range start. When `showTime` is false, the emitted value is normalized to
6
+ * the start of the day (00:00:00.000) so the range is inclusive.
7
+ */
8
+ start?: Date | string | number | null
9
+ /**
10
+ * Range end. When `showTime` is false, the emitted value is normalized to
11
+ * the end of the day (23:59:59.999) so the range is inclusive.
12
+ */
13
+ end?: Date | string | number | null
6
14
  /** Minimum selectable date */
7
15
  minDate?: Date | string
8
16
  /** Maximum selectable date */
@@ -19,7 +27,11 @@ export interface DateRangePickerProps {
19
27
  endPlaceholder?: string
20
28
  /** Maximum span in days between start and end date */
21
29
  maxSpanDays?: number
22
- /** v-model output format (e.g. 'yyyy-MM-dd', 'timestamp', 'iso') */
30
+ /**
31
+ * v-model output format. Accepts any VueDatePicker `model-type` value:
32
+ * `'iso'`, `'timestamp'`, or a date-fns pattern (e.g. `'yyyy-MM-dd'`).
33
+ * Omit to bind a `Date` object.
34
+ */
23
35
  valueFormat?: string
24
36
  /** Auto apply selection without confirm button */
25
37
  autoApply?: boolean
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polymarbot/nuxt-layer-shadcn-ui",
3
- "version": "0.8.6",
3
+ "version": "0.8.7",
4
4
  "description": "Nuxt layer providing shadcn-vue based UI components",
5
5
  "type": "module",
6
6
  "main": "./nuxt.config.ts",
@@ -42,5 +42,5 @@
42
42
  "vue-i18n": "^11",
43
43
  "vue-router": "^4 || ^5"
44
44
  },
45
- "gitHead": "c2aa82c36486efc10b9d5723fcd49bb764f473d9"
45
+ "gitHead": "1f8a4521c7e52de4063c33f47888be48cc99329b"
46
46
  }