bge-ui 1.3.4 → 1.3.6

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.
Files changed (135) hide show
  1. package/dist/datePicker/components/ActionRow.vue.d.ts +1051 -0
  2. package/dist/datePicker/components/Common/ArrowBtn.vue.d.ts +29 -0
  3. package/dist/datePicker/components/Common/InstanceWrap.vue.d.ts +29 -0
  4. package/dist/datePicker/components/Common/SelectionOverlay.vue.d.ts +55 -0
  5. package/dist/datePicker/components/DatePicker/DatePicker.vue.d.ts +1114 -0
  6. package/dist/datePicker/components/DatePicker/DpCalendar.vue.d.ts +1085 -0
  7. package/dist/datePicker/components/DatePicker/DpHeader.vue.d.ts +1103 -0
  8. package/dist/datePicker/components/DatePicker/date-picker.d.ts +35 -0
  9. package/dist/datePicker/components/DatepickerInput.vue.d.ts +1008 -0
  10. package/dist/datePicker/components/DatepickerMenu.vue.d.ts +1061 -0
  11. package/dist/datePicker/components/Icons/CalendarIcon.d.ts +9 -0
  12. package/dist/datePicker/components/Icons/CancelIcon.d.ts +9 -0
  13. package/dist/datePicker/components/Icons/ChevronDownIcon.d.ts +9 -0
  14. package/dist/datePicker/components/Icons/ChevronLeftIcon.d.ts +9 -0
  15. package/dist/datePicker/components/Icons/ChevronRightIcon.d.ts +9 -0
  16. package/dist/datePicker/components/Icons/ChevronUpIcon.d.ts +9 -0
  17. package/dist/datePicker/components/Icons/ClockIcon.d.ts +9 -0
  18. package/dist/datePicker/components/Icons/index.d.ts +7 -0
  19. package/dist/datePicker/components/MonthPicker/MonthPicker.vue.d.ts +1071 -0
  20. package/dist/datePicker/components/MonthPicker/month-picker.d.ts +34 -0
  21. package/dist/datePicker/components/QuarterPicker/QuarterPicker.vue.d.ts +1043 -0
  22. package/dist/datePicker/components/QuarterPicker/quarter-picker.d.ts +25 -0
  23. package/dist/datePicker/components/TimePicker/TimeInput.vue.d.ts +1116 -0
  24. package/dist/datePicker/components/TimePicker/TimePicker.vue.d.ts +1087 -0
  25. package/dist/datePicker/components/TimePicker/TimePickerSolo.vue.d.ts +1036 -0
  26. package/dist/datePicker/components/TimePicker/time-picker-utils.d.ts +15 -0
  27. package/dist/datePicker/components/TimePicker/time-picker.d.ts +13 -0
  28. package/dist/datePicker/components/YearPicker/YearPicker.vue.d.ts +1040 -0
  29. package/dist/datePicker/components/YearPicker/year-picker.d.ts +9 -0
  30. package/dist/datePicker/components/shared/YearModePicker.vue.d.ts +1075 -0
  31. package/dist/datePicker/components/shared/month-quarter-picker.d.ts +29 -0
  32. package/dist/datePicker/composables/arrow-navigate.d.ts +26 -0
  33. package/dist/datePicker/composables/calendar-class.d.ts +8 -0
  34. package/dist/datePicker/composables/common.d.ts +6 -0
  35. package/dist/datePicker/composables/defaults.d.ts +37 -0
  36. package/dist/datePicker/composables/external-internal-mapper.d.ts +14 -0
  37. package/dist/datePicker/composables/flow.d.ts +10 -0
  38. package/dist/datePicker/composables/index.d.ts +14 -0
  39. package/dist/datePicker/composables/model.d.ts +17 -0
  40. package/dist/datePicker/composables/month-year.d.ts +10 -0
  41. package/dist/datePicker/composables/position.d.ts +25 -0
  42. package/dist/datePicker/composables/shared.d.ts +12 -0
  43. package/dist/datePicker/composables/slots.d.ts +10 -0
  44. package/dist/datePicker/composables/state.d.ts +8 -0
  45. package/dist/datePicker/composables/transition.d.ts +7 -0
  46. package/dist/datePicker/composables/validation.d.ts +12 -0
  47. package/dist/datePicker/constants/index.d.ts +43 -0
  48. package/dist/datePicker/datePicker.vue.d.ts +1006 -0
  49. package/dist/datePicker/directives/clickOutside.d.ts +2 -0
  50. package/dist/datePicker/index.vue.d.ts +1012 -0
  51. package/dist/datePicker/interfaces.d.ts +323 -0
  52. package/dist/datePicker/props.d.ts +865 -0
  53. package/dist/datePicker/utils/date-utils.d.ts +45 -0
  54. package/dist/datePicker/utils/defaults.d.ts +42 -0
  55. package/dist/datePicker/utils/timezone.d.ts +8 -0
  56. package/dist/datePicker/utils/type-guard.d.ts +1 -0
  57. package/dist/datePicker/utils/util.d.ts +57 -0
  58. package/dist/dialog/index.vue.d.ts +6 -3
  59. package/dist/index.d.ts +2 -1
  60. package/dist/index.js +13008 -1250
  61. package/dist/style.css +1188 -1
  62. package/dist/tooltip/index.vue.d.ts +2 -2
  63. package/dist/tooltip/usePopper.d.ts +5 -5
  64. package/package.json +3 -2
  65. package/src/datePicker/components/ActionRow.vue +216 -0
  66. package/src/datePicker/components/Common/ArrowBtn.vue +42 -0
  67. package/src/datePicker/components/Common/InstanceWrap.vue +28 -0
  68. package/src/datePicker/components/Common/SelectionOverlay.vue +320 -0
  69. package/src/datePicker/components/DatePicker/DatePicker.vue +302 -0
  70. package/src/datePicker/components/DatePicker/DpCalendar.vue +405 -0
  71. package/src/datePicker/components/DatePicker/DpHeader.vue +332 -0
  72. package/src/datePicker/components/DatePicker/date-picker.ts +674 -0
  73. package/src/datePicker/components/DatepickerInput.vue +334 -0
  74. package/src/datePicker/components/DatepickerMenu.vue +424 -0
  75. package/src/datePicker/components/Icons/CalendarIcon.ts +40 -0
  76. package/src/datePicker/components/Icons/CancelIcon.ts +32 -0
  77. package/src/datePicker/components/Icons/ChevronDownIcon.ts +29 -0
  78. package/src/datePicker/components/Icons/ChevronLeftIcon.ts +29 -0
  79. package/src/datePicker/components/Icons/ChevronRightIcon.ts +29 -0
  80. package/src/datePicker/components/Icons/ChevronUpIcon.ts +29 -0
  81. package/src/datePicker/components/Icons/ClockIcon.ts +32 -0
  82. package/src/datePicker/components/Icons/index.ts +8 -0
  83. package/src/datePicker/components/MonthPicker/MonthPicker.vue +130 -0
  84. package/src/datePicker/components/MonthPicker/month-picker.ts +232 -0
  85. package/src/datePicker/components/QuarterPicker/QuarterPicker.vue +111 -0
  86. package/src/datePicker/components/QuarterPicker/quarter-picker.ts +153 -0
  87. package/src/datePicker/components/TimePicker/TimeInput.vue +477 -0
  88. package/src/datePicker/components/TimePicker/TimePicker.vue +265 -0
  89. package/src/datePicker/components/TimePicker/TimePickerSolo.vue +79 -0
  90. package/src/datePicker/components/TimePicker/time-picker-utils.ts +179 -0
  91. package/src/datePicker/components/TimePicker/time-picker.ts +112 -0
  92. package/src/datePicker/components/YearPicker/YearPicker.vue +70 -0
  93. package/src/datePicker/components/YearPicker/year-picker.ts +109 -0
  94. package/src/datePicker/components/shared/YearModePicker.vue +105 -0
  95. package/src/datePicker/components/shared/month-quarter-picker.ts +199 -0
  96. package/src/datePicker/composables/arrow-navigate.ts +191 -0
  97. package/src/datePicker/composables/calendar-class.ts +383 -0
  98. package/src/datePicker/composables/common.ts +25 -0
  99. package/src/datePicker/composables/defaults.ts +123 -0
  100. package/src/datePicker/composables/external-internal-mapper.ts +442 -0
  101. package/src/datePicker/composables/flow.ts +70 -0
  102. package/src/datePicker/composables/index.ts +14 -0
  103. package/src/datePicker/composables/model.ts +89 -0
  104. package/src/datePicker/composables/month-year.ts +72 -0
  105. package/src/datePicker/composables/position.ts +297 -0
  106. package/src/datePicker/composables/shared.ts +98 -0
  107. package/src/datePicker/composables/slots.ts +84 -0
  108. package/src/datePicker/composables/state.ts +25 -0
  109. package/src/datePicker/composables/transition.ts +18 -0
  110. package/src/datePicker/composables/validation.ts +312 -0
  111. package/src/datePicker/constants/index.ts +49 -0
  112. package/src/datePicker/datePicker.vue +554 -0
  113. package/src/datePicker/directives/clickOutside.ts +79 -0
  114. package/src/datePicker/index.vue +158 -0
  115. package/src/datePicker/interfaces.ts +404 -0
  116. package/src/datePicker/props.ts +173 -0
  117. package/src/datePicker/style/components/_ActionRow.scss +73 -0
  118. package/src/datePicker/style/components/_Calendar.scss +284 -0
  119. package/src/datePicker/style/components/_DatepickerInput.scss +109 -0
  120. package/src/datePicker/style/components/_DatepickerMenu.scss +213 -0
  121. package/src/datePicker/style/components/_MonthYearInput.scss +97 -0
  122. package/src/datePicker/style/components/_QuarterPicker.scss +53 -0
  123. package/src/datePicker/style/components/_SelectionOverlay.scss +142 -0
  124. package/src/datePicker/style/components/_TimeInput.scss +181 -0
  125. package/src/datePicker/style/components/_shared.scss +15 -0
  126. package/src/datePicker/style/main.scss +259 -0
  127. package/src/datePicker/utils/date-utils.ts +440 -0
  128. package/src/datePicker/utils/defaults.ts +327 -0
  129. package/src/datePicker/utils/timezone.ts +38 -0
  130. package/src/datePicker/utils/type-guard.ts +3 -0
  131. package/src/datePicker/utils/util.ts +322 -0
  132. package/src/dialog/index.vue +9 -0
  133. package/src/form/index.vue +2 -1
  134. package/src/index.ts +6 -2
  135. package/src/slider/index.vue +1 -1
@@ -0,0 +1,554 @@
1
+ <template>
2
+ <div ref="pickerWrapperRef" :class="wrapperClass" data-datepicker-instance>
3
+ <DatepickerInput
4
+ ref="inputRef"
5
+ v-model:input-value="inputValue"
6
+ :is-menu-open="isOpen"
7
+ v-bind="$props"
8
+ @clear="clearValue"
9
+ @open="openMenu"
10
+ @set-input-date="setInputDate"
11
+ @set-empty-date="emitModelValue"
12
+ @select-date="selectDate"
13
+ @toggle="toggleMenu"
14
+ @close="closeMenu"
15
+ @focus="handleInputFocus"
16
+ @blur="handleBlur"
17
+ @real-blur="isInputFocused = false"
18
+ @text-input="$emit('text-input', $event)"
19
+ >
20
+ <template v-for="(slot, i) in inputSlots" #[slot]="args" :key="i">
21
+ <slot :name="slot" v-bind="args" />
22
+ </template>
23
+ </DatepickerInput>
24
+ <component :is="teleport ? TeleportCmp : 'div'" v-bind="teleportProps">
25
+ <transition :name="menuTransition(openOnTop)" :css="showTransition && !defaultedInline.enabled">
26
+ <div
27
+ v-if="isOpen"
28
+ ref="dpWrapMenuRef"
29
+ v-bind="menuWrapProps"
30
+ :class="{ 'dp--menu-wrapper': !defaultedInline.enabled }"
31
+ :style="!defaultedInline.enabled ? menuStyle : undefined"
32
+ >
33
+ <DatepickerMenu
34
+ ref="dpMenuRef"
35
+ v-bind="$props"
36
+ v-model:internal-model-value="internalModelValue"
37
+ :class="{ [theme]: true, 'dp--menu-wrapper': teleport }"
38
+ :open-on-top="openOnTop"
39
+ :no-overlay-focus="noOverlayFocus"
40
+ :collapse="collapse"
41
+ :get-input-rect="getInputRect"
42
+ :is-text-input-date="isTextInputDate"
43
+ @close-picker="closeMenu"
44
+ @select-date="selectDate"
45
+ @auto-apply="autoApplyValue"
46
+ @time-update="timeUpdate"
47
+ @flow-step="$emit('flow-step', $event)"
48
+ @update-month-year="$emit('update-month-year', $event)"
49
+ @invalid-select="$emit('invalid-select', internalModelValue)"
50
+ @auto-apply-invalid="$emit('invalid-select', $event)"
51
+ @invalid-fixed-range="$emit('invalid-fixed-range', $event)"
52
+ @recalculate-position="setMenuPosition"
53
+ @tooltip-open="$emit('tooltip-open', $event)"
54
+ @tooltip-close="$emit('tooltip-close', $event)"
55
+ @time-picker-open="$emit('time-picker-open', $event)"
56
+ @time-picker-close="$emit('time-picker-close', $event)"
57
+ @am-pm-change="$emit('am-pm-change', $event)"
58
+ @range-start="$emit('range-start', $event)"
59
+ @range-end="$emit('range-end', $event)"
60
+ @date-update="$emit('date-update', $event)"
61
+ @invalid-date="$emit('invalid-date', $event)"
62
+ @overlay-toggle="$emit('overlay-toggle', $event)"
63
+ >
64
+ <template v-for="(slot, i) in slotList" #[slot]="args" :key="i">
65
+ <slot :name="slot" v-bind="{ ...args }" />
66
+ </template>
67
+ </DatepickerMenu>
68
+ </div>
69
+ </transition>
70
+ </component>
71
+ </div>
72
+ </template>
73
+
74
+ <script lang="ts" setup>
75
+ import {
76
+ computed,
77
+ onMounted,
78
+ onUnmounted,
79
+ ref,
80
+ toRef,
81
+ useSlots,
82
+ watch,
83
+ Teleport as TeleportCmp,
84
+ nextTick,
85
+ } from 'vue';
86
+
87
+ import DatepickerInput from './components/DatepickerInput.vue';
88
+ import DatepickerMenu from './components/DatepickerMenu.vue';
89
+
90
+ import {
91
+ useExternalInternalMapper,
92
+ usePosition,
93
+ mapSlots,
94
+ useArrowNavigation,
95
+ useState,
96
+ useTransitions,
97
+ useValidation,
98
+ } from './composables';
99
+ import { onClickOutside } from './directives/clickOutside';
100
+ import { AllProps } from './props';
101
+ import { findNextFocusableElement, getNumVal } from './utils/util';
102
+
103
+ import type {
104
+ DynamicClass,
105
+ MonthYearOpt,
106
+ DatepickerMenuRef,
107
+ DatepickerInputRef,
108
+ ModelValue,
109
+ MenuView,
110
+ MaybeElementRef,
111
+ } from './interfaces';
112
+ import { useDefaults } from './composables/defaults';
113
+
114
+ const emit = defineEmits([
115
+ 'input-value',
116
+ 'update:model-value',
117
+ 'update:model-timezone-value',
118
+ 'text-submit',
119
+ 'closed',
120
+ 'cleared',
121
+ 'open',
122
+ 'focus',
123
+ 'blur',
124
+ 'internal-model-change',
125
+ 'recalculate-position',
126
+ 'flow-step',
127
+ 'update-month-year',
128
+ 'invalid-select',
129
+ 'invalid-fixed-range',
130
+ 'tooltip-open',
131
+ 'tooltip-close',
132
+ 'time-picker-open',
133
+ 'time-picker-close',
134
+ 'am-pm-change',
135
+ 'range-start',
136
+ 'range-end',
137
+ 'date-update',
138
+ 'invalid-date',
139
+ 'overlay-toggle',
140
+ 'text-input',
141
+ ]);
142
+
143
+ defineOptions({
144
+ compatConfig: {
145
+ MODE: 3,
146
+ },
147
+ });
148
+
149
+ const props = defineProps({
150
+ ...AllProps,
151
+ });
152
+ const slots = useSlots();
153
+ const isOpen = ref(false);
154
+ const modelValueRef = toRef(props, 'modelValue');
155
+ const timezoneRef = toRef(props, 'timezone');
156
+ const dpWrapMenuRef = ref<HTMLElement | null>(null);
157
+ const dpMenuRef = ref<DatepickerMenuRef | null>(null);
158
+ const inputRef = ref<DatepickerInputRef | null>(null);
159
+ const isInputFocused = ref(false);
160
+ const pickerWrapperRef = ref<HTMLElement | null>(null);
161
+ const shouldFocusNext = ref(false);
162
+ const shiftKeyActive = ref(false);
163
+ const collapse = ref(false);
164
+ const isTextInputDate = ref(false);
165
+
166
+ const { setMenuFocused, setShiftKey } = useState();
167
+ const { clearArrowNav } = useArrowNavigation();
168
+ const { validateDate, isValidTime } = useValidation(props);
169
+ const {
170
+ defaultedTransitions,
171
+ defaultedTextInput,
172
+ defaultedInline,
173
+ defaultedConfig,
174
+ defaultedRange,
175
+ defaultedMultiDates,
176
+ } = useDefaults(props);
177
+ const { menuTransition, showTransition } = useTransitions(defaultedTransitions);
178
+
179
+ onMounted(() => {
180
+ parseExternalModelValue(props.modelValue);
181
+ nextTick().then(() => {
182
+ if (!defaultedInline.value.enabled) {
183
+ const el = getScrollableParent(pickerWrapperRef.value);
184
+ el?.addEventListener('scroll', onScroll);
185
+
186
+ window?.addEventListener('resize', onResize);
187
+ }
188
+ });
189
+
190
+ if (defaultedInline.value.enabled) {
191
+ isOpen.value = true;
192
+ }
193
+
194
+ window?.addEventListener('keyup', onKeyUp);
195
+ window?.addEventListener('keydown', onKeyDown);
196
+ });
197
+
198
+ onUnmounted(() => {
199
+ if (!defaultedInline.value.enabled) {
200
+ const el = getScrollableParent(pickerWrapperRef.value);
201
+ el?.removeEventListener('scroll', onScroll);
202
+ window?.removeEventListener('resize', onResize);
203
+ }
204
+ window?.removeEventListener('keyup', onKeyUp);
205
+ window?.removeEventListener('keydown', onKeyDown);
206
+ });
207
+
208
+ const slotList = mapSlots(slots, 'all', props.presetDates);
209
+ const inputSlots = mapSlots(slots, 'input');
210
+
211
+ watch(
212
+ [modelValueRef, timezoneRef],
213
+ () => {
214
+ parseExternalModelValue(modelValueRef.value);
215
+ },
216
+ { deep: true },
217
+ );
218
+
219
+ const { openOnTop, menuStyle, xCorrect, setMenuPosition, getScrollableParent, shadowRender } = usePosition({
220
+ menuRef: dpWrapMenuRef,
221
+ menuRefInner: dpMenuRef,
222
+ inputRef,
223
+ pickerWrapperRef,
224
+ inline: defaultedInline,
225
+ emit,
226
+ props,
227
+ slots,
228
+ });
229
+
230
+ const {
231
+ inputValue,
232
+ internalModelValue,
233
+ parseExternalModelValue,
234
+ emitModelValue,
235
+ formatInputValue,
236
+ checkBeforeEmit,
237
+ } = useExternalInternalMapper(emit, props, isInputFocused);
238
+
239
+ const wrapperClass = computed(
240
+ (): DynamicClass => ({
241
+ dp__main: true,
242
+ dp__theme_dark: props.dark,
243
+ dp__theme_light: !props.dark,
244
+ dp__flex_display: defaultedInline.value.enabled,
245
+ 'dp--flex-display-collapsed': collapse.value,
246
+ dp__flex_display_with_input: defaultedInline.value.input,
247
+ }),
248
+ );
249
+
250
+ const theme = computed(() => (props.dark ? 'dp__theme_dark' : 'dp__theme_light'));
251
+ const teleportProps = computed(() => {
252
+ return props.teleport
253
+ ? {
254
+ to: typeof props.teleport === 'boolean' ? 'body' : props.teleport,
255
+ disabled: !props.teleport || defaultedInline.value.enabled,
256
+ }
257
+ : {};
258
+ });
259
+ const menuWrapProps = computed(() => {
260
+ return { class: 'dp__outer_menu_wrap' };
261
+ });
262
+
263
+ const noOverlayFocus = computed(() => {
264
+ return (
265
+ defaultedInline.value.enabled &&
266
+ (props.timePicker || props.monthPicker || props.yearPicker || props.quarterPicker)
267
+ );
268
+ });
269
+
270
+ const getInputRect = () => {
271
+ return inputRef.value?.$el?.getBoundingClientRect();
272
+ };
273
+
274
+ /**
275
+ * Event listener for 'scroll'
276
+ * Depending on the props, it can close the menu or set correct position
277
+ */
278
+ const onScroll = (): void => {
279
+ if (isOpen.value) {
280
+ if (defaultedConfig.value.closeOnScroll) {
281
+ closeMenu();
282
+ } else {
283
+ setMenuPosition();
284
+ }
285
+ }
286
+ };
287
+
288
+ /**
289
+ * Event listener for 'resize'
290
+ * Since the menu is absolutely positioned, on window resize, correct positioning
291
+ */
292
+ const onResize = (): void => {
293
+ if (isOpen.value) {
294
+ setMenuPosition();
295
+ }
296
+ const width = dpMenuRef.value?.$el.getBoundingClientRect().width;
297
+ collapse.value = document.body.offsetWidth <= width;
298
+ };
299
+
300
+ const onKeyUp = (event: KeyboardEvent) => {
301
+ if (
302
+ event.key === 'Tab' &&
303
+ !defaultedInline.value.enabled &&
304
+ !props.teleport &&
305
+ defaultedConfig.value.tabOutClosesMenu
306
+ ) {
307
+ if (!pickerWrapperRef.value!.contains(document.activeElement)) {
308
+ closeMenu();
309
+ }
310
+ }
311
+
312
+ shiftKeyActive.value = event.shiftKey;
313
+ };
314
+
315
+ const onKeyDown = (event: KeyboardEvent) => {
316
+ shiftKeyActive.value = event.shiftKey;
317
+ };
318
+
319
+ const openMenu = () => {
320
+ if (!props.disabled && !props.readonly) {
321
+ shadowRender(DatepickerMenu, props);
322
+ setMenuPosition(false);
323
+ isOpen.value = true;
324
+
325
+ if (isOpen.value) {
326
+ emit('open');
327
+ }
328
+
329
+ if (!isOpen.value) {
330
+ clearInternalValues();
331
+ }
332
+
333
+ parseExternalModelValue(props.modelValue);
334
+ }
335
+ };
336
+
337
+ /**
338
+ * When x button is pressed on input, it will call this function that will emit null
339
+ * for the modelValue and clear internally stored data
340
+ */
341
+ const clearValue = (): void => {
342
+ inputValue.value = '';
343
+ clearInternalValues();
344
+ inputRef.value?.setParsedDate(null);
345
+ emit('update:model-value', null);
346
+ emit('update:model-timezone-value', null);
347
+ emit('cleared');
348
+ if (defaultedConfig.value.closeOnClearValue) {
349
+ closeMenu();
350
+ }
351
+ };
352
+
353
+ const validateBeforeEmit = () => {
354
+ const date = internalModelValue.value;
355
+ if (!date) return true;
356
+ if (!Array.isArray(date) && validateDate(date)) return true;
357
+ if (Array.isArray(date)) {
358
+ if (defaultedMultiDates.value.enabled) return true;
359
+
360
+ if (date.length === 2 && validateDate(date[0]) && validateDate(date[1])) {
361
+ return true;
362
+ }
363
+ if (defaultedRange.value.partialRange && !props.timePicker) return validateDate(date[0]);
364
+ return false;
365
+ }
366
+ return false;
367
+ };
368
+
369
+ /**
370
+ * Called when select button is clicked, emit update for the modelValue
371
+ */
372
+ const selectDate = (): void => {
373
+ if (checkBeforeEmit() && validateBeforeEmit()) {
374
+ emitModelValue();
375
+ closeMenu();
376
+ } else {
377
+ emit('invalid-select', internalModelValue.value);
378
+ }
379
+ };
380
+
381
+ const emitOnAutoApply = (ignoreClose: boolean): void => {
382
+ updateTextInputWithDateTimeValue();
383
+ emitModelValue();
384
+ if (defaultedConfig.value.closeOnAutoApply && !ignoreClose) {
385
+ closeMenu();
386
+ }
387
+ };
388
+
389
+ const updateTextInputWithDateTimeValue = () => {
390
+ if (inputRef.value && defaultedTextInput.value.enabled) {
391
+ inputRef.value.setParsedDate(internalModelValue.value);
392
+ }
393
+ };
394
+
395
+ /**
396
+ * When value is selected it will emit an event that will call this function
397
+ * ignoreClose is passed when time is picked or month and year, since they update the value and for
398
+ * the user experience it should not close the menu
399
+ */
400
+ const autoApplyValue = (ignoreClose = false): void => {
401
+ if (props.autoApply) {
402
+ const isTimeValid = isValidTime(internalModelValue.value);
403
+
404
+ if (isTimeValid && validateBeforeEmit()) {
405
+ if (defaultedRange.value.enabled && Array.isArray(internalModelValue.value)) {
406
+ if (defaultedRange.value.partialRange || internalModelValue.value.length === 2) {
407
+ emitOnAutoApply(ignoreClose);
408
+ }
409
+ } else {
410
+ emitOnAutoApply(ignoreClose);
411
+ }
412
+ }
413
+ }
414
+ };
415
+
416
+ /**
417
+ * Clears the internally stored values. This is different from clearValue since it does not emit v-model
418
+ * update, just clears internal data
419
+ */
420
+ const clearInternalValues = (): void => {
421
+ if (!defaultedTextInput.value.enabled) {
422
+ internalModelValue.value = null;
423
+ }
424
+ };
425
+
426
+ /**
427
+ * Closes the menu and clears the internal data
428
+ */
429
+ const closeMenu = (): void => {
430
+ if (!defaultedInline.value.enabled) {
431
+ if (isOpen.value) {
432
+ isOpen.value = false;
433
+ xCorrect.value = false;
434
+ setMenuFocused(false);
435
+ setShiftKey(false);
436
+ clearArrowNav();
437
+ emit('closed');
438
+ if (inputValue.value) {
439
+ parseExternalModelValue(modelValueRef.value);
440
+ }
441
+ }
442
+ clearInternalValues();
443
+ emit('blur');
444
+ }
445
+ };
446
+
447
+ const setInputDate = (date: Date | Date[] | null, submit?: boolean, tabbed = false): void => {
448
+ if (!date) {
449
+ internalModelValue.value = null;
450
+ return;
451
+ }
452
+ const validDate = Array.isArray(date) ? !date.some((d) => !validateDate(d)) : validateDate(date);
453
+ const validTime = isValidTime(date);
454
+ if (validDate && validTime) {
455
+ isTextInputDate.value = true;
456
+ internalModelValue.value = date;
457
+ if (submit) {
458
+ shouldFocusNext.value = tabbed;
459
+ selectDate();
460
+ emit('text-submit');
461
+ }
462
+ nextTick().then(() => {
463
+ isTextInputDate.value = false;
464
+ });
465
+ }
466
+ };
467
+
468
+ const timeUpdate = (): void => {
469
+ if (props.autoApply && isValidTime(internalModelValue.value)) {
470
+ emitModelValue();
471
+ }
472
+ updateTextInputWithDateTimeValue();
473
+ };
474
+
475
+ const toggleMenu = () => {
476
+ if (isOpen.value) return closeMenu();
477
+ return openMenu();
478
+ };
479
+
480
+ const updateInternalModelValue = (value: Date | Date[]): void => {
481
+ internalModelValue.value = value;
482
+ };
483
+
484
+ const handleInputFocus = () => {
485
+ if (defaultedTextInput.value.enabled) {
486
+ isInputFocused.value = true;
487
+ formatInputValue();
488
+ }
489
+
490
+ emit('focus');
491
+ };
492
+
493
+ const handleBlur = () => {
494
+ if (defaultedTextInput.value.enabled) {
495
+ isInputFocused.value = false;
496
+ parseExternalModelValue(props.modelValue);
497
+ if (shouldFocusNext.value) {
498
+ const el = findNextFocusableElement(pickerWrapperRef.value!, shiftKeyActive.value);
499
+ el?.focus();
500
+ }
501
+ }
502
+ emit('blur');
503
+ };
504
+
505
+ const setMonthYear = (value: MonthYearOpt) => {
506
+ if (dpMenuRef.value) {
507
+ dpMenuRef.value.updateMonthYear(0, {
508
+ month: getNumVal(value.month) as number,
509
+ year: getNumVal(value.year) as number,
510
+ });
511
+ }
512
+ };
513
+
514
+ const parseModel = (value?: ModelValue) => {
515
+ parseExternalModelValue(value ?? props.modelValue);
516
+ };
517
+
518
+ const switchView = (view: MenuView, instance?: number) => {
519
+ dpMenuRef.value?.switchView(view, instance);
520
+ };
521
+
522
+ const clickOutside = (validateBeforeEmit: () => boolean) => {
523
+ if (defaultedConfig.value.onClickOutside) return defaultedConfig.value.onClickOutside(validateBeforeEmit);
524
+ return closeMenu();
525
+ };
526
+
527
+ const handleFlow = (skipStep = 0) => {
528
+ dpMenuRef.value?.handleFlow(skipStep);
529
+ };
530
+
531
+ watch(inputValue, () => {
532
+ emit('input-value', inputValue.value)
533
+ })
534
+
535
+
536
+
537
+ onClickOutside(dpWrapMenuRef, inputRef as unknown as MaybeElementRef, () => clickOutside(validateBeforeEmit));
538
+
539
+ defineExpose({
540
+ closeMenu,
541
+ selectDate,
542
+ clearValue,
543
+ openMenu,
544
+ onScroll,
545
+ formatInputValue, // exposed for testing purposes
546
+ updateInternalModelValue, // modify internal modelValue
547
+ setMonthYear,
548
+ parseModel,
549
+ switchView,
550
+ toggleMenu,
551
+ handleFlow,
552
+ dpWrapMenuRef,
553
+ });
554
+ </script>
@@ -0,0 +1,79 @@
1
+ // Following code is a port of @vueuse/core clickOutside hook
2
+ import { unref, watch, getCurrentScope, onScopeDispose } from 'vue';
3
+
4
+ import type { Fn, MaybeElementRef, MaybeRef, OnClickOutsideEvents, OnClickOutsideOptions } from '../interfaces';
5
+ import { unrefElement } from '../utils/util';
6
+
7
+ const defaultWindow = typeof window !== 'undefined' ? window : undefined;
8
+
9
+ const noop = () => {
10
+ return;
11
+ };
12
+
13
+ const tryOnScopeDispose = (fn: Fn): boolean => {
14
+ if (getCurrentScope()) {
15
+ onScopeDispose(fn);
16
+ return true;
17
+ }
18
+ return false;
19
+ };
20
+
21
+ const useEventListener = (
22
+ target: MaybeRef<EventTarget> | undefined,
23
+ event: string,
24
+ listener: EventListener,
25
+ options: Record<string, boolean>,
26
+ ): (() => void) => {
27
+ if (!target) return noop;
28
+
29
+ let cleanup = noop;
30
+
31
+ const stopWatch = watch(
32
+ () => unref(target),
33
+ (el) => {
34
+ cleanup();
35
+ if (!el) return;
36
+
37
+ el.addEventListener(event, listener, options);
38
+
39
+ cleanup = () => {
40
+ el.removeEventListener(event, listener, options);
41
+ cleanup = noop;
42
+ };
43
+ },
44
+ { immediate: true, flush: 'post' },
45
+ );
46
+
47
+ const stop = () => {
48
+ stopWatch();
49
+ cleanup();
50
+ };
51
+
52
+ tryOnScopeDispose(stop);
53
+
54
+ return stop;
55
+ };
56
+
57
+ export const onClickOutside = <E extends keyof OnClickOutsideEvents = 'pointerdown'>(
58
+ target: MaybeElementRef,
59
+ inputRef: MaybeElementRef,
60
+ handler: (evt: OnClickOutsideEvents[E]) => void,
61
+ options: OnClickOutsideOptions<E> = {},
62
+ ): (() => void) | undefined => {
63
+ const { window = defaultWindow, event = 'pointerdown' } = options;
64
+
65
+ if (!window) return;
66
+
67
+ const listener = (event: OnClickOutsideEvents[E]) => {
68
+ const el = unrefElement(target);
69
+ const inputEl = unrefElement(inputRef);
70
+
71
+ if (!el || !inputEl) return;
72
+
73
+ if (el === event.target || event.composedPath().includes(el) || event.composedPath().includes(inputEl)) return;
74
+
75
+ handler(event);
76
+ };
77
+
78
+ return useEventListener(window, event, listener as EventListener, { passive: true });
79
+ };