@bagelink/vue 0.0.1218 → 0.0.1220

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 (138) hide show
  1. package/dist/components/Calendar/Index.vue.d.ts +510 -0
  2. package/dist/components/Calendar/Index.vue.d.ts.map +1 -0
  3. package/dist/components/Calendar/components/header/Header.vue.d.ts +117 -0
  4. package/dist/components/Calendar/components/header/Header.vue.d.ts.map +1 -0
  5. package/dist/components/Calendar/components/month/AgendaEventTile.vue.d.ts +37 -0
  6. package/dist/components/Calendar/components/month/AgendaEventTile.vue.d.ts.map +1 -0
  7. package/dist/components/Calendar/components/month/AgendaEvents.vue.d.ts +37 -0
  8. package/dist/components/Calendar/components/month/AgendaEvents.vue.d.ts.map +1 -0
  9. package/dist/components/Calendar/components/month/Day.vue.d.ts +84 -0
  10. package/dist/components/Calendar/components/month/Day.vue.d.ts.map +1 -0
  11. package/dist/components/Calendar/components/month/Event.vue.d.ts +69 -0
  12. package/dist/components/Calendar/components/month/Event.vue.d.ts.map +1 -0
  13. package/dist/components/Calendar/components/month/Month.vue.d.ts +134 -0
  14. package/dist/components/Calendar/components/month/Month.vue.d.ts.map +1 -0
  15. package/dist/components/Calendar/components/month/WeekDay.vue.d.ts +7 -0
  16. package/dist/components/Calendar/components/month/WeekDay.vue.d.ts.map +1 -0
  17. package/dist/components/Calendar/components/partials/EventFlyout.vue.d.ts +122 -0
  18. package/dist/components/Calendar/components/partials/EventFlyout.vue.d.ts.map +1 -0
  19. package/dist/components/Calendar/components/week/Day.vue.d.ts +152 -0
  20. package/dist/components/Calendar/components/week/Day.vue.d.ts.map +1 -0
  21. package/dist/components/Calendar/components/week/DayEvent.vue.d.ts +136 -0
  22. package/dist/components/Calendar/components/week/DayEvent.vue.d.ts.map +1 -0
  23. package/dist/components/Calendar/components/week/DayTimeline.vue.d.ts +23 -0
  24. package/dist/components/Calendar/components/week/DayTimeline.vue.d.ts.map +1 -0
  25. package/dist/components/Calendar/components/week/FullDayEvent.vue.d.ts +42 -0
  26. package/dist/components/Calendar/components/week/FullDayEvent.vue.d.ts.map +1 -0
  27. package/dist/components/Calendar/components/week/Week.vue.d.ts +196 -0
  28. package/dist/components/Calendar/components/week/Week.vue.d.ts.map +1 -0
  29. package/dist/components/Calendar/components/week/WeekTimeline.vue.d.ts +21 -0
  30. package/dist/components/Calendar/components/week/WeekTimeline.vue.d.ts.map +1 -0
  31. package/dist/components/Calendar/constants.d.ts +13 -0
  32. package/dist/components/Calendar/constants.d.ts.map +1 -0
  33. package/dist/components/Calendar/helpers/DayIntervals.d.ts +17 -0
  34. package/dist/components/Calendar/helpers/DayIntervals.d.ts.map +1 -0
  35. package/dist/components/Calendar/helpers/EDate.d.ts +10 -0
  36. package/dist/components/Calendar/helpers/EDate.d.ts.map +1 -0
  37. package/dist/components/Calendar/helpers/Errors.d.ts +18 -0
  38. package/dist/components/Calendar/helpers/Errors.d.ts.map +1 -0
  39. package/dist/components/Calendar/helpers/EventChange.d.ts +19 -0
  40. package/dist/components/Calendar/helpers/EventChange.d.ts.map +1 -0
  41. package/dist/components/Calendar/helpers/EventConcurrency.d.ts +12 -0
  42. package/dist/components/Calendar/helpers/EventConcurrency.d.ts.map +1 -0
  43. package/dist/components/Calendar/helpers/EventFlyoutPosition.d.ts +14 -0
  44. package/dist/components/Calendar/helpers/EventFlyoutPosition.d.ts.map +1 -0
  45. package/dist/components/Calendar/helpers/EventPosition.d.ts +11 -0
  46. package/dist/components/Calendar/helpers/EventPosition.d.ts.map +1 -0
  47. package/dist/components/Calendar/helpers/EventsFilter.d.ts +11 -0
  48. package/dist/components/Calendar/helpers/EventsFilter.d.ts.map +1 -0
  49. package/dist/components/Calendar/helpers/Helpers.d.ts +19 -0
  50. package/dist/components/Calendar/helpers/Helpers.d.ts.map +1 -0
  51. package/dist/components/Calendar/helpers/Time.d.ts +118 -0
  52. package/dist/components/Calendar/helpers/Time.d.ts.map +1 -0
  53. package/dist/components/Calendar/helpers/Week.d.ts +10 -0
  54. package/dist/components/Calendar/helpers/Week.d.ts.map +1 -0
  55. package/dist/components/Calendar/index.d.ts +4 -0
  56. package/dist/components/Calendar/index.d.ts.map +1 -0
  57. package/dist/components/Calendar/language/index.d.ts +6 -0
  58. package/dist/components/Calendar/language/index.d.ts.map +1 -0
  59. package/dist/components/Calendar/language/keys.d.ts +90 -0
  60. package/dist/components/Calendar/language/keys.d.ts.map +1 -0
  61. package/dist/components/Calendar/models/Event.d.ts +50 -0
  62. package/dist/components/Calendar/models/Event.d.ts.map +1 -0
  63. package/dist/components/Calendar/typings/config.interface.d.ts +77 -0
  64. package/dist/components/Calendar/typings/config.interface.d.ts.map +1 -0
  65. package/dist/components/Calendar/typings/interfaces/day.interface.d.ts +10 -0
  66. package/dist/components/Calendar/typings/interfaces/day.interface.d.ts.map +1 -0
  67. package/dist/components/Calendar/typings/interfaces/event.interface.d.ts +32 -0
  68. package/dist/components/Calendar/typings/interfaces/event.interface.d.ts.map +1 -0
  69. package/dist/components/Calendar/typings/interfaces/full-day-events-week.type.d.ts +7 -0
  70. package/dist/components/Calendar/typings/interfaces/full-day-events-week.type.d.ts.map +1 -0
  71. package/dist/components/Calendar/typings/interfaces/period.interface.d.ts +6 -0
  72. package/dist/components/Calendar/typings/interfaces/period.interface.d.ts.map +1 -0
  73. package/dist/components/Calendar/typings/interfaces/time-modes.d.ts +6 -0
  74. package/dist/components/Calendar/typings/interfaces/time-modes.d.ts.map +1 -0
  75. package/dist/components/Calendar/typings/types.d.ts +21 -0
  76. package/dist/components/Calendar/typings/types.d.ts.map +1 -0
  77. package/dist/components/DataTable/DataTable.vue.d.ts.map +1 -1
  78. package/dist/components/form/inputs/DatePick.vue.d.ts +8 -0
  79. package/dist/components/form/inputs/DatePick.vue.d.ts.map +1 -1
  80. package/dist/components/form/inputs/NumberInput.vue.d.ts.map +1 -1
  81. package/dist/components/index.d.ts +2 -1
  82. package/dist/components/index.d.ts.map +1 -1
  83. package/dist/directives/index.d.ts +2 -0
  84. package/dist/directives/index.d.ts.map +1 -1
  85. package/dist/directives/vResize.d.ts +18 -0
  86. package/dist/directives/vResize.d.ts.map +1 -0
  87. package/dist/index.cjs +3583 -111
  88. package/dist/index.mjs +3584 -112
  89. package/dist/style.css +843 -77
  90. package/package.json +2 -1
  91. package/src/components/Calendar/Index.vue +420 -0
  92. package/src/components/Calendar/assets/base.css +60 -0
  93. package/src/components/Calendar/components/header/Header.vue +274 -0
  94. package/src/components/Calendar/components/month/AgendaEventTile.vue +137 -0
  95. package/src/components/Calendar/components/month/AgendaEvents.vue +107 -0
  96. package/src/components/Calendar/components/month/Day.vue +271 -0
  97. package/src/components/Calendar/components/month/Event.vue +221 -0
  98. package/src/components/Calendar/components/month/Month.vue +278 -0
  99. package/src/components/Calendar/components/month/WeekDay.vue +25 -0
  100. package/src/components/Calendar/components/partials/EventFlyout.vue +429 -0
  101. package/src/components/Calendar/components/week/Day.vue +212 -0
  102. package/src/components/Calendar/components/week/DayEvent.vue +585 -0
  103. package/src/components/Calendar/components/week/DayTimeline.vue +86 -0
  104. package/src/components/Calendar/components/week/FullDayEvent.vue +121 -0
  105. package/src/components/Calendar/components/week/Week.vue +414 -0
  106. package/src/components/Calendar/components/week/WeekTimeline.vue +126 -0
  107. package/src/components/Calendar/constants.ts +13 -0
  108. package/src/components/Calendar/env.d.ts +8 -0
  109. package/src/components/Calendar/helpers/DayIntervals.ts +48 -0
  110. package/src/components/Calendar/helpers/EDate.ts +18 -0
  111. package/src/components/Calendar/helpers/Errors.ts +69 -0
  112. package/src/components/Calendar/helpers/EventChange.ts +88 -0
  113. package/src/components/Calendar/helpers/EventConcurrency.ts +69 -0
  114. package/src/components/Calendar/helpers/EventFlyoutPosition.ts +96 -0
  115. package/src/components/Calendar/helpers/EventPosition.ts +154 -0
  116. package/src/components/Calendar/helpers/EventsFilter.ts +50 -0
  117. package/src/components/Calendar/helpers/Helpers.ts +86 -0
  118. package/src/components/Calendar/helpers/Time.ts +588 -0
  119. package/src/components/Calendar/helpers/Week.ts +37 -0
  120. package/src/components/Calendar/index.ts +4 -0
  121. package/src/components/Calendar/language/index.ts +37 -0
  122. package/src/components/Calendar/language/keys.ts +90 -0
  123. package/src/components/Calendar/models/Event.ts +112 -0
  124. package/src/components/Calendar/styles/_mixins.css +21 -0
  125. package/src/components/Calendar/styles/_variables.css +51 -0
  126. package/src/components/Calendar/typings/config.interface.ts +87 -0
  127. package/src/components/Calendar/typings/interfaces/day.interface.ts +10 -0
  128. package/src/components/Calendar/typings/interfaces/event.interface.ts +32 -0
  129. package/src/components/Calendar/typings/interfaces/full-day-events-week.type.ts +8 -0
  130. package/src/components/Calendar/typings/interfaces/period.interface.ts +5 -0
  131. package/src/components/Calendar/typings/interfaces/time-modes.ts +9 -0
  132. package/src/components/Calendar/typings/types.ts +23 -0
  133. package/src/components/DataTable/DataTable.vue +4 -0
  134. package/src/components/form/inputs/DatePick.vue +189 -152
  135. package/src/components/form/inputs/NumberInput.vue +1 -3
  136. package/src/components/index.ts +3 -6
  137. package/src/directives/index.ts +2 -0
  138. package/src/directives/vResize.ts +205 -0
@@ -0,0 +1,585 @@
1
+ <script setup lang="ts">
2
+ import type { PropType } from 'vue'
3
+ import type Time from '../../helpers/Time'
4
+ import type { ConfigInterface } from '../../typings/config.interface'
5
+ import type { EventInterface } from '../../typings/interfaces/event.interface'
6
+ import type { DayInfo, modeType } from '../../typings/types'
7
+ import { Icon } from '@bagelink/vue'
8
+
9
+ import { ref, computed, onMounted, watch } from 'vue'
10
+ import { EVENT_COLORS } from '../../constants'
11
+ import { EventChange } from '../../helpers/EventChange'
12
+ import Helpers from '../../helpers/Helpers'
13
+ import { DRAG_N_RESIZE_DIRECTION } from '../../typings/types'
14
+
15
+ const props = defineProps({
16
+ eventProp: {
17
+ type: Object as PropType<EventInterface>,
18
+ required: true,
19
+ },
20
+ time: {
21
+ type: Object as PropType<Time>,
22
+ required: true,
23
+ },
24
+ config: {
25
+ type: Object as PropType<ConfigInterface>,
26
+ required: true,
27
+ },
28
+ dayInfo: {
29
+ type: Object as PropType<DayInfo>,
30
+ required: true,
31
+ },
32
+ mode: {
33
+ type: String as PropType<modeType>,
34
+ required: true,
35
+ },
36
+ })
37
+
38
+ const emit = defineEmits<{
39
+ (e: 'eventWasClicked', data: { clickedEvent: EventInterface, eventElement: HTMLElement }): void
40
+ (e: 'eventWasResized', event: EventInterface): void
41
+ (e: 'eventWasDragged', event: EventInterface): void
42
+ (e: 'dragStart'): void
43
+ (e: 'dragEnd'): void
44
+ }>()
45
+
46
+ const event = ref(props.eventProp)
47
+ const icons = ref({
48
+ clock: 'clock',
49
+ user: 'user',
50
+ description: 'description',
51
+ location: 'location_on',
52
+ topic: 'topic',
53
+ })
54
+
55
+ const showResizeElements = ref(false)
56
+ const eventTransformValue = ref('initial')
57
+ const eventZIndexValue = ref<'initial' | number>('initial')
58
+ const dayElement = ref<Element | null>(null)
59
+
60
+ // Resizing events
61
+ const resizingStartingPoint = ref<undefined | number>(undefined)
62
+ const resizingStartingPointEndOfTime = ref(props.eventProp.time.end)
63
+ const resizingStartingPointStartOfTime = ref(props.eventProp.time.start)
64
+ const resizingDirection = ref('')
65
+ const changeInQuarterHoursEventStart = ref(0)
66
+ const changeInQuarterHoursEventEnd = ref(0)
67
+ const isEditable = ref(props.eventProp.isEditable || false)
68
+ const colors = ref(EVENT_COLORS as { [key: string]: string })
69
+ const eventColor = ref('#fff')
70
+ const eventBackgroundColor = ref('')
71
+ const isResizing = ref(false)
72
+
73
+ // Dragging events
74
+ const canDrag = ref(false)
75
+ const clientYDragStart = ref<null | number>(null)
76
+ const clientXDragStart = ref<null | number>(null)
77
+ const changeInQuartersOnDrag = ref(0)
78
+ const changeInDaysOnDrag = ref(0)
79
+ const isDragging = ref(false)
80
+ const timeStartDragStart = ref(props.eventProp.time.start)
81
+ const timeEndDragStart = ref(props.eventProp.time.end)
82
+
83
+ const dragMoveListenerNameAndCallbacks = [
84
+ ['mousemove', handleDrag],
85
+ ['touchmove', handleDrag],
86
+ ['mouseup', onMouseUpWhenDragging],
87
+ ['touchend', onMouseUpWhenDragging],
88
+ ] as const
89
+
90
+ const eventChangeHelper = computed(() => {
91
+ const eventCurrentDay = props.time.addDaysToDateTimeString(changeInDaysOnDrag.value, props.dayInfo.dateTimeString)
92
+ return new EventChange(props.time, props.time.dateStringFrom(eventCurrentDay))
93
+ })
94
+
95
+ const isCustomEvent = computed(() => {
96
+ if (Array.isArray(props.eventProp.isCustom)) {
97
+ return props.eventProp.isCustom.includes(props.mode)
98
+ }
99
+ return props.eventProp.isCustom || false
100
+ })
101
+
102
+ const getEventTime = computed(() => {
103
+ return `${props.time.getLocalizedTime(event.value.time.start)} - ${props.time.getLocalizedTime(event.value.time.end)}`
104
+ })
105
+
106
+ const timePointsInDay = computed(() => props.time.HOURS_PER_DAY * 100)
107
+ const timePointsInOneMinute = computed(() => 100 / 60)
108
+
109
+ const getLeftRule = computed(() => {
110
+ if (!event.value.totalConcurrentEvents || !event.value.nOfPreviousConcurrentEvents) {
111
+ return 0
112
+ }
113
+ return (event.value.nOfPreviousConcurrentEvents / event.value.totalConcurrentEvents) * 100
114
+ })
115
+
116
+ const getWidthRule = computed(() => 100 - getLeftRule.value)
117
+ const getBorderRule = computed(() => !event.value.nOfPreviousConcurrentEvents ? 'none' : '1px solid #fff')
118
+
119
+ const eventIsLongerThan30Minutes = computed(() => {
120
+ const { hour: startHour, minutes: startMinutes } = props.time.getAllVariablesFromDateTimeString(event.value.time.start)
121
+ const { hour: endHour, minutes: endMinutes } = props.time.getAllVariablesFromDateTimeString(event.value.time.end)
122
+ const startDateMS = new Date(0, 0, 0, startHour, startMinutes).getTime()
123
+ const endDateMS = new Date(0, 0, 0, endHour, endMinutes).getTime()
124
+ return endDateMS - startDateMS >= 1800000
125
+ })
126
+
127
+ const hasDisabledDragAndDrop = computed(() => {
128
+ return !!(props.eventProp.disableDnD && props.eventProp.disableDnD.includes(props.mode))
129
+ })
130
+
131
+ const hasDisabledResize = computed(() => {
132
+ return !!(props.eventProp.disableResize && props.eventProp.disableResize.includes(props.mode))
133
+ })
134
+
135
+ const requiredStyles = computed(() => ({
136
+ top: getPositionInDay(event.value.time.start),
137
+ height: getLengthOfEvent(event.value.time.start, event.value.time.end),
138
+ left: `${getLeftRule.value}%`,
139
+ width: `${getWidthRule.value}%`,
140
+ transform: eventTransformValue.value,
141
+ zIndex: eventZIndexValue.value,
142
+ }))
143
+
144
+ // Methods
145
+ function getPositionInDay(dateTimeString: string) {
146
+ return `${props.time.getPercentageOfDayFromDateTimeString(dateTimeString, props.time.DAY_START, props.time.DAY_END).toString()}%`
147
+ }
148
+
149
+ function getLengthOfEvent(start: string, end: string) {
150
+ const startOfEvent = props.time.getPercentageOfDayFromDateTimeString(start, props.time.DAY_START, props.time.DAY_END)
151
+ const endOfEvent = props.time.getPercentageOfDayFromDateTimeString(end, props.time.DAY_START, props.time.DAY_END)
152
+ const length = Math.abs(endOfEvent - startOfEvent)
153
+ return `${length}%`
154
+ }
155
+
156
+ function handleClickOnEvent(event: any) {
157
+ const eventElement = getEventElementFromChildElement(event)
158
+ if (!eventElement) return
159
+ emit('eventWasClicked', {
160
+ clickedEvent: props.eventProp,
161
+ eventElement,
162
+ })
163
+ }
164
+
165
+ function getEventElementFromChildElement(event: any) {
166
+ const eventTarget = event.target
167
+ if (!eventTarget || typeof eventTarget.className.includes !== 'function') return null
168
+ if (eventTarget.className.includes('.calendar-week__event')) return event.target
169
+ return eventTarget.closest('.calendar-week__event')
170
+ }
171
+
172
+ function onMouseMoveResize(event: MouseEvent) {
173
+ const eventsContainer = document.querySelector('.calendar-week__events')
174
+ if (!eventsContainer) return
175
+
176
+ if (typeof resizingStartingPoint.value === 'undefined') {
177
+ resizingStartingPoint.value = event.clientY
178
+ }
179
+
180
+ const cursorPositionY = event.clientY
181
+ const nOfPixelsDistance = cursorPositionY - resizingStartingPoint.value
182
+ const eventsContainerHeight = eventsContainer.clientHeight
183
+ const percentageOfDayChanged = (nOfPixelsDistance / eventsContainerHeight) * 100
184
+ const changeInTimePoints = (timePointsInDay.value / 100) * percentageOfDayChanged
185
+ const changeInMinutes = getMinutesFromTimePoints(changeInTimePoints)
186
+
187
+ if (resizingDirection.value === 'down') {
188
+ changeInQuarterHoursEventEnd.value = Math.floor(changeInMinutes / 15)
189
+ } else {
190
+ changeInQuarterHoursEventStart.value = Math.floor(changeInMinutes / 15)
191
+ }
192
+ }
193
+
194
+ function onMouseUpWhenResizing() {
195
+ stopResizing()
196
+ }
197
+
198
+ function resizeEvent(direction: 'down' | 'up') {
199
+ isResizing.value = true
200
+ resizingDirection.value = direction
201
+ document.addEventListener('mousemove', onMouseMoveResize)
202
+ document.addEventListener('mouseup', onMouseUpWhenResizing)
203
+ }
204
+
205
+ function stopResizing() {
206
+ document.removeEventListener('mousemove', onMouseMoveResize)
207
+ document.removeEventListener('mouseup', onMouseUpWhenResizing)
208
+ resetResizingValues()
209
+ emit('eventWasResized', event.value)
210
+ isResizing.value = false
211
+ }
212
+
213
+ function resetResizingValues() {
214
+ resizingStartingPoint.value = undefined
215
+ resizingStartingPointStartOfTime.value = props.eventProp.time.start
216
+ resizingStartingPointEndOfTime.value = props.eventProp.time.end
217
+ changeInQuarterHoursEventEnd.value = 0
218
+ }
219
+
220
+ function getMinutesFromTimePoints(timePoints: number) {
221
+ return timePoints / timePointsInOneMinute.value
222
+ }
223
+
224
+ function setColors() {
225
+ if (
226
+ event.value.colorScheme
227
+ && props.config.style?.colorSchemes
228
+ && props.config.style.colorSchemes[event.value.colorScheme]
229
+ ) {
230
+ eventColor.value = props.config.style.colorSchemes[event.value.colorScheme].color
231
+ eventBackgroundColor.value = props.config.style.colorSchemes[event.value.colorScheme].backgroundColor
232
+ return
233
+ }
234
+
235
+ if (event.value.color) {
236
+ eventColor.value = '#fff'
237
+ eventBackgroundColor.value = colors.value[event.value.color]
238
+ return
239
+ }
240
+
241
+ eventBackgroundColor.value = colors.value.blue
242
+ }
243
+
244
+ function initDrag(domEvent: UIEvent) {
245
+ if (!event.value.isEditable || hasDisabledDragAndDrop.value) return
246
+
247
+ emit('dragStart')
248
+
249
+ dragMoveListenerNameAndCallbacks.forEach(([name, callback]) => {
250
+ document.addEventListener(name, callback)
251
+ })
252
+
253
+ if (Helpers.isUIEventTouchEvent(domEvent)) {
254
+ setInitialDragValues(
255
+ (domEvent as TouchEvent).touches[0].clientX,
256
+ (domEvent as TouchEvent).touches[0].clientY
257
+ )
258
+ } else {
259
+ setInitialDragValues((domEvent as MouseEvent).clientX, (domEvent as MouseEvent).clientY)
260
+ }
261
+ }
262
+
263
+ function setInitialDragValues(clientX: number, clientY: number) {
264
+ canDrag.value = true
265
+ eventZIndexValue.value = 10
266
+ clientYDragStart.value = clientY
267
+ clientXDragStart.value = clientX
268
+ timeStartDragStart.value = event.value.time.start
269
+ timeEndDragStart.value = event.value.time.end
270
+ }
271
+
272
+ function onMouseUpWhenDragging() {
273
+ emit('dragEnd')
274
+ handleDragEnd()
275
+ }
276
+
277
+ function handleDragEnd() {
278
+ canDrag.value = false
279
+ eventZIndexValue.value = 'initial'
280
+ dragMoveListenerNameAndCallbacks.forEach(([name, callback]) => {
281
+ document.removeEventListener(name, callback)
282
+ })
283
+ const dayChanged = changeInDaysOnDrag.value <= -1 || changeInDaysOnDrag.value > 0
284
+ const timeChanged = changeInQuartersOnDrag.value <= -1 || changeInQuartersOnDrag.value > 0
285
+ if (dayChanged || timeChanged) emit('eventWasDragged', event.value)
286
+ }
287
+
288
+ function handleDrag(mouseEvent: UIEvent) {
289
+ if (isResizing.value || !canDrag.value || !clientYDragStart.value) return
290
+
291
+ if (Helpers.isUIEventTouchEvent(mouseEvent)) {
292
+ handleVerticalDrag((mouseEvent as TouchEvent).touches[0].clientY)
293
+ handleHorizontalDrag((mouseEvent as TouchEvent).touches[0].clientX)
294
+ } else {
295
+ handleVerticalDrag((mouseEvent as MouseEvent).clientY)
296
+ handleHorizontalDrag((mouseEvent as MouseEvent).clientX)
297
+ }
298
+ }
299
+
300
+ function handleVerticalDrag(clientY: number) {
301
+ const eventsContainer = document.querySelector('.calendar-week__events')
302
+ if (!eventsContainer || !clientYDragStart.value) return
303
+
304
+ const nOfPixelsDistance = clientY - clientYDragStart.value
305
+ const eventsContainerHeight = eventsContainer.clientHeight
306
+ const percentageOfDayChanged = (nOfPixelsDistance / eventsContainerHeight) * 100
307
+ const changeInTimePoints = (timePointsInDay.value / 100) * percentageOfDayChanged
308
+ const changeInMinutes = getMinutesFromTimePoints(changeInTimePoints)
309
+ changeInQuartersOnDrag.value = changeInMinutes < 0
310
+ ? Math.ceil(changeInMinutes / 15)
311
+ : Math.floor(changeInMinutes / 15)
312
+ }
313
+
314
+ function handleHorizontalDrag(clientX: number) {
315
+ if (!dayElement.value || !clientXDragStart.value) return
316
+
317
+ const dayWidth = dayElement.value.clientWidth
318
+ const changeInPixelsX = clientX - clientXDragStart.value
319
+ changeInDaysOnDrag.value = changeInPixelsX < 0
320
+ ? Math.ceil(changeInPixelsX / dayWidth)
321
+ : Math.floor(changeInPixelsX / dayWidth)
322
+ }
323
+
324
+ function updatePositionOnDrag() {
325
+ const minutesChangedVertically = changeInQuartersOnDrag.value * 15
326
+ const minutesChangedHorizontally = changeInDaysOnDrag.value * 1440
327
+
328
+ event.value.time.start = props.time.addMinutesToDateTimeString(
329
+ minutesChangedVertically + minutesChangedHorizontally,
330
+ timeStartDragStart.value
331
+ )
332
+
333
+ event.value.time.end = props.time.addMinutesToDateTimeString(
334
+ minutesChangedVertically + minutesChangedHorizontally,
335
+ timeEndDragStart.value
336
+ )
337
+ }
338
+
339
+ // Watch effects
340
+ watch(changeInQuarterHoursEventStart, (newValue: number, oldValue: number) => {
341
+ const newStartOfTimeDateTimeString = props.time.addMinutesToDateTimeString(
342
+ 15 * newValue,
343
+ resizingStartingPointStartOfTime.value
344
+ )
345
+ const direction = newValue > oldValue ? DRAG_N_RESIZE_DIRECTION.FORWARDS : DRAG_N_RESIZE_DIRECTION.BACKWARDS
346
+ const eventCanBeResizedFurther = eventChangeHelper.value.canEventBeMoved(event.value, direction)
347
+
348
+ if (newStartOfTimeDateTimeString < event.value.time.end && eventCanBeResizedFurther) {
349
+ event.value.time.start = newStartOfTimeDateTimeString
350
+ }
351
+ })
352
+
353
+ watch(changeInQuarterHoursEventEnd, (newValue: number, oldValue: number) => {
354
+ const newEndOfTimeDateTimeString = props.time.addMinutesToDateTimeString(
355
+ 15 * newValue,
356
+ resizingStartingPointEndOfTime.value
357
+ )
358
+ const direction = newValue > oldValue ? DRAG_N_RESIZE_DIRECTION.FORWARDS : DRAG_N_RESIZE_DIRECTION.BACKWARDS
359
+ const eventCanBeResizedFurther = eventChangeHelper.value.canEventBeMoved(event.value, direction)
360
+
361
+ if (newEndOfTimeDateTimeString > event.value.time.start && eventCanBeResizedFurther) {
362
+ event.value.time.end = newEndOfTimeDateTimeString
363
+ }
364
+ })
365
+
366
+ watch(changeInQuartersOnDrag, (newValue: number, oldValue: number) => {
367
+ const direction = newValue > oldValue ? DRAG_N_RESIZE_DIRECTION.FORWARDS : DRAG_N_RESIZE_DIRECTION.BACKWARDS
368
+ const eventCanBeDraggedFurther = eventChangeHelper.value.canEventBeMoved(event.value, direction)
369
+ if (!eventCanBeDraggedFurther) return
370
+ updatePositionOnDrag()
371
+ })
372
+
373
+ watch(changeInDaysOnDrag, (newValue: number) => {
374
+ if (!dayElement.value) return
375
+ const upcomingDaysInWeek = props.dayInfo.daysTotalN - (props.dayInfo.thisDayIndex + 1)
376
+ const previousDaysInWeek = 0 - props.dayInfo.thisDayIndex
377
+ if (newValue > upcomingDaysInWeek || newValue < previousDaysInWeek) return
378
+
379
+ const pixelsToTransform = newValue * dayElement.value.clientWidth
380
+ eventTransformValue.value = `translateX(${pixelsToTransform}px)`
381
+ updatePositionOnDrag()
382
+ })
383
+
384
+ onMounted(() => {
385
+ dayElement.value = document.querySelector('.calendar-week__day')
386
+ setColors()
387
+ })
388
+
389
+ // Accessibility handlers
390
+ function handleFocus() {
391
+ if (isEditable.value && !hasDisabledResize.value) {
392
+ showResizeElements.value = true
393
+ }
394
+ }
395
+
396
+ function handleBlur() {
397
+ showResizeElements.value = false
398
+ }
399
+ </script>
400
+
401
+ <template>
402
+ <div
403
+ class="calendar-week__event is-event"
404
+ :class="{
405
+ 'is-editable': isEditable,
406
+ 'has-disabled-dnd': hasDisabledDragAndDrop,
407
+ }"
408
+ :style="{
409
+ ...requiredStyles,
410
+ border: getBorderRule,
411
+ }"
412
+ :data-ref="`event-${event.id}`"
413
+ tabindex="0"
414
+ @click="handleClickOnEvent"
415
+ @mouseenter="handleFocus"
416
+ @mouseleave="handleBlur"
417
+ @focus="handleFocus"
418
+ @blur="handleBlur"
419
+ @mousedown="initDrag"
420
+ @touchstart="initDrag"
421
+ >
422
+ <div
423
+ v-if="!isCustomEvent"
424
+ class="calendar-week__event-info-wrapper p-05"
425
+ :style="{
426
+ color: eventColor,
427
+ width: '100%',
428
+ height: '100%',
429
+ backgroundColor: eventBackgroundColor,
430
+ }"
431
+ >
432
+ <div class="calendar-week__event-row is-title">
433
+ {{ event.title }}
434
+ </div>
435
+
436
+ <div class="calendar-week__event-row is-time">
437
+ <Icon
438
+ :icon="icons.clock"
439
+ class="calendar-week__event-icon"
440
+ />
441
+ <span>{{ getEventTime }}</span>
442
+ </div>
443
+
444
+ <div
445
+ v-if="event.location"
446
+ class="calendar-week__event-row is-location"
447
+ >
448
+ <Icon
449
+ :icon="icons.location"
450
+ class="calendar-week__event-icon"
451
+ />
452
+ <span>{{ event.location }}</span>
453
+ </div>
454
+
455
+ <div
456
+ v-if="event.with"
457
+ class="calendar-week__event-row is-with"
458
+ >
459
+ <Icon
460
+ :icon="icons.user"
461
+ class="calendar-week__event-icon"
462
+ />
463
+ <span>{{ event.with }}</span>
464
+ </div>
465
+
466
+ <div
467
+ v-if="event.topic"
468
+ class="calendar-week__event-row is-topic"
469
+ >
470
+ <Icon
471
+ :icon="icons.topic"
472
+ class="calendar-week__event-icon"
473
+ />
474
+ <span>{{ event.topic }}</span>
475
+ </div>
476
+
477
+ <div
478
+ v-if="event.description"
479
+ class="calendar-week__event-row is-description"
480
+ >
481
+ <Icon
482
+ :icon="icons.description"
483
+ class="calendar-week__event-icon"
484
+ />
485
+ <!-- eslint-disable vue/no-v-html -->
486
+ <p v-html="event.description" />
487
+ <!-- eslint-enable -->
488
+ </div>
489
+
490
+ <div
491
+ v-if="eventIsLongerThan30Minutes"
492
+ class="calendar-week__event-blend-out"
493
+ :style="{
494
+ backgroundImage: `linear-gradient(to bottom, transparent, ${eventBackgroundColor})`,
495
+ }"
496
+ />
497
+ </div>
498
+
499
+ <slot
500
+ v-else
501
+ name="weekDayEvent"
502
+ :event-data="event"
503
+ />
504
+
505
+ <div
506
+ v-if="showResizeElements"
507
+ class="calendar-week__event-resize calendar-week__event-resize-up"
508
+ @mousedown="resizeEvent('up')"
509
+ />
510
+
511
+ <div
512
+ v-if="showResizeElements"
513
+ class="calendar-week__event-resize calendar-week__event-resize-down"
514
+ @mousedown="resizeEvent('down')"
515
+ />
516
+ </div>
517
+ </template>
518
+
519
+ <style scoped>
520
+ .calendar-week__event {
521
+ position: absolute;
522
+ width: 100%;
523
+ border-radius: 4px;
524
+ cursor: pointer;
525
+ box-sizing: content-box;
526
+ user-select: none;
527
+ overflow: hidden;
528
+ }
529
+
530
+ .calendar-week__event.is-editable {
531
+ cursor: grab;
532
+ }
533
+
534
+ .calendar-week__event.has-disabled-dnd {
535
+ cursor: initial;
536
+ }
537
+
538
+ .calendar-week__event .calendar-week__event-row {
539
+ display: flex;
540
+ align-items: flex-start;
541
+ margin-bottom: 0.25em;
542
+ }
543
+
544
+ .calendar-week__event .calendar-week__event-row p {
545
+ margin: 0;
546
+ padding: 0;
547
+ }
548
+
549
+ .calendar-week__event .calendar-week__event-info-wrapper {
550
+ position: relative;
551
+ padding: var(--qalendar-spacing-half);
552
+ font-size: var(--qalendar-font-xs);
553
+ height: 100%;
554
+ box-sizing: border-box;
555
+ user-select: none;
556
+ }
557
+
558
+ .calendar-week__event .calendar-week__event-blend-out {
559
+ position: absolute;
560
+ bottom: 0;
561
+ height: 20px;
562
+ width: 100%;
563
+ transform: translateX(calc(var(--qalendar-spacing-half) * -1));
564
+ }
565
+
566
+ .calendar-week__event .calendar-week__event-icon {
567
+ margin: 2px 4px 0 0;
568
+ font-size: var(--qalendar-font-xs);
569
+ }
570
+
571
+ .calendar-week__event .calendar-week__event-resize {
572
+ position: absolute;
573
+ width: 100%;
574
+ cursor: ns-resize;
575
+ height: 5px;
576
+ }
577
+
578
+ .calendar-week__event .calendar-week__event-resize-up {
579
+ top: 0;
580
+ }
581
+
582
+ .calendar-week__event .calendar-week__event-resize-down {
583
+ bottom: 0;
584
+ }
585
+ </style>
@@ -0,0 +1,86 @@
1
+ <script setup lang="ts">
2
+ import type { PropType } from 'vue'
3
+ import type Time from '../../helpers/Time'
4
+ import type { DAY_TIME_POINT } from '../../typings/config.interface'
5
+ import { ref, onMounted } from 'vue'
6
+
7
+ const props = defineProps({
8
+ time: {
9
+ type: Object as PropType<Time>,
10
+ required: true,
11
+ },
12
+ weekHeight: {
13
+ type: String,
14
+ required: true,
15
+ },
16
+ })
17
+
18
+ // const availableHours = [0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300] as DAY_TIME_POINT[]
19
+ const timelineHours = ref<DAY_TIME_POINT[]>([])
20
+
21
+ onMounted(() => {
22
+ timelineHours.value = props.time.getTimelineHours()
23
+ })
24
+
25
+ function getLocaleTimeString(time: DAY_TIME_POINT): string {
26
+ const { hour } = props.time.getHourAndMinutesFromTimePoints(time)
27
+ return props.time.getLocalizedHour(new Date(2100, 1, 1, hour))
28
+ }
29
+ </script>
30
+
31
+ <template>
32
+ <div class="day-timeline">
33
+ <div
34
+ v-for="hour in timelineHours"
35
+ :key="hour"
36
+ class="day-timeline__hour"
37
+ >
38
+ <span class="day-timeline__hour-text">
39
+ {{ getLocaleTimeString(hour) }}
40
+ </span>
41
+ </div>
42
+ </div>
43
+ </template>
44
+
45
+ <style scoped>
46
+ .day-timeline {
47
+ position: absolute;
48
+ top: 0;
49
+ left: 0;
50
+ width: calc(100% + 10px);
51
+ height: v-bind(weekHeight);
52
+ transform: translateX(-10px);
53
+ display: flex;
54
+ flex-flow: column;
55
+ justify-content: space-evenly;
56
+ }
57
+
58
+ .day-timeline__hour {
59
+ padding-left: 4px;
60
+ display: flex;
61
+ flex-flow: column;
62
+ justify-content: flex-start;
63
+ height: 100%;
64
+ font-size: clamp(10px, 0.625rem, 14px);
65
+ color: var(--qalendar-gray-quite-dark);
66
+ }
67
+
68
+ .day-timeline__hour-text {
69
+ line-height: 0;
70
+ transform: translate(-40px, 0);
71
+ }
72
+
73
+ .day-timeline__hour:first-child .day-timeline__hour-text {
74
+ display: none;
75
+ }
76
+
77
+ .day-timeline__hour:not(:last-child) {
78
+ border-bottom: var(--qalendar-border-gray-thin);
79
+ }
80
+
81
+ @media (prefers-color-scheme: dark) {
82
+ .day-timeline__hour:not(:last-child) {
83
+ border-color: var(--qalendar-dark-mode-line-color);
84
+ }
85
+ }
86
+ </style>