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.
Files changed (45) hide show
  1. package/dist/design-system-next.es.js +7569 -6646
  2. package/dist/design-system-next.es.js.gz +0 -0
  3. package/dist/design-system-next.umd.js +14 -14
  4. package/dist/design-system-next.umd.js.gz +0 -0
  5. package/dist/main.css +1 -1
  6. package/dist/main.css.gz +0 -0
  7. package/dist/package.json.d.ts +1 -1
  8. package/package.json +1 -1
  9. package/src/App.vue +43 -1642
  10. package/src/assets/styles/tailwind.css +20 -0
  11. package/src/components/attribute-filter/attribute-filter.ts +5 -1
  12. package/src/components/attribute-filter/attribute-filter.vue +3 -3
  13. package/src/components/calendar/calendar.ts +1 -1
  14. package/src/components/calendar/calendar.vue +41 -18
  15. package/src/components/calendar/use-calendar.ts +13 -6
  16. package/src/components/calendar-cell/calendar-cell.ts +4 -0
  17. package/src/components/calendar-cell/use-calendar-cell.ts +21 -2
  18. package/src/components/card/card.ts +5 -0
  19. package/src/components/card/use-card.ts +15 -3
  20. package/src/components/date-picker/date-picker.ts +36 -5
  21. package/src/components/date-picker/date-picker.vue +2 -1
  22. package/src/components/date-picker/date-range-picker/date-range-picker.ts +14 -6
  23. package/src/components/date-picker/date-range-picker/date-range-picker.vue +2 -1
  24. package/src/components/date-picker/reusable-calendar/reusable-calendar.ts +121 -0
  25. package/src/components/date-picker/reusable-calendar/reusable-calendar.vue +192 -0
  26. package/src/components/date-picker/reusable-calendar/use-reusable-calendar.ts +366 -0
  27. package/src/components/date-picker/tabs/DatePickerCalendarTab.vue +321 -0
  28. package/src/components/date-picker/tabs/DatePickerMonthTab.vue +60 -0
  29. package/src/components/date-picker/tabs/DatePickerYearTab.vue +114 -0
  30. package/src/components/dropdown/dropdown.ts +25 -21
  31. package/src/components/dropdown/dropdown.vue +1 -1
  32. package/src/components/icon/icon.ts +36 -0
  33. package/src/components/icon/icon.vue +12 -0
  34. package/src/components/icon/use-icon.ts +67 -0
  35. package/src/components/lozenge/lozenge.ts +1 -1
  36. package/src/components/popper/popper.ts +12 -0
  37. package/src/components/popper/popper.vue +36 -0
  38. package/src/components/popper/use-popper.ts +16 -0
  39. package/src/components/select/select-ladderized/select-ladderized.ts +16 -12
  40. package/src/components/select/select-ladderized/select-ladderized.vue +1 -1
  41. package/src/components/select/select-multiple/select-multiple.ts +8 -4
  42. package/src/components/select/select-multiple/select-multiple.vue +1 -1
  43. package/src/components/select/select-multiple/use-select-multiple.ts +15 -4
  44. package/src/components/select/select.ts +4 -0
  45. 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
- showBadge: {
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.showBadge && savedFilters.length > 0"
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 && savedFilters.length > 0"
32
+ :closable="props.clearable"
33
33
  :disabled="props.disabled"
34
34
  @close="handleClear"
35
35
  />
@@ -67,7 +67,7 @@ export const calendarPropTypes = {
67
67
  type: String,
68
68
  default: '',
69
69
  },
70
- hideAddButton: {
70
+ hideCopyButton: {
71
71
  type: Boolean,
72
72
  default: false,
73
73
  },
@@ -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="showAddShift(index, employee.id)">
163
- <spr-calendar-cell
164
- status="pending"
165
- type="exempt"
166
- :view-only="false"
167
- fullwidth
168
- @on-click="
169
- onCellClick({ employeeId: employee.id, date: formatDate(date, dateFormat), shift: null })
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
- <template #prefix>
173
- <Icon icon="ph:plus" />
174
- </template>
175
- <div class="spr-label-xs-medium">Add New Shift</div>
176
- </spr-calendar-cell>
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
- showAddShift,
312
+ showCopyShift,
291
313
  handleSorting,
292
- } = useCalendar(props, emit);
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, hideAddButton } = toRefs(props);
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 showAddShift = (index: number, employeeId: number) => {
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
- !hideAddButton.value
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
- showAddShift,
200
+ showCopyShift,
195
201
  handleSorting,
202
+ showCustomSlot,
196
203
 
197
204
  ...state,
198
205
  };
@@ -55,6 +55,10 @@ export const calendarCellPropTypes = {
55
55
  type: String,
56
56
  default: '',
57
57
  },
58
+ customBorderSize: {
59
+ type: String,
60
+ default: null,
61
+ },
58
62
  };
59
63
 
60
64
  export type CalendarCellPropTypes = ExtractPropTypes<typeof calendarCellPropTypes>;
@@ -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 { title, description, type, status, subDescription, icon, fullwidth, viewOnly, loading, customColor } =
8
- toRefs(props);
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 { tone, title, headerIcon, borderRadiusSize, hasCollapsible, isCollapsibleOpen, hasContentPadding, flexbox } =
16
- toRefs(props);
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-bg-white': toneValue === 'plain',
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;