v-calendar-3 1.0.0

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 (147) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +142 -0
  3. package/dist/cjs/index.css +1133 -0
  4. package/dist/cjs/index.js +10699 -0
  5. package/dist/cjs/index.js.map +1 -0
  6. package/dist/cjs/package.json +1 -0
  7. package/dist/es/index.js +10678 -0
  8. package/dist/es/index.js.map +1 -0
  9. package/dist/es/style.css +1134 -0
  10. package/dist/iife/index.js +2 -0
  11. package/dist/iife/index.js.map +1 -0
  12. package/dist/mjs/index.mjs +10678 -0
  13. package/dist/mjs/index.mjs.map +1 -0
  14. package/dist/mjs/style.css +1134 -0
  15. package/dist/style.css +1134 -0
  16. package/dist/types/components/BaseIcon/BaseIcon.vue.d.ts +41 -0
  17. package/dist/types/components/BaseIcon/icons/IconChevronDown.vue.d.ts +3 -0
  18. package/dist/types/components/BaseIcon/icons/IconChevronLeft.vue.d.ts +3 -0
  19. package/dist/types/components/BaseIcon/icons/IconChevronRight.vue.d.ts +3 -0
  20. package/dist/types/components/BaseIcon/icons/IconClock.vue.d.ts +3 -0
  21. package/dist/types/components/BaseIcon/icons/index.d.ts +4 -0
  22. package/dist/types/components/BaseSelect/BaseSelect.vue.d.ts +26 -0
  23. package/dist/types/components/Calendar/Calendar.vue.d.ts +2526 -0
  24. package/dist/types/components/Calendar/CalendarDay.vue.d.ts +83 -0
  25. package/dist/types/components/Calendar/CalendarDayPopover.vue.d.ts +3 -0
  26. package/dist/types/components/Calendar/CalendarHeader.vue.d.ts +13 -0
  27. package/dist/types/components/Calendar/CalendarNav.vue.d.ts +4 -0
  28. package/dist/types/components/Calendar/CalendarNavPopover.vue.d.ts +3 -0
  29. package/dist/types/components/Calendar/CalendarPage.vue.d.ts +3 -0
  30. package/dist/types/components/Calendar/CalendarPageProvider.vue.d.ts +17 -0
  31. package/dist/types/components/Calendar/CalendarSlot.vue.d.ts +15 -0
  32. package/dist/types/components/Calendar/CalendarTitleSelect.vue.d.ts +15 -0
  33. package/dist/types/components/CalendarGrid/CalendarCell.vue.d.ts +9 -0
  34. package/dist/types/components/CalendarGrid/CalendarCellPopover.vue.d.ts +209 -0
  35. package/dist/types/components/CalendarGrid/CalendarDayCell.vue.d.ts +8 -0
  36. package/dist/types/components/CalendarGrid/CalendarEventDetails.vue.d.ts +15 -0
  37. package/dist/types/components/CalendarGrid/CalendarEventEdit.vue.d.ts +26 -0
  38. package/dist/types/components/CalendarGrid/CalendarGrid.vue.d.ts +134 -0
  39. package/dist/types/components/CalendarGrid/CalendarGridWeek.vue.d.ts +8 -0
  40. package/dist/types/components/CalendarGrid/CalendarViewSelect.vue.d.ts +3 -0
  41. package/dist/types/components/CalendarGrid/CalendarWeekCell.vue.d.ts +10 -0
  42. package/dist/types/components/CalendarGrid/Constraints.d.ts +16 -0
  43. package/dist/types/components/DatePicker/DatePicker.vue.d.ts +15251 -0
  44. package/dist/types/components/DatePicker/DatePickerBase.vue.d.ts +3 -0
  45. package/dist/types/components/DatePicker/DatePickerPopover.vue.d.ts +3 -0
  46. package/dist/types/components/DatePicker/TimePicker.vue.d.ts +10089 -0
  47. package/dist/types/components/Popover/Popover.vue.d.ts +72 -0
  48. package/dist/types/components/Popover/PopoverRow.vue.d.ts +17 -0
  49. package/dist/types/components/index.d.ts +4 -0
  50. package/dist/types/index.d.cts +40981 -0
  51. package/dist/types/index.d.mts +40981 -0
  52. package/dist/types/index.d.ts +40981 -0
  53. package/dist/types/use/base.d.ts +67 -0
  54. package/dist/types/use/calendar.d.ts +2422 -0
  55. package/dist/types/use/calendarGrid.d.ts +9370 -0
  56. package/dist/types/use/datePicker.d.ts +20210 -0
  57. package/dist/types/use/page.d.ts +20 -0
  58. package/dist/types/use/slots.d.ts +5 -0
  59. package/dist/types/use/timePicker.d.ts +10089 -0
  60. package/dist/types/utils/attribute.d.ts +49 -0
  61. package/dist/types/utils/cache.d.ts +10 -0
  62. package/dist/types/utils/calendar/event.d.ts +111 -0
  63. package/dist/types/utils/config/index.d.ts +5 -0
  64. package/dist/types/utils/date/helpers.d.ts +161 -0
  65. package/dist/types/utils/date/range.d.ts +74 -0
  66. package/dist/types/utils/date/repeat.d.ts +34 -0
  67. package/dist/types/utils/date/rules.d.ts +82 -0
  68. package/dist/types/utils/defaults/index.d.ts +30 -0
  69. package/dist/types/utils/defaults/locales.d.ts +9 -0
  70. package/dist/types/utils/glyph.d.ts +58 -0
  71. package/dist/types/utils/helpers.d.ts +49 -0
  72. package/dist/types/utils/locale.d.ts +48 -0
  73. package/dist/types/utils/page.d.ts +95 -0
  74. package/dist/types/utils/plugins/index.d.ts +4 -0
  75. package/dist/types/utils/popovers.d.ts +47 -0
  76. package/dist/types/utils/theme.d.ts +17 -0
  77. package/dist/types/utils/touch.d.ts +8 -0
  78. package/dist/types/utils/useDisplayMode.d.ts +12 -0
  79. package/dist/types/utils/watchers.d.ts +6 -0
  80. package/package.json +115 -0
  81. package/src/components/BaseIcon/BaseIcon.vue +29 -0
  82. package/src/components/BaseIcon/icons/IconChevronDown.vue +5 -0
  83. package/src/components/BaseIcon/icons/IconChevronLeft.vue +5 -0
  84. package/src/components/BaseIcon/icons/IconChevronRight.vue +5 -0
  85. package/src/components/BaseIcon/icons/IconClock.vue +11 -0
  86. package/src/components/BaseIcon/icons/index.ts +4 -0
  87. package/src/components/BaseSelect/BaseSelect.vue +136 -0
  88. package/src/components/Calendar/Calendar.vue +116 -0
  89. package/src/components/Calendar/CalendarDay.vue +422 -0
  90. package/src/components/Calendar/CalendarDayPopover.vue +44 -0
  91. package/src/components/Calendar/CalendarHeader.vue +203 -0
  92. package/src/components/Calendar/CalendarNav.vue +325 -0
  93. package/src/components/Calendar/CalendarNavPopover.vue +24 -0
  94. package/src/components/Calendar/CalendarPage.vue +140 -0
  95. package/src/components/Calendar/CalendarPageProvider.vue +15 -0
  96. package/src/components/Calendar/CalendarSlot.vue +36 -0
  97. package/src/components/Calendar/CalendarTitleSelect.vue +72 -0
  98. package/src/components/CalendarGrid/CalendarCell.vue +112 -0
  99. package/src/components/CalendarGrid/CalendarCellPopover.vue +93 -0
  100. package/src/components/CalendarGrid/CalendarDayCell.vue +57 -0
  101. package/src/components/CalendarGrid/CalendarEventDetails.vue +71 -0
  102. package/src/components/CalendarGrid/CalendarEventEdit.vue +195 -0
  103. package/src/components/CalendarGrid/CalendarGrid.vue +715 -0
  104. package/src/components/CalendarGrid/CalendarGridWeek.vue +60 -0
  105. package/src/components/CalendarGrid/CalendarViewSelect.vue +34 -0
  106. package/src/components/CalendarGrid/CalendarWeekCell.vue +52 -0
  107. package/src/components/CalendarGrid/Constraints.ts +40 -0
  108. package/src/components/DatePicker/DatePicker.vue +27 -0
  109. package/src/components/DatePicker/DatePickerBase.vue +53 -0
  110. package/src/components/DatePicker/DatePickerPopover.vue +37 -0
  111. package/src/components/DatePicker/TimePicker.vue +167 -0
  112. package/src/components/Popover/Popover.vue +572 -0
  113. package/src/components/Popover/PopoverRow.vue +94 -0
  114. package/src/components/index.ts +4 -0
  115. package/src/index.ts +24 -0
  116. package/src/styles/index.css +48 -0
  117. package/src/styles/theme.css +322 -0
  118. package/src/styles/transitions.css +77 -0
  119. package/src/use/base.ts +144 -0
  120. package/src/use/calendar.ts +796 -0
  121. package/src/use/calendarGrid.ts +954 -0
  122. package/src/use/datePicker.ts +909 -0
  123. package/src/use/page.ts +78 -0
  124. package/src/use/slots.ts +17 -0
  125. package/src/use/timePicker.ts +194 -0
  126. package/src/utils/attribute.ts +107 -0
  127. package/src/utils/cache.ts +30 -0
  128. package/src/utils/calendar/event.ts +335 -0
  129. package/src/utils/config/index.ts +11 -0
  130. package/src/utils/date/helpers.ts +1039 -0
  131. package/src/utils/date/range.ts +274 -0
  132. package/src/utils/date/repeat.ts +135 -0
  133. package/src/utils/date/rules.ts +290 -0
  134. package/src/utils/defaults/index.ts +77 -0
  135. package/src/utils/defaults/locales.ts +123 -0
  136. package/src/utils/defaults/masks.json +15 -0
  137. package/src/utils/defaults/touch.json +5 -0
  138. package/src/utils/glyph.ts +305 -0
  139. package/src/utils/helpers.ts +181 -0
  140. package/src/utils/locale.ts +275 -0
  141. package/src/utils/page.ts +608 -0
  142. package/src/utils/plugins/index.ts +24 -0
  143. package/src/utils/popovers.ts +216 -0
  144. package/src/utils/theme.ts +58 -0
  145. package/src/utils/touch.ts +72 -0
  146. package/src/utils/useDisplayMode.ts +198 -0
  147. package/src/utils/watchers.ts +26 -0
@@ -0,0 +1,325 @@
1
+ <template>
2
+ <!--Nav panel-->
3
+ <div class="vc-nav-container" ref="navContainer">
4
+ <!--Nav header-->
5
+ <div class="vc-nav-header">
6
+ <!--Move prev button-->
7
+ <button
8
+ type="button"
9
+ class="vc-nav-arrow is-left vc-focus"
10
+ :disabled="!prevItemsEnabled"
11
+ @click="movePrev"
12
+ @keydown="(e: KeyboardEvent) => onSpaceOrEnter(e, movePrev)"
13
+ >
14
+ <CalendarSlot
15
+ name="nav-prev-button"
16
+ :move="movePrev"
17
+ :disabled="!prevItemsEnabled"
18
+ >
19
+ <BaseIcon name="ChevronLeft" width="22px" height="24px" />
20
+ </CalendarSlot>
21
+ </button>
22
+ <!--Mode switch button-->
23
+ <button
24
+ type="button"
25
+ class="vc-nav-title vc-focus"
26
+ @click="toggleMode"
27
+ @keydown="(e: KeyboardEvent) => onSpaceOrEnter(e, toggleMode)"
28
+ >
29
+ {{ title }}
30
+ </button>
31
+ <!--Move next button-->
32
+ <button
33
+ type="button"
34
+ class="vc-nav-arrow is-right vc-focus"
35
+ :disabled="!nextItemsEnabled"
36
+ @click="moveNext"
37
+ @keydown="(e: KeyboardEvent) => onSpaceOrEnter(e, moveNext)"
38
+ >
39
+ <CalendarSlot
40
+ name="nav-next-button"
41
+ :move="moveNext"
42
+ :disabled="!nextItemsEnabled"
43
+ >
44
+ <BaseIcon name="ChevronRight" width="22px" height="24px" />
45
+ </CalendarSlot>
46
+ </button>
47
+ </div>
48
+ <!--Navigation items-->
49
+ <div class="vc-nav-items">
50
+ <button
51
+ v-for="item in activeItems"
52
+ :key="item.label"
53
+ type="button"
54
+ :data-id="item.id"
55
+ :aria-label="item.ariaLabel"
56
+ class="vc-nav-item vc-focus"
57
+ :class="[
58
+ item.isActive ? 'is-active' : item.isCurrent ? 'is-current' : '',
59
+ ]"
60
+ :disabled="item.isDisabled"
61
+ @click="item.click"
62
+ @keydown="(e: KeyboardEvent) => onSpaceOrEnter(e, item.click)"
63
+ >
64
+ {{ item.label }}
65
+ </button>
66
+ </div>
67
+ </div>
68
+ </template>
69
+
70
+ <script setup lang="ts">
71
+ import { computed, onMounted, ref, watch, watchEffect } from 'vue';
72
+ import { useCalendar } from '../../use/calendar';
73
+ import { usePage } from '../../use/page';
74
+ import { head, last, onSpaceOrEnter } from '../../utils/helpers';
75
+ import BaseIcon from '../BaseIcon/BaseIcon.vue';
76
+ import CalendarSlot from './CalendarSlot.vue';
77
+
78
+ export type IQuerySelector = Pick<HTMLElement, 'querySelector'>;
79
+
80
+ const { masks, move } = useCalendar();
81
+ const { page, getMonthItems, getYearItems } = usePage();
82
+
83
+ const monthMode = ref(true);
84
+ const yearGroupCount = 12;
85
+
86
+ const selectedYear = ref(page.value.year);
87
+ const selectedYearGroup = ref(getYearGroupIndex(page.value.year));
88
+ const navContainer = ref<IQuerySelector | null>(null);
89
+
90
+ function focusFirstItem() {
91
+ // Use setTimeout instead of $nextTick so it plays nice with popperjs
92
+ setTimeout(() => {
93
+ if (navContainer.value == null) return;
94
+ // Set focus on the first enabled nav item
95
+ const focusableEl = navContainer.value.querySelector(
96
+ '.vc-nav-item:not(:disabled)',
97
+ ) as HTMLElement;
98
+ if (focusableEl) {
99
+ focusableEl.focus();
100
+ }
101
+ }, 10);
102
+ }
103
+
104
+ function getYearGroupIndex(year: number) {
105
+ return Math.floor(year / yearGroupCount);
106
+ }
107
+
108
+ function toggleMode() {
109
+ monthMode.value = !monthMode.value;
110
+ }
111
+
112
+ function getStartYear(groupIndex: number) {
113
+ return groupIndex * yearGroupCount;
114
+ }
115
+
116
+ function getEndYear(groupIndex: number) {
117
+ return yearGroupCount * (groupIndex + 1) - 1;
118
+ }
119
+
120
+ // #region Move methods
121
+
122
+ function movePrev() {
123
+ if (!prevItemsEnabled.value) return;
124
+ if (monthMode.value) {
125
+ movePrevYear();
126
+ }
127
+ movePrevYearGroup();
128
+ }
129
+
130
+ function moveNext() {
131
+ if (!nextItemsEnabled.value) return;
132
+ if (monthMode.value) {
133
+ moveNextYear();
134
+ }
135
+ moveNextYearGroup();
136
+ }
137
+
138
+ function movePrevYear() {
139
+ selectedYear.value--;
140
+ }
141
+
142
+ function moveNextYear() {
143
+ selectedYear.value++;
144
+ }
145
+
146
+ function movePrevYearGroup() {
147
+ selectedYearGroup.value--;
148
+ }
149
+
150
+ function moveNextYearGroup() {
151
+ selectedYearGroup.value++;
152
+ }
153
+
154
+ // #endregion Move methods
155
+
156
+ const monthItems = computed(() =>
157
+ getMonthItems(selectedYear.value, masks.value.navMonths).map(item => ({
158
+ ...item,
159
+ click: () =>
160
+ move(
161
+ { month: item.month, year: item.year },
162
+ { position: page.value.position },
163
+ ),
164
+ })),
165
+ );
166
+
167
+ const prevMonthItems = computed(() =>
168
+ getMonthItems(selectedYear.value - 1, masks.value.navMonths),
169
+ );
170
+
171
+ const prevMonthItemsEnabled = computed(() =>
172
+ prevMonthItems.value.some(i => !i.isDisabled),
173
+ );
174
+
175
+ const nextMonthItems = computed(() =>
176
+ getMonthItems(selectedYear.value + 1, masks.value.navMonths),
177
+ );
178
+
179
+ const nextMonthItemsEnabled = computed(() =>
180
+ nextMonthItems.value.some(i => !i.isDisabled),
181
+ );
182
+
183
+ const yearItems = computed(() =>
184
+ getYearItems(
185
+ getStartYear(selectedYearGroup.value),
186
+ getEndYear(selectedYearGroup.value),
187
+ ).map(item => {
188
+ return {
189
+ ...item,
190
+ click: () => {
191
+ selectedYear.value = item.year;
192
+ monthMode.value = true;
193
+ focusFirstItem();
194
+ },
195
+ };
196
+ }),
197
+ );
198
+
199
+ const prevYearItems = computed(() =>
200
+ getYearItems(
201
+ getStartYear(selectedYearGroup.value - 1),
202
+ getEndYear(selectedYearGroup.value - 1),
203
+ ),
204
+ );
205
+
206
+ const prevYearItemsEnabled = computed(() =>
207
+ prevYearItems.value.some(i => !i.isDisabled),
208
+ );
209
+
210
+ const nextYearItems = computed(() =>
211
+ getYearItems(
212
+ getStartYear(selectedYearGroup.value + 1),
213
+ getEndYear(selectedYearGroup.value + 1),
214
+ ),
215
+ );
216
+
217
+ const nextYearItemsEnabled = computed(() =>
218
+ nextYearItems.value.some(i => !i.isDisabled),
219
+ );
220
+
221
+ const activeItems = computed(() =>
222
+ monthMode.value ? monthItems.value : yearItems.value,
223
+ );
224
+
225
+ const prevItemsEnabled = computed(() =>
226
+ monthMode.value ? prevMonthItemsEnabled.value : prevYearItemsEnabled.value,
227
+ );
228
+
229
+ const nextItemsEnabled = computed(() =>
230
+ monthMode.value ? nextMonthItemsEnabled.value : nextYearItemsEnabled.value,
231
+ );
232
+
233
+ const firstYear = computed(() => head(yearItems.value.map(i => i.year)));
234
+
235
+ const lastYear = computed(() => last(yearItems.value.map(i => i.year)));
236
+
237
+ const title = computed(() => {
238
+ return monthMode.value
239
+ ? selectedYear.value
240
+ : `${firstYear.value} - ${lastYear.value}`;
241
+ });
242
+
243
+ watchEffect(() => {
244
+ selectedYear.value = page.value.year;
245
+ focusFirstItem();
246
+ });
247
+
248
+ watch(
249
+ () => selectedYear.value,
250
+ val => (selectedYearGroup.value = getYearGroupIndex(val)),
251
+ );
252
+
253
+ onMounted(() => focusFirstItem());
254
+ </script>
255
+
256
+ <style lang="css">
257
+ .vc-nav-header {
258
+ display: flex;
259
+ justify-content: space-between;
260
+ }
261
+
262
+ .vc-nav-title,
263
+ .vc-nav-arrow,
264
+ .vc-nav-item {
265
+ font-size: var(--vc-text-sm);
266
+ margin: 0;
267
+ cursor: pointer;
268
+ user-select: none;
269
+ border: 0;
270
+ border-radius: var(--vc-rounded);
271
+ white-space: nowrap;
272
+ &:hover {
273
+ background-color: var(--vc-nav-hover-bg);
274
+ }
275
+ &:disabled {
276
+ opacity: 0.25;
277
+ pointer-events: none;
278
+ }
279
+ }
280
+
281
+ .vc-nav-title {
282
+ color: var(--vc-nav-title-color);
283
+ font-weight: var(--vc-font-bold);
284
+ line-height: var(--vc-leading-snug);
285
+ height: 30px;
286
+ padding: 0 6px;
287
+ }
288
+
289
+ .vc-nav-arrow {
290
+ display: flex;
291
+ justify-content: center;
292
+ align-items: center;
293
+ color: var(--vc-header-arrow-color);
294
+ width: 26px;
295
+ height: 30px;
296
+ padding: 0;
297
+ }
298
+
299
+ .vc-nav-items {
300
+ display: grid;
301
+ grid-template-columns: repeat(3, 1fr);
302
+ grid-row-gap: 2px;
303
+ grid-column-gap: 5px;
304
+ margin-top: 2px;
305
+ }
306
+
307
+ .vc-nav-item {
308
+ width: 48px;
309
+ text-align: center;
310
+ font-weight: var(--vc-font-semibold);
311
+ line-height: var(--vc-leading-snug);
312
+ padding: 6px 0;
313
+ &.is-active {
314
+ color: var(--vc-nav-item-active-color);
315
+ background-color: var(--vc-nav-item-active-bg);
316
+ font-weight: var(--vc-font-bold);
317
+ &:not(:focus) {
318
+ box-shadow: var(--vc-nav-item-active-box-shadow);
319
+ }
320
+ }
321
+ &.is-current {
322
+ color: var(--vc-nav-item-current-color);
323
+ }
324
+ }
325
+ </style>
@@ -0,0 +1,24 @@
1
+ <template>
2
+ <Popover
3
+ :id="navPopoverId"
4
+ :class="['vc-nav-popover-container', `vc-${color}`, `vc-${displayMode}`]"
5
+ >
6
+ <template #default="{ data }">
7
+ <CalendarPageProvider :page="data.page">
8
+ <CalendarSlot name="nav">
9
+ <CalendarNav />
10
+ </CalendarSlot>
11
+ </CalendarPageProvider>
12
+ </template>
13
+ </Popover>
14
+ </template>
15
+
16
+ <script setup lang="ts">
17
+ import { useCalendar } from '../../use/calendar';
18
+ import Popover from '../Popover/Popover.vue';
19
+ import CalendarNav from './CalendarNav.vue';
20
+ import CalendarPageProvider from './CalendarPageProvider.vue';
21
+ import CalendarSlot from './CalendarSlot.vue';
22
+
23
+ const { navPopoverId, color, displayMode } = useCalendar();
24
+ </script>
@@ -0,0 +1,140 @@
1
+ <template>
2
+ <div
3
+ :class="[
4
+ 'vc-pane',
5
+ `row-${page.row}`,
6
+ `row-from-end-${page.rowFromEnd}`,
7
+ `column-${page.column}`,
8
+ `column-from-end-${page.columnFromEnd}`,
9
+ ]"
10
+ ref="pane"
11
+ >
12
+ <CalendarHeader :page="page" is-lg hide-arrows />
13
+ <div
14
+ class="vc-weeks"
15
+ :class="{
16
+ [`vc-show-weeknumbers-${page.weeknumberPosition}`]:
17
+ page.weeknumberPosition,
18
+ }"
19
+ >
20
+ <div class="vc-weekdays">
21
+ <!--Weekday labels-->
22
+ <div
23
+ v-for="({ weekday, label }, i) in page.weekdays"
24
+ :key="i"
25
+ :class="`vc-weekday vc-weekday-${weekday}`"
26
+ >
27
+ {{ label }}
28
+ </div>
29
+ </div>
30
+ <!--Weeks-->
31
+ <div
32
+ v-for="week in page.viewWeeks"
33
+ :key="`weeknumber-${week.weeknumber}`"
34
+ class="vc-week"
35
+ >
36
+ <!--Weeknumber-->
37
+ <div
38
+ v-if="page.weeknumberPosition"
39
+ :class="['vc-weeknumber', `is-${page.weeknumberPosition}`]"
40
+ >
41
+ <span
42
+ :class="['vc-weeknumber-content']"
43
+ @click="onWeeknumberClick(week, $event)"
44
+ >{{ week.weeknumberDisplay }}</span
45
+ >
46
+ </div>
47
+ <!--Week days-->
48
+ <CalendarDay v-for="day in week.days" :key="day.id" :day="day" />
49
+ </div>
50
+ </div>
51
+ </div>
52
+ </template>
53
+
54
+ <script lang="ts">
55
+ export default {
56
+ inheritAttrs: false,
57
+ };
58
+ </script>
59
+
60
+ <script setup lang="ts">
61
+ import CalendarDay from './CalendarDay.vue';
62
+ import CalendarHeader from './CalendarHeader.vue';
63
+ import { useCalendar } from '../../use/calendar';
64
+ import { usePage } from '../../use/page';
65
+
66
+ const { page } = usePage();
67
+ const { onWeeknumberClick } = useCalendar();
68
+ </script>
69
+
70
+ <style lang="css">
71
+ .vc-pane {
72
+ min-width: 250px;
73
+ }
74
+
75
+ .vc-weeknumber {
76
+ display: flex;
77
+ justify-content: center;
78
+ align-items: center;
79
+ position: absolute;
80
+ &.is-left {
81
+ left: calc(var(--vc-weeknumber-offset-inside) * -1);
82
+ }
83
+ &.is-right {
84
+ right: calc(var(--vc-weeknumber-offset-inside) * -1);
85
+ }
86
+ &.is-left-outside {
87
+ left: calc(var(--vc-weeknumber-offset-outside) * -1);
88
+ }
89
+ &.is-right-outside {
90
+ right: calc(var(--vc-weeknumber-offset-outside) * -1);
91
+ }
92
+ }
93
+
94
+ .vc-weeknumber-content {
95
+ display: flex;
96
+ justify-content: center;
97
+ align-items: center;
98
+ font-size: var(--vc-text-xs);
99
+ font-weight: var(--vc-font-medium);
100
+ font-style: italic;
101
+ width: 28px;
102
+ height: 28px;
103
+ margin-top: 2px;
104
+ color: var(--vc-weeknumber-color);
105
+ user-select: none;
106
+ }
107
+
108
+ .vc-weeks {
109
+ position: relative;
110
+ /* overflow: auto; */
111
+ -webkit-overflow-scrolling: touch;
112
+ padding: 6px;
113
+ min-width: 232px;
114
+ &.vc-show-weeknumbers-left {
115
+ margin-left: var(--vc-weeknumber-offset-inside);
116
+ }
117
+ &.vc-show-weeknumbers-right {
118
+ margin-right: var(--vc-weeknumber-offset-inside);
119
+ }
120
+ }
121
+
122
+ .vc-weekday {
123
+ text-align: center;
124
+ color: var(--vc-weekday-color);
125
+ font-size: var(--vc-text-sm);
126
+ font-weight: var(--vc-font-bold);
127
+ line-height: 14px;
128
+ padding-top: 4px;
129
+ padding-bottom: 8px;
130
+ cursor: default;
131
+ user-select: none;
132
+ }
133
+
134
+ .vc-week,
135
+ .vc-weekdays {
136
+ display: grid;
137
+ grid-template-columns: repeat(7, 1fr);
138
+ position: relative;
139
+ }
140
+ </style>
@@ -0,0 +1,15 @@
1
+ <template>
2
+ <slot />
3
+ </template>
4
+
5
+ <script setup lang="ts">
6
+ import { toRef } from 'vue';
7
+ import { createPage } from '../../use/page';
8
+ import type { Page } from '../../utils/page';
9
+
10
+ const props = defineProps<{
11
+ page: Page;
12
+ }>();
13
+
14
+ createPage(toRef(props, 'page'));
15
+ </script>
@@ -0,0 +1,36 @@
1
+ <template>
2
+ <Component v-if="slot" :is="slot" v-bind="$attrs" />
3
+ <slot v-else />
4
+ </template>
5
+
6
+ <script lang="ts">
7
+ export default {
8
+ inheritAttrs: false,
9
+ };
10
+ </script>
11
+
12
+ <script setup lang="ts">
13
+ import { useSlot } from '../../use/slots';
14
+ import { VNode } from 'vue';
15
+
16
+ export type CalendarSlotName =
17
+ | 'day-content'
18
+ | 'day-popover'
19
+ | 'dp-footer'
20
+ | 'footer'
21
+ | 'header-title-wrapper'
22
+ | 'header-title'
23
+ | 'header-prev-button'
24
+ | 'header-next-button'
25
+ | 'nav'
26
+ | 'nav-prev-button'
27
+ | 'nav-next-button'
28
+ | 'page'
29
+ | 'time-header';
30
+
31
+ const props = defineProps<{
32
+ name: CalendarSlotName;
33
+ }>();
34
+
35
+ const slot = useSlot(props.name) as unknown as VNode|VNode[];
36
+ </script>
@@ -0,0 +1,72 @@
1
+ <template>
2
+ <div class="vc-title-select-nav">
3
+ <BaseSelect v-model="value" :options="monthOptions" fit-content />
4
+ <BaseSelect v-model="value" :options="yearOptions" fit-content />
5
+ </div>
6
+ </template>
7
+
8
+ <script setup lang="ts">
9
+ import { computed, ref, watch } from 'vue';
10
+ import { useCalendar } from '../../use/calendar';
11
+ import { usePage } from '../../use/page';
12
+ import { getPageId } from '../../utils/page';
13
+ import BaseSelect from '../BaseSelect/BaseSelect.vue';
14
+
15
+ const props = defineProps({
16
+ monthFormat: { type: String, default: 'MMMM' },
17
+ });
18
+
19
+ const { move, minPage, maxPage } = useCalendar();
20
+ const { page, getMonthItems, getYearItems } = usePage();
21
+
22
+ const value = ref(getPageId(page.value.month, page.value.year));
23
+
24
+ const defaultMinYear = 1900;
25
+ const defaultMaxYear = 2100;
26
+
27
+ const minYear = computed(() => {
28
+ if (minPage.value != null) return minPage.value.year;
29
+ if (maxPage.value != null) return maxPage.value.year - 200;
30
+ return defaultMinYear;
31
+ });
32
+
33
+ const maxYear = computed(() => {
34
+ if (maxPage.value != null) return maxPage.value.year;
35
+ if (minPage.value != null) return minPage.value.year + 200;
36
+ return defaultMaxYear;
37
+ });
38
+
39
+ const monthItems = computed(() =>
40
+ getMonthItems(page.value.year, props.monthFormat),
41
+ );
42
+ const monthOptions = computed(() =>
43
+ monthItems.value.map(item => ({
44
+ value: item.id,
45
+ label: item.label,
46
+ disabled: item.isDisabled,
47
+ })),
48
+ );
49
+
50
+ const yearItems = computed(() => getYearItems(minYear.value, maxYear.value));
51
+ const yearOptions = computed(() =>
52
+ yearItems.value.map(item => ({
53
+ value: item.id,
54
+ label: item.label,
55
+ disabled: item.isDisabled,
56
+ })),
57
+ );
58
+
59
+ watch(
60
+ () => value.value,
61
+ val => move(val, { position: page.value.position, transition: 'none' }),
62
+ );
63
+ </script>
64
+
65
+ <style lang="css">
66
+ .vc-title-select-nav {
67
+ display: flex;
68
+ > * + * {
69
+ margin-left: 4px;
70
+ }
71
+ }
72
+ </style>