design-system-next 2.16.2 → 2.17.4
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/design-system-next.es.js +7569 -6646
- package/dist/design-system-next.es.js.gz +0 -0
- package/dist/design-system-next.umd.js +14 -14
- package/dist/design-system-next.umd.js.gz +0 -0
- package/dist/main.css +1 -1
- package/dist/main.css.gz +0 -0
- package/dist/package.json.d.ts +1 -1
- package/package.json +1 -1
- package/src/App.vue +43 -1642
- package/src/assets/styles/tailwind.css +20 -0
- package/src/components/attribute-filter/attribute-filter.ts +5 -1
- package/src/components/attribute-filter/attribute-filter.vue +3 -3
- package/src/components/calendar/calendar.ts +1 -1
- package/src/components/calendar/calendar.vue +41 -18
- package/src/components/calendar/use-calendar.ts +13 -6
- package/src/components/calendar-cell/calendar-cell.ts +4 -0
- package/src/components/calendar-cell/use-calendar-cell.ts +21 -2
- package/src/components/card/card.ts +5 -0
- package/src/components/card/use-card.ts +15 -3
- package/src/components/date-picker/date-picker.ts +36 -5
- package/src/components/date-picker/date-picker.vue +2 -1
- package/src/components/date-picker/date-range-picker/date-range-picker.ts +14 -6
- package/src/components/date-picker/date-range-picker/date-range-picker.vue +2 -1
- package/src/components/date-picker/reusable-calendar/reusable-calendar.ts +121 -0
- package/src/components/date-picker/reusable-calendar/reusable-calendar.vue +192 -0
- package/src/components/date-picker/reusable-calendar/use-reusable-calendar.ts +366 -0
- package/src/components/date-picker/tabs/DatePickerCalendarTab.vue +321 -0
- package/src/components/date-picker/tabs/DatePickerMonthTab.vue +60 -0
- package/src/components/date-picker/tabs/DatePickerYearTab.vue +114 -0
- package/src/components/dropdown/dropdown.ts +25 -21
- package/src/components/dropdown/dropdown.vue +1 -1
- package/src/components/icon/icon.ts +36 -0
- package/src/components/icon/icon.vue +12 -0
- package/src/components/icon/use-icon.ts +67 -0
- package/src/components/lozenge/lozenge.ts +1 -1
- package/src/components/popper/popper.ts +12 -0
- package/src/components/popper/popper.vue +36 -0
- package/src/components/popper/use-popper.ts +16 -0
- package/src/components/select/select-ladderized/select-ladderized.ts +16 -12
- package/src/components/select/select-ladderized/select-ladderized.vue +1 -1
- package/src/components/select/select-multiple/select-multiple.ts +8 -4
- package/src/components/select/select-multiple/select-multiple.vue +1 -1
- package/src/components/select/select-multiple/use-select-multiple.ts +15 -4
- package/src/components/select/select.ts +4 -0
- package/src/components/select/select.vue +1 -1
|
@@ -269,6 +269,26 @@
|
|
|
269
269
|
@apply spr-min-w-[328px] spr-drop-shadow-md;
|
|
270
270
|
}
|
|
271
271
|
/* #endregion - Filter, time-picker */
|
|
272
|
+
|
|
273
|
+
/* #region - Popper */
|
|
274
|
+
#popper-wrapper {
|
|
275
|
+
@apply spr-border-color-weak spr-border-color-weak spr-z-[1000] spr-w-[inherit] spr-min-w-[240px] spr-rounded-border-radius-xl spr-border spr-border-solid spr-shadow-drop;
|
|
276
|
+
|
|
277
|
+
.v-popper__wrapper {
|
|
278
|
+
.v-popper__inner {
|
|
279
|
+
@apply spr-w-full spr-rounded-border-radius-xl spr-border-none spr-font-main spr-shadow-none;
|
|
280
|
+
|
|
281
|
+
&::-webkit-scrollbar-track {
|
|
282
|
+
@apply spr-rounded-br-xl spr-rounded-tr-xl;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.v-popper__arrow-container {
|
|
287
|
+
@apply spr-hidden;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/* #endregion - Popper */
|
|
272
292
|
}
|
|
273
293
|
|
|
274
294
|
@layer utilities {
|
|
@@ -103,10 +103,14 @@ export const attributeFilterPropTypes = {
|
|
|
103
103
|
type: Boolean,
|
|
104
104
|
default: false,
|
|
105
105
|
},
|
|
106
|
-
|
|
106
|
+
showSelectedFilterCount: {
|
|
107
107
|
type: Boolean,
|
|
108
108
|
default: true,
|
|
109
109
|
},
|
|
110
|
+
selectedFilterCount: {
|
|
111
|
+
type: String,
|
|
112
|
+
default: undefined,
|
|
113
|
+
},
|
|
110
114
|
badgeVariant: {
|
|
111
115
|
type: String,
|
|
112
116
|
default: 'danger',
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
:label="props.filterLabel"
|
|
27
27
|
:active="isFilterActive"
|
|
28
28
|
icon="ph:funnel-simple"
|
|
29
|
-
:badge="props.
|
|
30
|
-
:badge-text="savedFilters.length.toString()"
|
|
29
|
+
:badge="props.showSelectedFilterCount"
|
|
30
|
+
:badge-text="props.selectedFilterCount ?? savedFilters.length.toString()"
|
|
31
31
|
:badge-variant="props.badgeVariant"
|
|
32
|
-
:closable="props.clearable
|
|
32
|
+
:closable="props.clearable"
|
|
33
33
|
:disabled="props.disabled"
|
|
34
34
|
@close="handleClear"
|
|
35
35
|
/>
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
class="spr-w-full"
|
|
125
125
|
>
|
|
126
126
|
<div
|
|
127
|
-
v-if="schedule.type === 'restday'"
|
|
127
|
+
v-if="schedule.type === 'restday' || schedule.type === 'exempted'"
|
|
128
128
|
class="spr-flex spr-flex-col spr-items-center spr-justify-start"
|
|
129
129
|
@click="
|
|
130
130
|
onCellClick({
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
})
|
|
135
135
|
"
|
|
136
136
|
>
|
|
137
|
-
<spr-calendar-cell type="restday" fullwidth />
|
|
137
|
+
<spr-calendar-cell :type="schedule.type === 'restday' ? 'restday' : 'exempt'" fullwidth />
|
|
138
138
|
</div>
|
|
139
139
|
<div
|
|
140
140
|
v-else
|
|
@@ -159,21 +159,41 @@
|
|
|
159
159
|
</div>
|
|
160
160
|
</section>
|
|
161
161
|
|
|
162
|
-
<section v-if="
|
|
163
|
-
<
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
162
|
+
<section v-if="showCustomSlot(index, employee.id)">
|
|
163
|
+
<slot
|
|
164
|
+
name="cell"
|
|
165
|
+
:details="{
|
|
166
|
+
employeeId: employee.id,
|
|
167
|
+
date: formatDate(date, dateFormat),
|
|
168
|
+
shift: employee.schedule[formatDate(date, dateFormat)],
|
|
169
|
+
}"
|
|
170
|
+
/>
|
|
171
|
+
</section>
|
|
172
|
+
|
|
173
|
+
<section v-if="showCopyShift(index, employee.id)">
|
|
174
|
+
<slot
|
|
175
|
+
name="copy"
|
|
176
|
+
:copy="{
|
|
177
|
+
employeeId: employee.id,
|
|
178
|
+
date: formatDate(date, dateFormat),
|
|
179
|
+
shift: employee.schedule[formatDate(date, dateFormat)],
|
|
180
|
+
}"
|
|
171
181
|
>
|
|
172
|
-
<
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
182
|
+
<spr-calendar-cell
|
|
183
|
+
:view-only="false"
|
|
184
|
+
custom-border-size="1"
|
|
185
|
+
custom-color="#FFFFFF"
|
|
186
|
+
fullwidth
|
|
187
|
+
@on-click="
|
|
188
|
+
onCellClick({ employeeId: details.employeeId, date: details.date, shift: details.shift })
|
|
189
|
+
"
|
|
190
|
+
>
|
|
191
|
+
<div class="spr-flex spr-w-full spr-items-center spr-justify-center spr-gap-size-spacing-3xs">
|
|
192
|
+
<Icon icon="ph:copy-light" />
|
|
193
|
+
<div class="spr-label-xs-medium">Copy</div>
|
|
194
|
+
</div>
|
|
195
|
+
</spr-calendar-cell>
|
|
196
|
+
</slot>
|
|
177
197
|
</section>
|
|
178
198
|
</td>
|
|
179
199
|
</tr>
|
|
@@ -257,6 +277,7 @@
|
|
|
257
277
|
</template>
|
|
258
278
|
|
|
259
279
|
<script setup lang="ts">
|
|
280
|
+
import { useSlots } from 'vue';
|
|
260
281
|
import { Icon } from '@iconify/vue';
|
|
261
282
|
import SprButton from '@/components/button/button.vue';
|
|
262
283
|
import SprAvatar from '@/components/avatar/avatar.vue';
|
|
@@ -269,6 +290,7 @@ import { calendarPropTypes, calendarEmitTypes } from './calendar';
|
|
|
269
290
|
const props = defineProps(calendarPropTypes);
|
|
270
291
|
import { useCalendar } from './use-calendar';
|
|
271
292
|
const emit = defineEmits(calendarEmitTypes);
|
|
293
|
+
const slots = useSlots();
|
|
272
294
|
|
|
273
295
|
const {
|
|
274
296
|
// State
|
|
@@ -287,7 +309,8 @@ const {
|
|
|
287
309
|
goToToday,
|
|
288
310
|
onCellClick,
|
|
289
311
|
handleHover,
|
|
290
|
-
|
|
312
|
+
showCopyShift,
|
|
291
313
|
handleSorting,
|
|
292
|
-
|
|
314
|
+
showCustomSlot,
|
|
315
|
+
} = useCalendar(props, emit, slots);
|
|
293
316
|
</script>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { computed, SetupContext, toRefs, ref, watch } from 'vue';
|
|
1
|
+
import { computed, SetupContext, toRefs, ref, watch, Slots } from 'vue';
|
|
2
2
|
import dayjs from 'dayjs';
|
|
3
3
|
import isBetween from 'dayjs/plugin/isBetween';
|
|
4
4
|
import classNames from 'classnames';
|
|
@@ -9,8 +9,8 @@ dayjs.extend(isBetween);
|
|
|
9
9
|
|
|
10
10
|
import type { CalendarPropTypes, CalendarEmitTypes, SelectedShift } from './calendar';
|
|
11
11
|
|
|
12
|
-
export const useCalendar = (props: CalendarPropTypes, emit: SetupContext<CalendarEmitTypes>['emit']) => {
|
|
13
|
-
const { initialDate,
|
|
12
|
+
export const useCalendar = (props: CalendarPropTypes, emit: SetupContext<CalendarEmitTypes>['emit'], slots: Slots) => {
|
|
13
|
+
const { initialDate, hideCopyButton } = toRefs(props);
|
|
14
14
|
|
|
15
15
|
const state = {
|
|
16
16
|
dateFormat: ref('YYYY-MM-DD'),
|
|
@@ -108,12 +108,18 @@ export const useCalendar = (props: CalendarPropTypes, emit: SetupContext<Calenda
|
|
|
108
108
|
state.employeeId.value = employeeId;
|
|
109
109
|
};
|
|
110
110
|
|
|
111
|
-
const
|
|
111
|
+
const showCopyShift = (index: number, employeeId: number) => {
|
|
112
112
|
return (
|
|
113
113
|
state.hoveredCell.value === index &&
|
|
114
114
|
state.isHover.value &&
|
|
115
115
|
state.employeeId.value === employeeId &&
|
|
116
|
-
!
|
|
116
|
+
!hideCopyButton.value
|
|
117
|
+
);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const showCustomSlot = (index: number, employeeId: number) => {
|
|
121
|
+
return (
|
|
122
|
+
state.hoveredCell.value === index && state.isHover.value && state.employeeId.value === employeeId && slots.cell
|
|
117
123
|
);
|
|
118
124
|
};
|
|
119
125
|
|
|
@@ -191,8 +197,9 @@ export const useCalendar = (props: CalendarPropTypes, emit: SetupContext<Calenda
|
|
|
191
197
|
goToToday,
|
|
192
198
|
onCellClick,
|
|
193
199
|
handleHover,
|
|
194
|
-
|
|
200
|
+
showCopyShift,
|
|
195
201
|
handleSorting,
|
|
202
|
+
showCustomSlot,
|
|
196
203
|
|
|
197
204
|
...state,
|
|
198
205
|
};
|
|
@@ -4,8 +4,19 @@ import classNames from 'classnames';
|
|
|
4
4
|
import type { CalendarCellPropTypes, CalendarCellEmitTypes } from './calendar-cell';
|
|
5
5
|
|
|
6
6
|
export const useCalendarCell = (props: CalendarCellPropTypes, emit: SetupContext<CalendarCellEmitTypes>['emit']) => {
|
|
7
|
-
const {
|
|
8
|
-
|
|
7
|
+
const {
|
|
8
|
+
title,
|
|
9
|
+
description,
|
|
10
|
+
type,
|
|
11
|
+
status,
|
|
12
|
+
subDescription,
|
|
13
|
+
icon,
|
|
14
|
+
fullwidth,
|
|
15
|
+
viewOnly,
|
|
16
|
+
loading,
|
|
17
|
+
customColor,
|
|
18
|
+
customBorderSize,
|
|
19
|
+
} = toRefs(props);
|
|
9
20
|
const offlineStatus = ['restday', 'vacation', 'holiday', 'exempt', 'sick', 'emergency'];
|
|
10
21
|
const shiftLabels: Record<string, string> = {
|
|
11
22
|
standard: 'Standard Day Shift',
|
|
@@ -68,6 +79,12 @@ export const useCalendarCell = (props: CalendarCellPropTypes, emit: SetupContext
|
|
|
68
79
|
|
|
69
80
|
const getCustomColorStyles = computed(() => {
|
|
70
81
|
if (!customColor.value || !customColor.value.startsWith('#')) return {};
|
|
82
|
+
if (customColor.value === '#FFFFFF') {
|
|
83
|
+
return {
|
|
84
|
+
borderColor: '#B8C1C0',
|
|
85
|
+
backgroundColor: customColor.value,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
71
88
|
|
|
72
89
|
const opacity = '20'; // 20 in hex = 12.5% opacity
|
|
73
90
|
|
|
@@ -80,11 +97,13 @@ export const useCalendarCell = (props: CalendarCellPropTypes, emit: SetupContext
|
|
|
80
97
|
const getCalendarCellClassess = computed(() => {
|
|
81
98
|
const calendarCellWrapper = classNames(
|
|
82
99
|
'spr-flex spr-items-center spr-p-size-spacing-3xs spr-gap-size-spacing-3xs spr-relative spr-rounded-lg spr-border-2 spr-transition-all sm:spr-flex-col spr-overflow-hidden',
|
|
100
|
+
|
|
83
101
|
{
|
|
84
102
|
'spr-w-full': fullwidth.value,
|
|
85
103
|
'spr-max-w-[217px]': !fullwidth.value,
|
|
86
104
|
'hover:spr-drop-shadow-sm spr-cursor-pointer': !viewOnly.value,
|
|
87
105
|
'spr-h-[80px] spr-skeletal-loader': loading.value,
|
|
106
|
+
[`spr-border-[${customBorderSize.value}px]`]: customBorderSize.value,
|
|
88
107
|
},
|
|
89
108
|
);
|
|
90
109
|
|
|
@@ -12,6 +12,7 @@ export const cardPropTypes = {
|
|
|
12
12
|
tone: {
|
|
13
13
|
type: String as PropType<(typeof TONES)[number] | undefined>,
|
|
14
14
|
validator: (val: string | undefined) => !val || TONES.includes(val as (typeof TONES)[number]),
|
|
15
|
+
default: 'plain',
|
|
15
16
|
},
|
|
16
17
|
title: {
|
|
17
18
|
type: String,
|
|
@@ -59,6 +60,10 @@ export const cardPropTypes = {
|
|
|
59
60
|
type: Boolean,
|
|
60
61
|
default: false,
|
|
61
62
|
},
|
|
63
|
+
customBorderSize: {
|
|
64
|
+
type: String,
|
|
65
|
+
default: null,
|
|
66
|
+
},
|
|
62
67
|
};
|
|
63
68
|
|
|
64
69
|
export type CardPropTypes = ExtractPropTypes<typeof cardPropTypes>;
|
|
@@ -12,8 +12,17 @@ interface CardClasses {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export const useCard = (props: CardPropTypes, slots: Slots) => {
|
|
15
|
-
const {
|
|
16
|
-
|
|
15
|
+
const {
|
|
16
|
+
tone,
|
|
17
|
+
title,
|
|
18
|
+
headerIcon,
|
|
19
|
+
borderRadiusSize,
|
|
20
|
+
hasCollapsible,
|
|
21
|
+
isCollapsibleOpen,
|
|
22
|
+
hasContentPadding,
|
|
23
|
+
flexbox,
|
|
24
|
+
customBorderSize,
|
|
25
|
+
} = toRefs(props);
|
|
17
26
|
|
|
18
27
|
const cardClasses: ComputedRef<CardClasses> = computed(() => {
|
|
19
28
|
const toneValue = tone?.value;
|
|
@@ -21,7 +30,7 @@ export const useCard = (props: CardPropTypes, slots: Slots) => {
|
|
|
21
30
|
const baseClasses = classNames(`spr-border-solid`, {
|
|
22
31
|
// Tones
|
|
23
32
|
'spr-background-color-base': !toneValue,
|
|
24
|
-
'spr-
|
|
33
|
+
'spr-background-color': toneValue === 'plain',
|
|
25
34
|
'spr-background-color-surface': toneValue === 'neutral',
|
|
26
35
|
'spr-background-color-success-weak': toneValue === 'success',
|
|
27
36
|
'spr-background-color-information-weak': toneValue === 'information',
|
|
@@ -47,6 +56,9 @@ export const useCard = (props: CardPropTypes, slots: Slots) => {
|
|
|
47
56
|
'spr-rounded-border-radius-md': borderRadiusSize.value === 'xs',
|
|
48
57
|
'spr-rounded-border-radius-lg': borderRadiusSize.value === 'lg',
|
|
49
58
|
'spr-rounded-border-radius-xl': borderRadiusSize.value === 'xl' || !borderRadiusSize.value,
|
|
59
|
+
|
|
60
|
+
[`spr-border-[${customBorderSize.value}px]`]: customBorderSize.value,
|
|
61
|
+
'spr-border-none': customBorderSize.value === '0',
|
|
50
62
|
});
|
|
51
63
|
|
|
52
64
|
const headerClasses = classNames(`spr-flex spr-items-center transition-all duration-300 ease-in-out`, {
|
|
@@ -90,11 +90,6 @@ export const datePickerPropTypes = {
|
|
|
90
90
|
type: String,
|
|
91
91
|
default: '100%',
|
|
92
92
|
},
|
|
93
|
-
popperStrategy: {
|
|
94
|
-
type: String,
|
|
95
|
-
validator: (value: 'fixed' | 'absolute') => POPPER_STRATEGY_TYPES.includes(value),
|
|
96
|
-
default: 'absolute',
|
|
97
|
-
},
|
|
98
93
|
placement: {
|
|
99
94
|
type: String as PropType<(typeof PLACEMENTS_TYPES)[number]>,
|
|
100
95
|
validator: (value: (typeof PLACEMENTS_TYPES)[number]) => PLACEMENTS_TYPES.includes(value),
|
|
@@ -105,6 +100,19 @@ export const datePickerPropTypes = {
|
|
|
105
100
|
default: 'MM-DD-YYYY',
|
|
106
101
|
description: 'Format for the selected date. For example: MM/DD/YYYY, YYYY-MM-DD, etc.',
|
|
107
102
|
},
|
|
103
|
+
wrapperPosition: {
|
|
104
|
+
type: String,
|
|
105
|
+
default: 'relative',
|
|
106
|
+
},
|
|
107
|
+
popperStrategy: {
|
|
108
|
+
type: String,
|
|
109
|
+
validator: (value: 'fixed' | 'absolute') => POPPER_STRATEGY_TYPES.includes(value),
|
|
110
|
+
default: 'absolute',
|
|
111
|
+
},
|
|
112
|
+
popperContainer: {
|
|
113
|
+
type: String,
|
|
114
|
+
default: '',
|
|
115
|
+
},
|
|
108
116
|
};
|
|
109
117
|
|
|
110
118
|
export type RestDayType = (typeof REST_DAYS_TYPES)[number];
|
|
@@ -154,3 +162,26 @@ export const datePickerEmitTypes = {
|
|
|
154
162
|
|
|
155
163
|
export type DatePickerPropTypes = ExtractPropTypes<typeof datePickerPropTypes>;
|
|
156
164
|
export type DatePickerEmitTypes = typeof datePickerEmitTypes;
|
|
165
|
+
|
|
166
|
+
// Tab component interfaces
|
|
167
|
+
export interface TabComponentProps {
|
|
168
|
+
selectedMonth?: number;
|
|
169
|
+
selectedYear?: number;
|
|
170
|
+
selectedDay?: number;
|
|
171
|
+
minMaxYear: MinMaxYearType;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export interface CalendarTabEmits {
|
|
175
|
+
'update:date': (day: { date: Date; inactive: boolean }) => void;
|
|
176
|
+
'update:month': (month: number) => void;
|
|
177
|
+
'update:year': (year: number) => void;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export interface MonthTabEmits {
|
|
181
|
+
'update:month': (month: number) => void;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export interface YearTabEmits {
|
|
185
|
+
'update:year': (year: number) => void;
|
|
186
|
+
'update:currentPage': (page: number) => void;
|
|
187
|
+
}
|
|
@@ -9,12 +9,13 @@
|
|
|
9
9
|
:popper-hide-triggers="[]"
|
|
10
10
|
:auto-hide="false"
|
|
11
11
|
:disabled="isDatePickerPopperDisabled"
|
|
12
|
-
:container="`#${props.id}`"
|
|
12
|
+
:container="props.popperContainer ? props.popperContainer : `#${props.id}`"
|
|
13
13
|
:strategy="
|
|
14
14
|
props.popperStrategy === 'fixed' || props.popperStrategy === 'absolute' ? props.popperStrategy : 'absolute'
|
|
15
15
|
"
|
|
16
16
|
:delay="0"
|
|
17
17
|
:style="{
|
|
18
|
+
position: props.wrapperPosition,
|
|
18
19
|
width: props.width,
|
|
19
20
|
}"
|
|
20
21
|
>
|
|
@@ -94,11 +94,6 @@ export const dateRangePickerPropTypes = {
|
|
|
94
94
|
type: String,
|
|
95
95
|
default: '100%',
|
|
96
96
|
},
|
|
97
|
-
popperStrategy: {
|
|
98
|
-
type: String,
|
|
99
|
-
validator: (value: 'fixed' | 'absolute') => POPPER_STRATEGY_TYPES.includes(value),
|
|
100
|
-
default: 'absolute',
|
|
101
|
-
},
|
|
102
97
|
placement: {
|
|
103
98
|
type: String as PropType<(typeof PLACEMENTS_TYPES)[number]>,
|
|
104
99
|
validator: (value: (typeof PLACEMENTS_TYPES)[number]) => PLACEMENTS_TYPES.includes(value),
|
|
@@ -128,6 +123,19 @@ export const dateRangePickerPropTypes = {
|
|
|
128
123
|
default: 1,
|
|
129
124
|
description: 'Minimum number of days required in the range',
|
|
130
125
|
},
|
|
126
|
+
wrapperPosition: {
|
|
127
|
+
type: String,
|
|
128
|
+
default: 'relative',
|
|
129
|
+
},
|
|
130
|
+
popperStrategy: {
|
|
131
|
+
type: String,
|
|
132
|
+
validator: (value: 'fixed' | 'absolute') => POPPER_STRATEGY_TYPES.includes(value),
|
|
133
|
+
default: 'absolute',
|
|
134
|
+
},
|
|
135
|
+
popperContainer: {
|
|
136
|
+
type: String,
|
|
137
|
+
default: '',
|
|
138
|
+
},
|
|
131
139
|
};
|
|
132
140
|
|
|
133
141
|
export type RestDayType = (typeof REST_DAYS_TYPES)[number];
|
|
@@ -190,4 +198,4 @@ export const dateRangePickerEmitTypes = {
|
|
|
190
198
|
};
|
|
191
199
|
|
|
192
200
|
export type DateRangePickerPropTypes = ExtractPropTypes<typeof dateRangePickerPropTypes>;
|
|
193
|
-
export type DateRangePickerEmitTypes = typeof dateRangePickerEmitTypes;
|
|
201
|
+
export type DateRangePickerEmitTypes = typeof dateRangePickerEmitTypes;
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
:popper-hide-triggers="[]"
|
|
10
10
|
:auto-hide="false"
|
|
11
11
|
:disabled="isDateRangePickerPopperDisabled"
|
|
12
|
-
:container="`#${props.id}`"
|
|
12
|
+
:container="props.popperContainer ? props.popperContainer : `#${props.id}`"
|
|
13
13
|
:reference="activeInputRef"
|
|
14
14
|
:strategy="
|
|
15
15
|
props.popperStrategy === 'fixed' || props.popperStrategy === 'absolute' ? props.popperStrategy : 'absolute'
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
:delay="0"
|
|
18
18
|
:auto-placement="!isUsingCustomSlot"
|
|
19
19
|
:style="{
|
|
20
|
+
position: props.wrapperPosition,
|
|
20
21
|
width: props.width,
|
|
21
22
|
}"
|
|
22
23
|
>
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { PropType, ExtractPropTypes } from 'vue';
|
|
2
|
+
|
|
3
|
+
// Helper function for prop types
|
|
4
|
+
export const definePropType = <T>(val: unknown): PropType<T> => val as PropType<T>;
|
|
5
|
+
|
|
6
|
+
// Define constants for prop validation
|
|
7
|
+
export const DATE_PICKER_MODES = ['full', 'month-year', 'year-only'] as const;
|
|
8
|
+
|
|
9
|
+
// Define types
|
|
10
|
+
export interface MinMaxYearType {
|
|
11
|
+
min: number;
|
|
12
|
+
max: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface DisabledDatesType {
|
|
16
|
+
to: string;
|
|
17
|
+
from: string;
|
|
18
|
+
pastDates: boolean | string;
|
|
19
|
+
futureDates: boolean | string;
|
|
20
|
+
selectedDates: Array<string>;
|
|
21
|
+
weekends: boolean;
|
|
22
|
+
weekdays: boolean;
|
|
23
|
+
selectedDays: Array<string>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type RestDayType = 'su' | 'mo' | 'tu' | 'we' | 'th' | 'fr' | 'sa';
|
|
27
|
+
export type DatePickerMode = typeof DATE_PICKER_MODES[number];
|
|
28
|
+
|
|
29
|
+
// Define props with JSDoc comments for documentation
|
|
30
|
+
export const reusableCalendarPropTypes = {
|
|
31
|
+
/**
|
|
32
|
+
* @description The selected date value (v-model)
|
|
33
|
+
*/
|
|
34
|
+
modelValue: {
|
|
35
|
+
type: String,
|
|
36
|
+
default: '',
|
|
37
|
+
},
|
|
38
|
+
/**
|
|
39
|
+
* @description Pre-selected month (0-indexed)
|
|
40
|
+
*/
|
|
41
|
+
selectedMonth: {
|
|
42
|
+
type: Number,
|
|
43
|
+
default: undefined,
|
|
44
|
+
},
|
|
45
|
+
/**
|
|
46
|
+
* @description Pre-selected year
|
|
47
|
+
*/
|
|
48
|
+
selectedYear: {
|
|
49
|
+
type: Number,
|
|
50
|
+
default: undefined,
|
|
51
|
+
},
|
|
52
|
+
/**
|
|
53
|
+
* @description Pre-selected day
|
|
54
|
+
*/
|
|
55
|
+
selectedDay: {
|
|
56
|
+
type: Number,
|
|
57
|
+
default: undefined,
|
|
58
|
+
},
|
|
59
|
+
/**
|
|
60
|
+
* @description Year range constraints
|
|
61
|
+
*/
|
|
62
|
+
minMaxYear: {
|
|
63
|
+
type: Object as PropType<MinMaxYearType>,
|
|
64
|
+
default: () => ({ min: 1900, max: new Date().getFullYear() }),
|
|
65
|
+
},
|
|
66
|
+
/**
|
|
67
|
+
* @description Days to mark as rest days
|
|
68
|
+
*/
|
|
69
|
+
restDays: {
|
|
70
|
+
type: Array as PropType<RestDayType[]>,
|
|
71
|
+
default: () => [],
|
|
72
|
+
},
|
|
73
|
+
/**
|
|
74
|
+
* @description Date restrictions
|
|
75
|
+
*/
|
|
76
|
+
disabledDates: {
|
|
77
|
+
type: Object as PropType<DisabledDatesType>,
|
|
78
|
+
default: undefined,
|
|
79
|
+
},
|
|
80
|
+
/**
|
|
81
|
+
* @description Disable the calendar
|
|
82
|
+
*/
|
|
83
|
+
disabled: {
|
|
84
|
+
type: Boolean,
|
|
85
|
+
default: false,
|
|
86
|
+
},
|
|
87
|
+
/**
|
|
88
|
+
* @description Make the calendar read-only
|
|
89
|
+
*/
|
|
90
|
+
readonly: {
|
|
91
|
+
type: Boolean,
|
|
92
|
+
default: false,
|
|
93
|
+
},
|
|
94
|
+
/**
|
|
95
|
+
* @description Calendar mode: 'full', 'month-year', 'year-only'
|
|
96
|
+
*/
|
|
97
|
+
mode: {
|
|
98
|
+
type: String as PropType<DatePickerMode>,
|
|
99
|
+
validator: (value: DatePickerMode) => DATE_PICKER_MODES.includes(value),
|
|
100
|
+
default: 'full',
|
|
101
|
+
},
|
|
102
|
+
/**
|
|
103
|
+
* @description Date format for v-model
|
|
104
|
+
*/
|
|
105
|
+
format: {
|
|
106
|
+
type: String,
|
|
107
|
+
default: 'MM-DD-YYYY',
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// Define emits with type validation
|
|
112
|
+
export const reusableCalendarEmitTypes = {
|
|
113
|
+
'update:modelValue': (value: string): value is string => typeof value === 'string',
|
|
114
|
+
'update:month': (month: number): month is number => typeof month === 'number',
|
|
115
|
+
'update:year': (year: number): year is number => typeof year === 'number',
|
|
116
|
+
'update:day': (day: number): day is number => typeof day === 'number',
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Export types for use in other files
|
|
120
|
+
export type ReusableCalendarPropTypes = ExtractPropTypes<typeof reusableCalendarPropTypes>;
|
|
121
|
+
export type ReusableCalendarEmitTypes = typeof reusableCalendarEmitTypes;
|