@coreui/vue-pro 4.10.4 → 4.11.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coreui/vue-pro",
3
- "version": "4.10.4",
3
+ "version": "4.11.1",
4
4
  "description": "UI Components Library for Vue.js",
5
5
  "keywords": [
6
6
  "vue",
@@ -24,9 +24,7 @@ const CCalendar = defineComponent({
24
24
  /**
25
25
  * Default date of the component
26
26
  */
27
- calendarDate: {
28
- type: [Date, String],
29
- },
27
+ calendarDate: [Date, String],
30
28
  /**
31
29
  * The number of calendars that render on desktop devices.
32
30
  */
@@ -66,9 +64,7 @@ const CCalendar = defineComponent({
66
64
  /**
67
65
  * Initial selected to date (range).
68
66
  */
69
- endDate: {
70
- type: [Date, String],
71
- },
67
+ endDate: [Date, String],
72
68
  /**
73
69
  * Sets the day of start week.
74
70
  * - 0 - Sunday,
@@ -93,15 +89,11 @@ const CCalendar = defineComponent({
93
89
  /**
94
90
  * Max selectable date.
95
91
  */
96
- maxDate: {
97
- type: [Date, String],
98
- },
92
+ maxDate: [Date, String],
99
93
  /**
100
94
  * Min selectable date.
101
95
  */
102
- minDate: {
103
- type: [Date, String],
104
- },
96
+ minDate: [Date, String],
105
97
  /**
106
98
  * Show arrows navigation.
107
99
  */
@@ -141,9 +133,7 @@ const CCalendar = defineComponent({
141
133
  /**
142
134
  * Initial selected date.
143
135
  */
144
- startDate: {
145
- type: [Date, String],
146
- },
136
+ startDate: [Date, String],
147
137
  /**
148
138
  * Set length or format of day name.
149
139
  *
@@ -240,8 +230,9 @@ const CCalendar = defineComponent({
240
230
  watch(
241
231
  () => props.maxDate,
242
232
  () => {
243
- if (props.maxDate) {
244
- maxDate.value = new Date(props.maxDate)
233
+ const date = props.maxDate ? new Date(props.maxDate) : null
234
+ if (!isSameDateAs(date, maxDate.value)) {
235
+ maxDate.value = date
245
236
  }
246
237
  },
247
238
  )
@@ -249,8 +240,9 @@ const CCalendar = defineComponent({
249
240
  watch(
250
241
  () => props.minDate,
251
242
  () => {
252
- if (props.minDate) {
253
- minDate.value = new Date(props.minDate)
243
+ const date = props.minDate ? new Date(props.minDate) : null
244
+ if (!isSameDateAs(date, minDate.value)) {
245
+ minDate.value = date
254
246
  }
255
247
  },
256
248
  )
@@ -198,6 +198,7 @@ export const isDateDisabled = (
198
198
  disabled = true
199
199
  }
200
200
  }
201
+
201
202
  if (_date instanceof Date) {
202
203
  if (isSameDateAs(date, _date)) {
203
204
  disabled = true
@@ -205,6 +206,7 @@ export const isDateDisabled = (
205
206
  }
206
207
  })
207
208
  }
209
+
208
210
  if (min && date < min) {
209
211
  disabled = true
210
212
  }
@@ -212,6 +214,7 @@ export const isDateDisabled = (
212
214
  if (max && date > max) {
213
215
  disabled = true
214
216
  }
217
+
215
218
  return disabled
216
219
  }
217
220
 
@@ -8,8 +8,8 @@ import { CFormControlWrapper } from './../form/CFormControlWrapper'
8
8
  import { CPicker } from '../picker'
9
9
  import { CTimePicker } from '../time-picker'
10
10
 
11
+ import { useDebouncedCallback } from '../../composables'
11
12
  import { getLocalDateFromString } from './utils'
12
-
13
13
  import { Color } from '../props'
14
14
 
15
15
  const CDateRangePicker = defineComponent({
@@ -212,6 +212,27 @@ const CDateRangePicker = defineComponent({
212
212
  type: Boolean,
213
213
  default: true,
214
214
  },
215
+ /**
216
+ * Custom function to format the selected date into a string according to a custom format.
217
+ *
218
+ * @since v4.11.0
219
+ */
220
+ inputDateFormat: Function,
221
+ /**
222
+ * Custom function to parse the input value into a valid Date object.
223
+ *
224
+ * @since v4.11.0
225
+ */
226
+ inputDateParse: Function,
227
+ /**
228
+ * Defines the delay (in milliseconds) for the input field's onChange event.
229
+ *
230
+ * @since v4.11.0
231
+ */
232
+ inputOnChangeDelay: {
233
+ type: Number,
234
+ default: 750,
235
+ },
215
236
  /**
216
237
  * Toggle the readonly state for the component.
217
238
  */
@@ -474,8 +495,8 @@ const CDateRangePicker = defineComponent({
474
495
  const endDate = ref<Date | null>(props.endDate ? new Date(props.endDate) : null)
475
496
  const initialStartDate = ref<Date | null>(startDate.value ? new Date(startDate.value) : null)
476
497
  const initialEndDate = ref<Date | null>(endDate.value ? new Date(endDate.value) : null)
477
- const maxDate = ref(props.maxDate && new Date(props.maxDate))
478
- const minDate = ref(props.minDate && new Date(props.minDate))
498
+ const maxDate = ref<Date | null>(props.maxDate ? new Date(props.maxDate) : null)
499
+ const minDate = ref<Date | null>(props.minDate ? new Date(props.minDate) : null)
479
500
  const selectEndDate = ref(false)
480
501
  const isValid = ref<boolean | undefined>(
481
502
  props.valid ?? (props.invalid === true ? false : undefined),
@@ -496,40 +517,30 @@ const CDateRangePicker = defineComponent({
496
517
  watch(
497
518
  () => props.startDate,
498
519
  () => {
499
- if (props.startDate) {
500
- const date = new Date(props.startDate)
501
- calendarDate.value = date
502
- startDate.value = date
503
- }
520
+ calendarDate.value = props.startDate ? new Date(props.startDate) : new Date()
521
+ startDate.value = props.startDate ? new Date(props.startDate) : null
504
522
  },
505
523
  )
506
524
 
507
525
  watch(
508
526
  () => props.endDate,
509
527
  () => {
510
- if (props.endDate) {
511
- const date = new Date(props.endDate)
512
- calendarDate.value = date
513
- endDate.value = date
514
- }
528
+ calendarDate.value = props.endDate ? new Date(props.endDate) : new Date()
529
+ endDate.value = props.endDate ? new Date(props.endDate) : null
515
530
  },
516
531
  )
517
532
 
518
533
  watch(
519
534
  () => props.maxDate,
520
535
  () => {
521
- if (props.maxDate) {
522
- maxDate.value = new Date(props.maxDate)
523
- }
536
+ maxDate.value = props.maxDate ? new Date(props.maxDate) : null
524
537
  },
525
538
  )
526
539
 
527
540
  watch(
528
541
  () => props.minDate,
529
542
  () => {
530
- if (props.minDate) {
531
- minDate.value = new Date(props.minDate)
532
- }
543
+ minDate.value = props.minDate ? new Date(props.minDate) : null
533
544
  },
534
545
  )
535
546
 
@@ -550,7 +561,9 @@ const CDateRangePicker = defineComponent({
550
561
  })
551
562
 
552
563
  const formatDate = (date: Date) => {
553
- return props.format
564
+ return props.inputDateFormat
565
+ ? props.inputDateFormat(date)
566
+ : props.format
554
567
  ? dateFormat(date, props.format)
555
568
  : props.timepicker
556
569
  ? date.toLocaleString(props.locale)
@@ -645,6 +658,20 @@ const CDateRangePicker = defineComponent({
645
658
  emit('update:end-date', null)
646
659
  }
647
660
 
661
+ const handleOnChange = (value: string, input: string) => {
662
+ const date = props.inputDateParse
663
+ ? props.inputDateParse(value)
664
+ : getLocalDateFromString(value, props.locale, props.timepicker)
665
+ if (date instanceof Date && date.getTime()) {
666
+ calendarDate.value = date
667
+ if (input === 'start') {
668
+ startDate.value = date
669
+ } else {
670
+ endDate.value = date
671
+ }
672
+ }
673
+ }
674
+
648
675
  const InputGroup = () =>
649
676
  h(
650
677
  'div',
@@ -671,17 +698,13 @@ const CDateRangePicker = defineComponent({
671
698
  onClick: () => {
672
699
  selectEndDate.value = false
673
700
  },
674
- onInput: (event: Event) => {
675
- const date = getLocalDateFromString(
676
- (event.target as HTMLInputElement).value,
677
- props.locale,
678
- props.timepicker,
679
- )
680
- if (date instanceof Date && date.getTime()) {
681
- calendarDate.value = date
682
- startDate.value = date
683
- }
684
- },
701
+ onChange: (event: Event) =>
702
+ handleOnChange((event.target as HTMLInputElement).value, 'start'),
703
+ onInput: (event: Event) =>
704
+ useDebouncedCallback(
705
+ () => handleOnChange((event.target as HTMLInputElement).value, 'start'),
706
+ props.inputOnChangeDelay,
707
+ ),
685
708
  placeholder: Array.isArray(props.placeholder)
686
709
  ? props.placeholder[0]
687
710
  : props.placeholder,
@@ -715,17 +738,13 @@ const CDateRangePicker = defineComponent({
715
738
  onClick: () => {
716
739
  selectEndDate.value = true
717
740
  },
718
- onInput: (event: Event) => {
719
- const date = getLocalDateFromString(
720
- (event.target as HTMLInputElement).value,
721
- props.locale,
722
- props.timepicker,
723
- )
724
- if (date instanceof Date && date.getTime()) {
725
- calendarDate.value = date
726
- endDate.value = date
727
- }
728
- },
741
+ onChange: (event: Event) =>
742
+ handleOnChange((event.target as HTMLInputElement).value, 'end'),
743
+ onInput: (event: Event) =>
744
+ useDebouncedCallback(
745
+ () => handleOnChange((event.target as HTMLInputElement).value, 'end'),
746
+ props.inputOnChangeDelay,
747
+ ),
729
748
  placeholder: props.placeholder[1],
730
749
  readonly: props.inputReadOnly || typeof props.format === 'string',
731
750
  required: props.required,
@@ -907,8 +926,8 @@ const CDateRangePicker = defineComponent({
907
926
  ...(endDate.value && { endDate: endDate.value }),
908
927
  firstDayOfWeek: props.firstDayOfWeek,
909
928
  locale: props.locale,
910
- maxDate: maxDate.value,
911
- minDate: minDate.value,
929
+ ...(maxDate.value && { maxDate: maxDate.value }),
930
+ ...(minDate.value && { minDate: minDate.value }),
912
931
  navYearFirst: props.navYearFirst,
913
932
  navigation: props.navigation,
914
933
  range: props.range,
@@ -1,4 +1,6 @@
1
- import { defineComponent, h, onUpdated, PropType, ref } from 'vue'
1
+ import { defineComponent, h, onUpdated, PropType, ref, watch } from 'vue'
2
+
3
+ import { useIsVisible } from '../../composables'
2
4
 
3
5
  export interface Element {
4
6
  value: number | string
@@ -19,17 +21,29 @@ const CTimePickerRollCol = defineComponent({
19
21
  emits: ['click'],
20
22
  setup(props, { emit }) {
21
23
  const init = ref(true)
22
- const colRef = ref<HTMLDivElement>()
24
+ const colRef = ref<HTMLElement>()
25
+ const isVisible = useIsVisible(colRef)
23
26
 
24
- onUpdated(() => {
27
+ const scrollToSelectedElement = () => {
25
28
  const nodeEl = colRef.value?.querySelector('.selected')
26
- if (nodeEl && nodeEl instanceof HTMLElement) {
29
+ if (isVisible.value && nodeEl && nodeEl instanceof HTMLElement) {
27
30
  colRef.value?.scrollTo({
28
31
  top: nodeEl.offsetTop,
29
32
  behavior: init.value ? 'auto' : 'smooth',
30
33
  })
31
34
  }
32
- init.value = false
35
+ }
36
+
37
+ watch(isVisible, () => {
38
+ scrollToSelectedElement()
39
+
40
+ if (isVisible.value) {
41
+ init.value = false
42
+ }
43
+ })
44
+
45
+ onUpdated(() => {
46
+ scrollToSelectedElement()
33
47
  })
34
48
 
35
49
  const handleKeyDown = (event: KeyboardEvent, value: number | string) => {
@@ -94,7 +94,7 @@ const CVirtualScroller = defineComponent({
94
94
  }),
95
95
  },
96
96
  ref: (node) => {
97
- if (node && (node as HTMLElement).offsetHeight) {
97
+ if (itemHeight.value === 0 && node && (node as HTMLElement).offsetHeight) {
98
98
  itemHeight.value =
99
99
  (node as HTMLElement).offsetHeight +
100
100
  Number.parseFloat(getComputedStyle(node as HTMLElement).marginTop) +
@@ -1,3 +1,5 @@
1
+ import { useDebouncedCallback } from './useDebouncedCallback'
2
+ import { useIsVisible } from './useIsVisible'
1
3
  import { usePopper } from './usePopper'
2
4
 
3
- export { usePopper }
5
+ export { useDebouncedCallback, useIsVisible, usePopper }
@@ -0,0 +1,16 @@
1
+ import { ref } from 'vue'
2
+
3
+ export const useDebouncedCallback = <F extends Function>(callback: F, delay: number) => {
4
+ const timeout = ref<ReturnType<typeof setTimeout>>()
5
+ const debouncedFn = (...args: any[]) => {
6
+ const handler = () => {
7
+ clearTimeout(timeout.value)
8
+ callback(...args)
9
+ }
10
+
11
+ clearTimeout(timeout.value)
12
+ timeout.value = setTimeout(handler, delay)
13
+ }
14
+
15
+ return debouncedFn()
16
+ }
@@ -0,0 +1,19 @@
1
+ import { onMounted, onUnmounted, ref, Ref } from 'vue'
2
+
3
+ export const useIsVisible = (el: Ref<HTMLElement | undefined>) => {
4
+ const isIntersecting = ref(false)
5
+ const observer = ref()
6
+
7
+ onMounted(() => {
8
+ observer.value = new IntersectionObserver(([entry]) => {
9
+ isIntersecting.value = entry.isIntersecting
10
+ })
11
+ el.value && observer.value.observe(el.value)
12
+ })
13
+
14
+ onUnmounted(() => {
15
+ observer.value.disconnect()
16
+ })
17
+
18
+ return isIntersecting
19
+ }