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.
- package/dist/datePicker/components/ActionRow.vue.d.ts +1051 -0
- package/dist/datePicker/components/Common/ArrowBtn.vue.d.ts +29 -0
- package/dist/datePicker/components/Common/InstanceWrap.vue.d.ts +29 -0
- package/dist/datePicker/components/Common/SelectionOverlay.vue.d.ts +55 -0
- package/dist/datePicker/components/DatePicker/DatePicker.vue.d.ts +1114 -0
- package/dist/datePicker/components/DatePicker/DpCalendar.vue.d.ts +1085 -0
- package/dist/datePicker/components/DatePicker/DpHeader.vue.d.ts +1103 -0
- package/dist/datePicker/components/DatePicker/date-picker.d.ts +35 -0
- package/dist/datePicker/components/DatepickerInput.vue.d.ts +1008 -0
- package/dist/datePicker/components/DatepickerMenu.vue.d.ts +1061 -0
- package/dist/datePicker/components/Icons/CalendarIcon.d.ts +9 -0
- package/dist/datePicker/components/Icons/CancelIcon.d.ts +9 -0
- package/dist/datePicker/components/Icons/ChevronDownIcon.d.ts +9 -0
- package/dist/datePicker/components/Icons/ChevronLeftIcon.d.ts +9 -0
- package/dist/datePicker/components/Icons/ChevronRightIcon.d.ts +9 -0
- package/dist/datePicker/components/Icons/ChevronUpIcon.d.ts +9 -0
- package/dist/datePicker/components/Icons/ClockIcon.d.ts +9 -0
- package/dist/datePicker/components/Icons/index.d.ts +7 -0
- package/dist/datePicker/components/MonthPicker/MonthPicker.vue.d.ts +1071 -0
- package/dist/datePicker/components/MonthPicker/month-picker.d.ts +34 -0
- package/dist/datePicker/components/QuarterPicker/QuarterPicker.vue.d.ts +1043 -0
- package/dist/datePicker/components/QuarterPicker/quarter-picker.d.ts +25 -0
- package/dist/datePicker/components/TimePicker/TimeInput.vue.d.ts +1116 -0
- package/dist/datePicker/components/TimePicker/TimePicker.vue.d.ts +1087 -0
- package/dist/datePicker/components/TimePicker/TimePickerSolo.vue.d.ts +1036 -0
- package/dist/datePicker/components/TimePicker/time-picker-utils.d.ts +15 -0
- package/dist/datePicker/components/TimePicker/time-picker.d.ts +13 -0
- package/dist/datePicker/components/YearPicker/YearPicker.vue.d.ts +1040 -0
- package/dist/datePicker/components/YearPicker/year-picker.d.ts +9 -0
- package/dist/datePicker/components/shared/YearModePicker.vue.d.ts +1075 -0
- package/dist/datePicker/components/shared/month-quarter-picker.d.ts +29 -0
- package/dist/datePicker/composables/arrow-navigate.d.ts +26 -0
- package/dist/datePicker/composables/calendar-class.d.ts +8 -0
- package/dist/datePicker/composables/common.d.ts +6 -0
- package/dist/datePicker/composables/defaults.d.ts +37 -0
- package/dist/datePicker/composables/external-internal-mapper.d.ts +14 -0
- package/dist/datePicker/composables/flow.d.ts +10 -0
- package/dist/datePicker/composables/index.d.ts +14 -0
- package/dist/datePicker/composables/model.d.ts +17 -0
- package/dist/datePicker/composables/month-year.d.ts +10 -0
- package/dist/datePicker/composables/position.d.ts +25 -0
- package/dist/datePicker/composables/shared.d.ts +12 -0
- package/dist/datePicker/composables/slots.d.ts +10 -0
- package/dist/datePicker/composables/state.d.ts +8 -0
- package/dist/datePicker/composables/transition.d.ts +7 -0
- package/dist/datePicker/composables/validation.d.ts +12 -0
- package/dist/datePicker/constants/index.d.ts +43 -0
- package/dist/datePicker/datePicker.vue.d.ts +1006 -0
- package/dist/datePicker/directives/clickOutside.d.ts +2 -0
- package/dist/datePicker/index.vue.d.ts +1012 -0
- package/dist/datePicker/interfaces.d.ts +323 -0
- package/dist/datePicker/props.d.ts +865 -0
- package/dist/datePicker/utils/date-utils.d.ts +45 -0
- package/dist/datePicker/utils/defaults.d.ts +42 -0
- package/dist/datePicker/utils/timezone.d.ts +8 -0
- package/dist/datePicker/utils/type-guard.d.ts +1 -0
- package/dist/datePicker/utils/util.d.ts +57 -0
- package/dist/dialog/index.vue.d.ts +6 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.js +13008 -1250
- package/dist/style.css +1188 -1
- package/dist/tooltip/index.vue.d.ts +2 -2
- package/dist/tooltip/usePopper.d.ts +5 -5
- package/package.json +3 -2
- package/src/datePicker/components/ActionRow.vue +216 -0
- package/src/datePicker/components/Common/ArrowBtn.vue +42 -0
- package/src/datePicker/components/Common/InstanceWrap.vue +28 -0
- package/src/datePicker/components/Common/SelectionOverlay.vue +320 -0
- package/src/datePicker/components/DatePicker/DatePicker.vue +302 -0
- package/src/datePicker/components/DatePicker/DpCalendar.vue +405 -0
- package/src/datePicker/components/DatePicker/DpHeader.vue +332 -0
- package/src/datePicker/components/DatePicker/date-picker.ts +674 -0
- package/src/datePicker/components/DatepickerInput.vue +334 -0
- package/src/datePicker/components/DatepickerMenu.vue +424 -0
- package/src/datePicker/components/Icons/CalendarIcon.ts +40 -0
- package/src/datePicker/components/Icons/CancelIcon.ts +32 -0
- package/src/datePicker/components/Icons/ChevronDownIcon.ts +29 -0
- package/src/datePicker/components/Icons/ChevronLeftIcon.ts +29 -0
- package/src/datePicker/components/Icons/ChevronRightIcon.ts +29 -0
- package/src/datePicker/components/Icons/ChevronUpIcon.ts +29 -0
- package/src/datePicker/components/Icons/ClockIcon.ts +32 -0
- package/src/datePicker/components/Icons/index.ts +8 -0
- package/src/datePicker/components/MonthPicker/MonthPicker.vue +130 -0
- package/src/datePicker/components/MonthPicker/month-picker.ts +232 -0
- package/src/datePicker/components/QuarterPicker/QuarterPicker.vue +111 -0
- package/src/datePicker/components/QuarterPicker/quarter-picker.ts +153 -0
- package/src/datePicker/components/TimePicker/TimeInput.vue +477 -0
- package/src/datePicker/components/TimePicker/TimePicker.vue +265 -0
- package/src/datePicker/components/TimePicker/TimePickerSolo.vue +79 -0
- package/src/datePicker/components/TimePicker/time-picker-utils.ts +179 -0
- package/src/datePicker/components/TimePicker/time-picker.ts +112 -0
- package/src/datePicker/components/YearPicker/YearPicker.vue +70 -0
- package/src/datePicker/components/YearPicker/year-picker.ts +109 -0
- package/src/datePicker/components/shared/YearModePicker.vue +105 -0
- package/src/datePicker/components/shared/month-quarter-picker.ts +199 -0
- package/src/datePicker/composables/arrow-navigate.ts +191 -0
- package/src/datePicker/composables/calendar-class.ts +383 -0
- package/src/datePicker/composables/common.ts +25 -0
- package/src/datePicker/composables/defaults.ts +123 -0
- package/src/datePicker/composables/external-internal-mapper.ts +442 -0
- package/src/datePicker/composables/flow.ts +70 -0
- package/src/datePicker/composables/index.ts +14 -0
- package/src/datePicker/composables/model.ts +89 -0
- package/src/datePicker/composables/month-year.ts +72 -0
- package/src/datePicker/composables/position.ts +297 -0
- package/src/datePicker/composables/shared.ts +98 -0
- package/src/datePicker/composables/slots.ts +84 -0
- package/src/datePicker/composables/state.ts +25 -0
- package/src/datePicker/composables/transition.ts +18 -0
- package/src/datePicker/composables/validation.ts +312 -0
- package/src/datePicker/constants/index.ts +49 -0
- package/src/datePicker/datePicker.vue +554 -0
- package/src/datePicker/directives/clickOutside.ts +79 -0
- package/src/datePicker/index.vue +158 -0
- package/src/datePicker/interfaces.ts +404 -0
- package/src/datePicker/props.ts +173 -0
- package/src/datePicker/style/components/_ActionRow.scss +73 -0
- package/src/datePicker/style/components/_Calendar.scss +284 -0
- package/src/datePicker/style/components/_DatepickerInput.scss +109 -0
- package/src/datePicker/style/components/_DatepickerMenu.scss +213 -0
- package/src/datePicker/style/components/_MonthYearInput.scss +97 -0
- package/src/datePicker/style/components/_QuarterPicker.scss +53 -0
- package/src/datePicker/style/components/_SelectionOverlay.scss +142 -0
- package/src/datePicker/style/components/_TimeInput.scss +181 -0
- package/src/datePicker/style/components/_shared.scss +15 -0
- package/src/datePicker/style/main.scss +259 -0
- package/src/datePicker/utils/date-utils.ts +440 -0
- package/src/datePicker/utils/defaults.ts +327 -0
- package/src/datePicker/utils/timezone.ts +38 -0
- package/src/datePicker/utils/type-guard.ts +3 -0
- package/src/datePicker/utils/util.ts +322 -0
- package/src/dialog/index.vue +9 -0
- package/src/form/index.vue +2 -1
- package/src/index.ts +6 -2
- package/src/slider/index.vue +1 -1
|
@@ -114,8 +114,8 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
|
|
|
114
114
|
toggleTooltip: import("vue").Ref<any>;
|
|
115
115
|
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
116
116
|
transition: (...args: any[]) => void;
|
|
117
|
-
opened: (...args: any[]) => void;
|
|
118
117
|
closed: (...args: any[]) => void;
|
|
118
|
+
opened: (...args: any[]) => void;
|
|
119
119
|
}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
|
|
120
120
|
/**
|
|
121
121
|
* title
|
|
@@ -225,9 +225,9 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
|
|
|
225
225
|
validator(value: unknown): boolean;
|
|
226
226
|
};
|
|
227
227
|
}>> & {
|
|
228
|
+
onClosed?: ((...args: any[]) => any) | undefined;
|
|
228
229
|
onTransition?: ((...args: any[]) => any) | undefined;
|
|
229
230
|
onOpened?: ((...args: any[]) => any) | undefined;
|
|
230
|
-
onClosed?: ((...args: any[]) => any) | undefined;
|
|
231
231
|
}, {
|
|
232
232
|
size: string;
|
|
233
233
|
type: string;
|
|
@@ -172,23 +172,23 @@ declare const usePopper: (triggerReference: any, suppliedOptions?: Options) => {
|
|
|
172
172
|
};
|
|
173
173
|
} | undefined;
|
|
174
174
|
offset?: {
|
|
175
|
-
|
|
175
|
+
left?: {
|
|
176
176
|
y: number;
|
|
177
177
|
x: number;
|
|
178
178
|
} | undefined;
|
|
179
|
-
|
|
179
|
+
right?: {
|
|
180
180
|
y: number;
|
|
181
181
|
x: number;
|
|
182
182
|
} | undefined;
|
|
183
|
-
|
|
183
|
+
top?: {
|
|
184
184
|
y: number;
|
|
185
185
|
x: number;
|
|
186
186
|
} | undefined;
|
|
187
|
-
|
|
187
|
+
bottom?: {
|
|
188
188
|
y: number;
|
|
189
189
|
x: number;
|
|
190
190
|
} | undefined;
|
|
191
|
-
|
|
191
|
+
auto?: {
|
|
192
192
|
y: number;
|
|
193
193
|
x: number;
|
|
194
194
|
} | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bge-ui",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.6",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"tsx": "^4.6.2",
|
|
28
28
|
"vite-plugin-dts": "^3.6.4",
|
|
29
29
|
"vue": "^3.3.9",
|
|
30
|
-
"bignumber.js": "^9.1.2"
|
|
30
|
+
"bignumber.js": "^9.1.2",
|
|
31
|
+
"date-fns": "^3.6.0"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
34
|
"@types/node": "^20.10.1"
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div ref="actionRowRef" class="dp__action_row">
|
|
3
|
+
<template v-if="$slots['action-row']">
|
|
4
|
+
<slot
|
|
5
|
+
name="action-row"
|
|
6
|
+
v-bind="{
|
|
7
|
+
internalModelValue,
|
|
8
|
+
disabled,
|
|
9
|
+
selectDate: () => $emit('select-date'),
|
|
10
|
+
closePicker: () => $emit('close-picker'),
|
|
11
|
+
}"
|
|
12
|
+
/>
|
|
13
|
+
</template>
|
|
14
|
+
<template v-else>
|
|
15
|
+
<div
|
|
16
|
+
v-if="defaultedActionRow.showPreview"
|
|
17
|
+
class="dp__selection_preview"
|
|
18
|
+
:title="formatValue"
|
|
19
|
+
:style="previewStyle"
|
|
20
|
+
>
|
|
21
|
+
<slot
|
|
22
|
+
v-if="$slots['action-preview'] && showPreview"
|
|
23
|
+
name="action-preview"
|
|
24
|
+
:value="internalModelValue"
|
|
25
|
+
/>
|
|
26
|
+
<template v-if="!$slots['action-preview'] && showPreview">
|
|
27
|
+
{{ formatValue }}
|
|
28
|
+
</template>
|
|
29
|
+
</div>
|
|
30
|
+
<div ref="actionBtnContainer" class="dp__action_buttons" data-dp-element="action-row">
|
|
31
|
+
<slot v-if="$slots['action-buttons']" name="action-buttons" :value="internalModelValue" />
|
|
32
|
+
<template v-if="!$slots['action-buttons']">
|
|
33
|
+
<button
|
|
34
|
+
v-if="!defaultedInline.enabled && defaultedActionRow.showCancel"
|
|
35
|
+
ref="cancelButtonRef"
|
|
36
|
+
type="button"
|
|
37
|
+
class="dp__action_button dp__action_cancel"
|
|
38
|
+
@click="$emit('close-picker')"
|
|
39
|
+
@keydown="checkKeyDown($event, () => $emit('close-picker'))"
|
|
40
|
+
>
|
|
41
|
+
{{ cancelText }}
|
|
42
|
+
</button>
|
|
43
|
+
<button
|
|
44
|
+
v-if="defaultedActionRow.showNow"
|
|
45
|
+
type="button"
|
|
46
|
+
class="dp__action_button dp__action_cancel"
|
|
47
|
+
@click="$emit('select-now')"
|
|
48
|
+
@keydown="checkKeyDown($event, () => $emit('select-now'))"
|
|
49
|
+
>
|
|
50
|
+
{{ nowButtonLabel }}
|
|
51
|
+
</button>
|
|
52
|
+
<button
|
|
53
|
+
v-if="defaultedActionRow.showSelect"
|
|
54
|
+
ref="selectButtonRef"
|
|
55
|
+
type="button"
|
|
56
|
+
class="dp__action_button dp__action_select"
|
|
57
|
+
:disabled="disabled"
|
|
58
|
+
data-test="select-button"
|
|
59
|
+
@keydown="checkKeyDown($event, () => selectDate())"
|
|
60
|
+
@click="selectDate"
|
|
61
|
+
>
|
|
62
|
+
{{ selectText }}
|
|
63
|
+
</button>
|
|
64
|
+
</template>
|
|
65
|
+
</div>
|
|
66
|
+
</template>
|
|
67
|
+
</div>
|
|
68
|
+
</template>
|
|
69
|
+
|
|
70
|
+
<script lang="ts" setup>
|
|
71
|
+
import { computed, onMounted, onUnmounted, ref } from 'vue';
|
|
72
|
+
|
|
73
|
+
import { checkKeyDown, convertType, unrefElement } from '../utils/util';
|
|
74
|
+
import { useArrowNavigation, useDefaults, useValidation } from '../composables';
|
|
75
|
+
import { PickerBaseProps } from '../props';
|
|
76
|
+
import { formatDate } from '../utils/date-utils';
|
|
77
|
+
|
|
78
|
+
import type { PropType } from 'vue';
|
|
79
|
+
|
|
80
|
+
defineOptions({
|
|
81
|
+
compatConfig: {
|
|
82
|
+
MODE: 3,
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const emit = defineEmits(['close-picker', 'select-date', 'select-now', 'invalid-select']);
|
|
87
|
+
|
|
88
|
+
const props = defineProps({
|
|
89
|
+
menuMount: { type: Boolean as PropType<boolean>, default: false },
|
|
90
|
+
calendarWidth: { type: Number as PropType<number>, default: 0 },
|
|
91
|
+
...PickerBaseProps,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const {
|
|
95
|
+
defaultedActionRow,
|
|
96
|
+
defaultedPreviewFormat,
|
|
97
|
+
defaultedMultiCalendars,
|
|
98
|
+
defaultedTextInput,
|
|
99
|
+
defaultedInline,
|
|
100
|
+
defaultedRange,
|
|
101
|
+
defaultedMultiDates,
|
|
102
|
+
} = useDefaults(props);
|
|
103
|
+
const { isTimeValid, isMonthValid } = useValidation(props);
|
|
104
|
+
const { buildMatrix } = useArrowNavigation();
|
|
105
|
+
|
|
106
|
+
const cancelButtonRef = ref(null);
|
|
107
|
+
const selectButtonRef = ref(null);
|
|
108
|
+
const showPreview = ref(false);
|
|
109
|
+
const previewStyle = ref<any>({});
|
|
110
|
+
const actionBtnContainer = ref<HTMLElement | null>(null);
|
|
111
|
+
const actionRowRef = ref<HTMLElement | null>(null);
|
|
112
|
+
|
|
113
|
+
onMounted(() => {
|
|
114
|
+
if (props.arrowNavigation) {
|
|
115
|
+
buildMatrix([unrefElement(cancelButtonRef), unrefElement(selectButtonRef)] as HTMLElement[], 'actionRow');
|
|
116
|
+
}
|
|
117
|
+
getPreviewAvailableSpace();
|
|
118
|
+
window.addEventListener('resize', getPreviewAvailableSpace);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
onUnmounted(() => {
|
|
122
|
+
window.removeEventListener('resize', getPreviewAvailableSpace);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const getPreviewAvailableSpace = () => {
|
|
126
|
+
showPreview.value = false;
|
|
127
|
+
setTimeout(() => {
|
|
128
|
+
const rect = actionBtnContainer.value?.getBoundingClientRect();
|
|
129
|
+
const rowRect = actionRowRef.value?.getBoundingClientRect();
|
|
130
|
+
if (rect && rowRect) {
|
|
131
|
+
previewStyle.value.maxWidth = `${rowRect.width - rect.width - 20}px`;
|
|
132
|
+
}
|
|
133
|
+
showPreview.value = true;
|
|
134
|
+
}, 0);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const validDateRange = computed(() => {
|
|
138
|
+
return defaultedRange.value.enabled && !defaultedRange.value.partialRange && props.internalModelValue
|
|
139
|
+
? (props.internalModelValue as Date[]).length === 2
|
|
140
|
+
: true;
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
const disabled = computed(
|
|
144
|
+
() =>
|
|
145
|
+
!isTimeValid.value(props.internalModelValue) ||
|
|
146
|
+
!isMonthValid.value(props.internalModelValue) ||
|
|
147
|
+
!validDateRange.value,
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
const handleCustomPreviewFormat = () => {
|
|
151
|
+
const formatFn = defaultedPreviewFormat.value as (val: Date | Date[]) => string | string[];
|
|
152
|
+
|
|
153
|
+
if (props.timePicker) return formatFn(convertType(props.internalModelValue));
|
|
154
|
+
|
|
155
|
+
if (props.monthPicker) return formatFn(convertType(props.internalModelValue as Date));
|
|
156
|
+
|
|
157
|
+
return formatFn(convertType(props.internalModelValue));
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const formatRangeDate = () => {
|
|
161
|
+
const dates = props.internalModelValue as Date[];
|
|
162
|
+
if (defaultedMultiCalendars.value.count > 0) {
|
|
163
|
+
return `${formatDatePreview(dates[0])} - ${formatDatePreview(dates[1])}`;
|
|
164
|
+
}
|
|
165
|
+
return [formatDatePreview(dates[0]), formatDatePreview(dates[1])];
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const formatDatePreview = (date: Date) => {
|
|
169
|
+
return formatDate(
|
|
170
|
+
date,
|
|
171
|
+
defaultedPreviewFormat.value as string,
|
|
172
|
+
props.formatLocale,
|
|
173
|
+
defaultedTextInput.value.rangeSeparator,
|
|
174
|
+
props.modelAuto,
|
|
175
|
+
defaultedPreviewFormat.value as string,
|
|
176
|
+
);
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const previewValue = computed((): string | string[] => {
|
|
180
|
+
if (!props.internalModelValue || !props.menuMount) return '';
|
|
181
|
+
if (typeof defaultedPreviewFormat.value === 'string') {
|
|
182
|
+
if (Array.isArray(props.internalModelValue)) {
|
|
183
|
+
if (props.internalModelValue.length === 2 && props.internalModelValue[1]) {
|
|
184
|
+
return formatRangeDate();
|
|
185
|
+
}
|
|
186
|
+
if (defaultedMultiDates.value.enabled) {
|
|
187
|
+
return props.internalModelValue.map((date) => `${formatDatePreview(date)}`);
|
|
188
|
+
}
|
|
189
|
+
if (props.modelAuto) {
|
|
190
|
+
return `${formatDatePreview(props.internalModelValue[0])}`;
|
|
191
|
+
}
|
|
192
|
+
return `${formatDatePreview(props.internalModelValue[0])} -`;
|
|
193
|
+
}
|
|
194
|
+
return formatDatePreview(props.internalModelValue);
|
|
195
|
+
}
|
|
196
|
+
return handleCustomPreviewFormat();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const dateSeparator = () => (defaultedMultiDates.value.enabled ? '; ' : ' - ');
|
|
200
|
+
|
|
201
|
+
const formatValue = computed(() =>
|
|
202
|
+
!Array.isArray(previewValue.value) ? previewValue.value : previewValue.value.join(dateSeparator()),
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
const selectDate = (): void => {
|
|
206
|
+
if (
|
|
207
|
+
isTimeValid.value(props.internalModelValue) &&
|
|
208
|
+
isMonthValid.value(props.internalModelValue) &&
|
|
209
|
+
validDateRange.value
|
|
210
|
+
) {
|
|
211
|
+
emit('select-date');
|
|
212
|
+
} else {
|
|
213
|
+
emit('invalid-select');
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
</script>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<button
|
|
3
|
+
ref="elRef"
|
|
4
|
+
type="button"
|
|
5
|
+
:data-dp-element="elName"
|
|
6
|
+
class="dp__btn dp--arrow-btn-nav"
|
|
7
|
+
tabindex="0"
|
|
8
|
+
:aria-label="ariaLabel"
|
|
9
|
+
:aria-disabled="disabled || undefined"
|
|
10
|
+
@click="$emit('activate')"
|
|
11
|
+
@keydown="checkKeyDown($event, () => $emit('activate'), true)"
|
|
12
|
+
>
|
|
13
|
+
<span class="dp__inner_nav" :class="{ dp__inner_nav_disabled: disabled }">
|
|
14
|
+
<slot />
|
|
15
|
+
</span>
|
|
16
|
+
</button>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script lang="ts" setup>
|
|
20
|
+
import { onMounted, ref } from 'vue';
|
|
21
|
+
import { checkKeyDown } from '../../utils/util';
|
|
22
|
+
|
|
23
|
+
defineOptions({
|
|
24
|
+
compatConfig: {
|
|
25
|
+
MODE: 3,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const emit = defineEmits(['activate', 'set-ref']);
|
|
30
|
+
|
|
31
|
+
interface Props {
|
|
32
|
+
ariaLabel?: string;
|
|
33
|
+
elName?: string;
|
|
34
|
+
disabled: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
defineProps<Props>();
|
|
38
|
+
|
|
39
|
+
const elRef = ref(null);
|
|
40
|
+
|
|
41
|
+
onMounted(() => emit('set-ref', elRef));
|
|
42
|
+
</script>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
:class="{
|
|
4
|
+
dp__menu_inner: !stretch,
|
|
5
|
+
'dp--menu--inner-stretched': stretch,
|
|
6
|
+
dp__flex_display: multiCalendars > 0,
|
|
7
|
+
'dp--flex-display-collapsed': collapse,
|
|
8
|
+
}"
|
|
9
|
+
>
|
|
10
|
+
<div v-for="(instance, i) in instances" :key="instance" :class="calendarInstanceClassWrapper">
|
|
11
|
+
<slot :instance="instance" :index="i"></slot>
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script lang="ts" setup>
|
|
17
|
+
import { computed } from 'vue';
|
|
18
|
+
|
|
19
|
+
const props = defineProps<{ multiCalendars: number; stretch?: boolean; collapse?: boolean }>();
|
|
20
|
+
|
|
21
|
+
const instances = computed((): number[] =>
|
|
22
|
+
props.multiCalendars > 0 ? [...Array(props.multiCalendars).keys()] : [0],
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
const calendarInstanceClassWrapper = computed(() => ({
|
|
26
|
+
dp__instance_calendar: props.multiCalendars > 0,
|
|
27
|
+
}));
|
|
28
|
+
</script>
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
ref="gridWrapRef"
|
|
4
|
+
:class="dpOverlayClass"
|
|
5
|
+
:style="dpOverlayStyle"
|
|
6
|
+
:role="useRelative ? undefined : 'dialog'"
|
|
7
|
+
:aria-label="overlayLabel"
|
|
8
|
+
:tabindex="useRelative ? undefined : '0'"
|
|
9
|
+
@keydown="onKeyDown"
|
|
10
|
+
@click.prevent
|
|
11
|
+
>
|
|
12
|
+
<div
|
|
13
|
+
ref="containerRef"
|
|
14
|
+
:class="containerClass"
|
|
15
|
+
:style="{ '--dp-overlay-height': `${containerHeight}px` }"
|
|
16
|
+
role="grid"
|
|
17
|
+
>
|
|
18
|
+
<div class="dp__selection_grid_header"><slot name="header"></slot></div>
|
|
19
|
+
<template v-if="$slots.overlay">
|
|
20
|
+
<slot name="overlay" />
|
|
21
|
+
</template>
|
|
22
|
+
<template v-else>
|
|
23
|
+
<div
|
|
24
|
+
v-for="(row, i) in items"
|
|
25
|
+
:key="i"
|
|
26
|
+
class="dp__overlay_row"
|
|
27
|
+
role="row"
|
|
28
|
+
>
|
|
29
|
+
<div
|
|
30
|
+
v-for="(col, ind) in row"
|
|
31
|
+
:key="col.value"
|
|
32
|
+
:ref="(el) => assignRef(el, col, i, ind)"
|
|
33
|
+
role="gridcell"
|
|
34
|
+
:class="cellClassName"
|
|
35
|
+
:aria-selected="col.active || undefined"
|
|
36
|
+
:aria-disabled="col.disabled || undefined"
|
|
37
|
+
tabindex="0"
|
|
38
|
+
:data-test="col.text"
|
|
39
|
+
@click.prevent="onClick(col)"
|
|
40
|
+
@keydown="checkKeyDown($event, () => onClick(col), true)"
|
|
41
|
+
@mouseover="setHoverValue(col.value)"
|
|
42
|
+
>
|
|
43
|
+
<div :class="col.className">
|
|
44
|
+
<slot v-if="$slots.item" name="item" :item="col" />
|
|
45
|
+
<template v-if="!$slots.item">{{ col.text }}</template>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
</template>
|
|
50
|
+
</div>
|
|
51
|
+
<button
|
|
52
|
+
v-if="$slots['button-icon']"
|
|
53
|
+
v-show="!hideNavigationButtons(hideNavigation, type)"
|
|
54
|
+
ref="toggleButton"
|
|
55
|
+
type="button"
|
|
56
|
+
:aria-label="defaultedAriaLabels?.toggleOverlay"
|
|
57
|
+
:class="actionButtonClass"
|
|
58
|
+
tabindex="0"
|
|
59
|
+
@click="toggle"
|
|
60
|
+
@keydown="onBtnKeyDown"
|
|
61
|
+
>
|
|
62
|
+
<slot name="button-icon" />
|
|
63
|
+
</button>
|
|
64
|
+
</div>
|
|
65
|
+
</template>
|
|
66
|
+
|
|
67
|
+
<script lang="ts" setup>
|
|
68
|
+
import { computed, nextTick, onBeforeUpdate, onMounted, onUnmounted, ref, watch } from 'vue';
|
|
69
|
+
|
|
70
|
+
import {
|
|
71
|
+
checkKeyDown,
|
|
72
|
+
checkStopPropagation,
|
|
73
|
+
convertType,
|
|
74
|
+
findFocusableEl,
|
|
75
|
+
getElWithin,
|
|
76
|
+
unrefElement,
|
|
77
|
+
} from '../../utils/util';
|
|
78
|
+
import { useArrowNavigation, useCommon, useDefaults } from '../../composables';
|
|
79
|
+
|
|
80
|
+
import type { AriaLabels, Config, DynamicClass, Flow, OverlayGridItem, TextInputProp } from '../../interfaces';
|
|
81
|
+
import type { PickerBasePropsType } from '../../props';
|
|
82
|
+
import { EventKey } from '../../constants';
|
|
83
|
+
|
|
84
|
+
const { setSelectionGrid, buildMultiLevelMatrix, setMonthPicker } = useArrowNavigation();
|
|
85
|
+
|
|
86
|
+
const emit = defineEmits(['selected', 'toggle', 'reset-flow', 'hover-value']);
|
|
87
|
+
|
|
88
|
+
interface Props {
|
|
89
|
+
items: OverlayGridItem[][];
|
|
90
|
+
type: Flow;
|
|
91
|
+
isLast: boolean;
|
|
92
|
+
arrowNavigation?: boolean;
|
|
93
|
+
skipButtonRef?: boolean;
|
|
94
|
+
headerRefs?: (HTMLElement | null)[];
|
|
95
|
+
hideNavigation?: Flow[];
|
|
96
|
+
escClose?: boolean;
|
|
97
|
+
useRelative?: boolean;
|
|
98
|
+
height?: number | string;
|
|
99
|
+
textInput?: TextInputProp;
|
|
100
|
+
config?: Partial<Config>;
|
|
101
|
+
noOverlayFocus?: boolean;
|
|
102
|
+
focusValue?: number;
|
|
103
|
+
menuWrapRef?: HTMLElement | null;
|
|
104
|
+
ariaLabels?: Partial<AriaLabels>;
|
|
105
|
+
overlayLabel?: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const props = defineProps<Props>();
|
|
109
|
+
|
|
110
|
+
const { defaultedAriaLabels, defaultedTextInput, defaultedConfig } = useDefaults(
|
|
111
|
+
props as unknown as PickerBasePropsType,
|
|
112
|
+
);
|
|
113
|
+
const { hideNavigationButtons } = useCommon();
|
|
114
|
+
|
|
115
|
+
const scrollable = ref(false);
|
|
116
|
+
const selectionActiveRef = ref<HTMLElement | null>(null);
|
|
117
|
+
const gridWrapRef = ref(null);
|
|
118
|
+
const elementRefs = ref<Array<HTMLElement | null>[]>([]);
|
|
119
|
+
const hoverValue = ref();
|
|
120
|
+
const toggleButton = ref<HTMLElement | null>(null);
|
|
121
|
+
const containerHeight = ref(0);
|
|
122
|
+
const containerRef = ref<HTMLElement | null>(null);
|
|
123
|
+
|
|
124
|
+
onBeforeUpdate(() => {
|
|
125
|
+
selectionActiveRef.value = null;
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* On mounted hook, set the scroll position, if any to a selected value when opening overlay
|
|
130
|
+
*/
|
|
131
|
+
onMounted(() => {
|
|
132
|
+
nextTick().then(() => setContainerHeightAndScroll());
|
|
133
|
+
if (!props.noOverlayFocus) {
|
|
134
|
+
focusGrid();
|
|
135
|
+
}
|
|
136
|
+
handleArrowNav(true);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
onUnmounted(() => handleArrowNav(false));
|
|
140
|
+
|
|
141
|
+
const handleArrowNav = (value: boolean): void => {
|
|
142
|
+
if (props.arrowNavigation) {
|
|
143
|
+
if (props.headerRefs?.length) {
|
|
144
|
+
setMonthPicker(value);
|
|
145
|
+
} else {
|
|
146
|
+
setSelectionGrid(value);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const focusGrid = (): void => {
|
|
152
|
+
const elm = unrefElement(gridWrapRef);
|
|
153
|
+
if (elm) {
|
|
154
|
+
if (!defaultedTextInput.value.enabled) {
|
|
155
|
+
if (selectionActiveRef.value) {
|
|
156
|
+
selectionActiveRef.value?.focus({ preventScroll: true });
|
|
157
|
+
} else {
|
|
158
|
+
elm.focus({ preventScroll: true });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
scrollable.value = elm.clientHeight < elm.scrollHeight;
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// Dynamic class for the overlay
|
|
167
|
+
const dpOverlayClass = computed(
|
|
168
|
+
(): DynamicClass => ({
|
|
169
|
+
dp__overlay: true,
|
|
170
|
+
'dp--overlay-absolute': !props.useRelative,
|
|
171
|
+
'dp--overlay-relative': props.useRelative,
|
|
172
|
+
}),
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
const dpOverlayStyle = computed(() =>
|
|
176
|
+
props.useRelative ? { height: `${props.height}px`, width: `var(--dp-menu-min-width)` } : undefined,
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
const cellClassName = computed(() => ({
|
|
180
|
+
dp__overlay_col: true,
|
|
181
|
+
}));
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Dynamic class for action button
|
|
185
|
+
*/
|
|
186
|
+
const actionButtonClass = computed(
|
|
187
|
+
(): DynamicClass => ({
|
|
188
|
+
dp__btn: true,
|
|
189
|
+
dp__button: true,
|
|
190
|
+
dp__overlay_action: true,
|
|
191
|
+
dp__over_action_scroll: scrollable.value,
|
|
192
|
+
dp__button_bottom: props.isLast,
|
|
193
|
+
}),
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
const containerClass = computed(() => ({
|
|
197
|
+
dp__overlay_container: true,
|
|
198
|
+
dp__container_flex: props.items?.length <= 6,
|
|
199
|
+
dp__container_block: props.items?.length > 6,
|
|
200
|
+
}));
|
|
201
|
+
|
|
202
|
+
watch(
|
|
203
|
+
() => props.items,
|
|
204
|
+
() => setContainerHeightAndScroll(false),
|
|
205
|
+
{ deep: true },
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
const setContainerHeightAndScroll = (setScroll = true) => {
|
|
209
|
+
nextTick().then(() => {
|
|
210
|
+
const el = unrefElement(selectionActiveRef);
|
|
211
|
+
const parent = unrefElement(gridWrapRef);
|
|
212
|
+
const btn = unrefElement(toggleButton);
|
|
213
|
+
const container = unrefElement(containerRef);
|
|
214
|
+
const toggleBtnHeight = btn ? btn.getBoundingClientRect().height : 0;
|
|
215
|
+
if (parent) {
|
|
216
|
+
if (!parent.getBoundingClientRect().height) {
|
|
217
|
+
containerHeight.value = defaultedConfig.value.modeHeight - toggleBtnHeight;
|
|
218
|
+
} else {
|
|
219
|
+
containerHeight.value = parent.getBoundingClientRect().height - toggleBtnHeight;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (el && container && setScroll) {
|
|
223
|
+
container.scrollTop =
|
|
224
|
+
el.offsetTop -
|
|
225
|
+
container.offsetTop -
|
|
226
|
+
(containerHeight.value / 2 - el.getBoundingClientRect().height) -
|
|
227
|
+
toggleBtnHeight;
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Handle click on cell, if value is enabled (not in filters), emit value back to parent
|
|
234
|
+
*/
|
|
235
|
+
const onClick = (val: OverlayGridItem): void => {
|
|
236
|
+
if (!val.disabled) {
|
|
237
|
+
emit('selected', val.value);
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const toggle = () => {
|
|
242
|
+
emit('toggle');
|
|
243
|
+
emit('reset-flow');
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const handleEsc = () => {
|
|
247
|
+
if (props.escClose) {
|
|
248
|
+
toggle();
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const assignRef = (el: any, col: OverlayGridItem, rowInd: number, colInd: number): void => {
|
|
253
|
+
if (el) {
|
|
254
|
+
if (col.active || col.value === props.focusValue) {
|
|
255
|
+
selectionActiveRef.value = el;
|
|
256
|
+
}
|
|
257
|
+
if (props.arrowNavigation) {
|
|
258
|
+
if (Array.isArray(elementRefs.value[rowInd])) {
|
|
259
|
+
elementRefs.value[rowInd][colInd] = el;
|
|
260
|
+
} else {
|
|
261
|
+
elementRefs.value[rowInd] = [el];
|
|
262
|
+
}
|
|
263
|
+
buildMatrix();
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const buildMatrix = () => {
|
|
269
|
+
const refs = props.headerRefs?.length
|
|
270
|
+
? [props.headerRefs].concat(elementRefs.value)
|
|
271
|
+
: elementRefs.value.concat([props.skipButtonRef ? [] : [toggleButton.value]]);
|
|
272
|
+
|
|
273
|
+
buildMultiLevelMatrix(convertType(refs), props.headerRefs?.length ? 'monthPicker' : 'selectionGrid');
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
const handleArrowKey = (ev: KeyboardEvent) => {
|
|
277
|
+
if (props.arrowNavigation) return;
|
|
278
|
+
checkStopPropagation(ev, defaultedConfig.value, true);
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
const setHoverValue = (val: number) => {
|
|
282
|
+
hoverValue.value = val;
|
|
283
|
+
emit('hover-value', val);
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
const onTab = () => {
|
|
287
|
+
toggle();
|
|
288
|
+
if (!props.isLast) {
|
|
289
|
+
const actionRow = getElWithin(props.menuWrapRef ?? null, 'action-row');
|
|
290
|
+
if (actionRow) {
|
|
291
|
+
const focusable = findFocusableEl(actionRow);
|
|
292
|
+
focusable?.focus();
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
const onKeyDown = (ev: KeyboardEvent) => {
|
|
298
|
+
switch (ev.key) {
|
|
299
|
+
case EventKey.esc:
|
|
300
|
+
return handleEsc();
|
|
301
|
+
case EventKey.arrowLeft:
|
|
302
|
+
return handleArrowKey(ev);
|
|
303
|
+
case EventKey.arrowRight:
|
|
304
|
+
return handleArrowKey(ev);
|
|
305
|
+
case EventKey.arrowUp:
|
|
306
|
+
return handleArrowKey(ev);
|
|
307
|
+
case EventKey.arrowDown:
|
|
308
|
+
return handleArrowKey(ev);
|
|
309
|
+
default:
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
const onBtnKeyDown = (ev: KeyboardEvent) => {
|
|
315
|
+
if (ev.key === EventKey.enter) return toggle();
|
|
316
|
+
if (ev.key === EventKey.tab) return onTab();
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
defineExpose({ focusGrid });
|
|
320
|
+
</script>
|