@bagelink/vue 1.2.15 → 1.2.18

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 (114) hide show
  1. package/dist/components/calendar/CalendarTypes.d.ts +13 -0
  2. package/dist/components/calendar/CalendarTypes.d.ts.map +1 -0
  3. package/dist/components/calendar/Index.vue.d.ts +39 -507
  4. package/dist/components/calendar/Index.vue.d.ts.map +1 -1
  5. package/dist/components/calendar/utils.d.ts +31 -0
  6. package/dist/components/calendar/utils.d.ts.map +1 -0
  7. package/dist/components/calendar/views/AgendaView.vue.d.ts +16 -0
  8. package/dist/components/calendar/views/AgendaView.vue.d.ts.map +1 -0
  9. package/dist/components/calendar/views/DayView.vue.d.ts +50 -0
  10. package/dist/components/calendar/views/DayView.vue.d.ts.map +1 -0
  11. package/dist/components/calendar/views/MonthView.vue.d.ts +20 -0
  12. package/dist/components/calendar/views/MonthView.vue.d.ts.map +1 -0
  13. package/dist/components/calendar/views/WeekView.vue.d.ts +33 -0
  14. package/dist/components/calendar/views/WeekView.vue.d.ts.map +1 -0
  15. package/dist/components/form/BglMultiStepForm.vue.d.ts +63 -0
  16. package/dist/components/form/BglMultiStepForm.vue.d.ts.map +1 -0
  17. package/dist/components/form/index.d.ts +1 -0
  18. package/dist/components/form/index.d.ts.map +1 -1
  19. package/dist/components/form/inputs/CodeEditor/Index.vue.d.ts.map +1 -1
  20. package/dist/components/form/inputs/DateInput.vue.d.ts +3 -3
  21. package/dist/components/form/inputs/DateInput.vue.d.ts.map +1 -1
  22. package/dist/components/form/inputs/DatePicker.vue.d.ts +3 -3
  23. package/dist/components/form/inputs/DatePicker.vue.d.ts.map +1 -1
  24. package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
  25. package/dist/index.cjs +2166 -3870
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.mjs +2167 -3871
  29. package/dist/style.css +604 -628
  30. package/dist/utils/BagelFormUtils.d.ts +4 -2
  31. package/dist/utils/BagelFormUtils.d.ts.map +1 -1
  32. package/dist/utils/calendar/EDate.d.ts +2 -0
  33. package/dist/utils/calendar/EDate.d.ts.map +1 -0
  34. package/dist/utils/calendar/Helpers.d.ts +19 -0
  35. package/dist/utils/calendar/Helpers.d.ts.map +1 -0
  36. package/dist/utils/calendar/constants.d.ts +3 -0
  37. package/dist/utils/calendar/constants.d.ts.map +1 -0
  38. package/dist/utils/calendar/dateUtils.d.ts +30 -0
  39. package/dist/utils/calendar/dateUtils.d.ts.map +1 -0
  40. package/dist/utils/calendar/event.interface.d.ts +32 -0
  41. package/dist/utils/calendar/event.interface.d.ts.map +1 -0
  42. package/dist/utils/calendar/time.d.ts +117 -0
  43. package/dist/utils/calendar/time.d.ts.map +1 -0
  44. package/dist/utils/calendar/types.d.ts +27 -0
  45. package/dist/utils/calendar/types.d.ts.map +1 -0
  46. package/dist/utils/calendar/typings.d.ts +87 -0
  47. package/dist/utils/calendar/typings.d.ts.map +1 -0
  48. package/dist/utils/calendar/week.d.ts +117 -0
  49. package/dist/utils/calendar/week.d.ts.map +1 -0
  50. package/package.json +1 -1
  51. package/src/components/calendar/CalendarTypes.ts +13 -0
  52. package/src/components/calendar/Index.vue +124 -389
  53. package/src/components/calendar/utils.ts +70 -0
  54. package/src/components/calendar/views/AgendaView.vue +263 -0
  55. package/src/components/calendar/views/DayView.vue +417 -0
  56. package/src/components/calendar/views/MonthView.vue +313 -0
  57. package/src/components/calendar/views/WeekView.vue +432 -0
  58. package/src/components/form/BglMultiStepForm.vue +323 -70
  59. package/src/components/form/index.ts +1 -0
  60. package/src/components/form/inputs/CodeEditor/Index.vue +11 -0
  61. package/src/components/form/inputs/DateInput.vue +3 -3
  62. package/src/components/form/inputs/DatePicker.vue +3 -3
  63. package/src/components/form/inputs/SelectInput.vue +2 -0
  64. package/src/components/form/inputs/Upload/upload.types.d.ts +0 -1
  65. package/src/index.ts +2 -2
  66. package/src/styles/inputs.css +138 -137
  67. package/src/styles/layout.css +3 -2
  68. package/src/styles/mobilLayout.css +4 -2
  69. package/src/utils/BagelFormUtils.ts +6 -2
  70. package/src/utils/calendar/EDate.ts +0 -0
  71. package/src/{components/calendar/helpers → utils/calendar}/Helpers.ts +6 -6
  72. package/src/utils/calendar/constants.ts +2 -0
  73. package/src/utils/{timeAgo.ts → calendar/dateUtils.ts} +38 -1
  74. package/src/utils/calendar/event.interface.ts +33 -0
  75. package/src/{components/calendar/helpers/Time.ts → utils/calendar/time.ts} +15 -15
  76. package/src/utils/calendar/types.ts +27 -0
  77. package/src/{components/calendar/typings/config.interface.ts → utils/calendar/typings.ts} +13 -6
  78. package/src/utils/calendar/week.ts +588 -0
  79. package/src/components/calendar/assets/base.css +0 -60
  80. package/src/components/calendar/components/header/Header.vue +0 -153
  81. package/src/components/calendar/components/month/AgendaEventTile.vue +0 -135
  82. package/src/components/calendar/components/month/AgendaEvents.vue +0 -72
  83. package/src/components/calendar/components/month/Day.vue +0 -256
  84. package/src/components/calendar/components/month/Event.vue +0 -164
  85. package/src/components/calendar/components/month/Month.vue +0 -241
  86. package/src/components/calendar/components/month/WeekDay.vue +0 -15
  87. package/src/components/calendar/components/partials/EventFlyout.vue +0 -430
  88. package/src/components/calendar/components/week/Day.vue +0 -198
  89. package/src/components/calendar/components/week/DayEvent.vue +0 -584
  90. package/src/components/calendar/components/week/DayTimeline.vue +0 -80
  91. package/src/components/calendar/components/week/FullDayEvent.vue +0 -121
  92. package/src/components/calendar/components/week/Week.vue +0 -414
  93. package/src/components/calendar/components/week/WeekTimeline.vue +0 -101
  94. package/src/components/calendar/constants.ts +0 -13
  95. package/src/components/calendar/helpers/DayIntervals.ts +0 -48
  96. package/src/components/calendar/helpers/EDate.ts +0 -18
  97. package/src/components/calendar/helpers/Errors.ts +0 -69
  98. package/src/components/calendar/helpers/EventChange.ts +0 -88
  99. package/src/components/calendar/helpers/EventConcurrency.ts +0 -69
  100. package/src/components/calendar/helpers/EventFlyoutPosition.ts +0 -96
  101. package/src/components/calendar/helpers/EventPosition.ts +0 -154
  102. package/src/components/calendar/helpers/EventsFilter.ts +0 -50
  103. package/src/components/calendar/helpers/Week.ts +0 -37
  104. package/src/components/calendar/language/index.ts +0 -41
  105. package/src/components/calendar/language/keys.ts +0 -99
  106. package/src/components/calendar/models/Event.ts +0 -112
  107. package/src/components/calendar/styles/_mixins.css +0 -21
  108. package/src/components/calendar/styles/_variables.css +0 -47
  109. package/src/components/calendar/typings/interfaces/day.interface.ts +0 -10
  110. package/src/components/calendar/typings/interfaces/event.interface.ts +0 -32
  111. package/src/components/calendar/typings/interfaces/full-day-events-week.type.ts +0 -8
  112. package/src/components/calendar/typings/interfaces/period.interface.ts +0 -5
  113. package/src/components/calendar/typings/interfaces/time-modes.ts +0 -11
  114. package/src/components/calendar/typings/types.ts +0 -27
@@ -0,0 +1,432 @@
1
+ <script setup lang="ts">
2
+ import type { CalendarEvent, WeekStart } from '../CalendarTypes'
3
+ import type { PopoverState } from '../utils'
4
+ import { Card, formatDate } from '@bagelink/vue'
5
+ import { ref, computed, onMounted, onUnmounted, useSlots } from 'vue'
6
+ import {
7
+ openPopover as openPopoverUtil,
8
+ closePopover as closePopoverUtil,
9
+ } from '../utils'
10
+
11
+ interface WeekViewEvent extends CalendarEvent {
12
+ top: number
13
+ height: number
14
+ left: number
15
+ width: number
16
+ overlappingEvents: number
17
+ position: number
18
+ }
19
+
20
+ const props = withDefaults(defineProps<{
21
+ events?: CalendarEvent[]
22
+ startDate?: Date
23
+ weekStart?: WeekStart
24
+ }>(), {
25
+ startDate: () => new Date(),
26
+ weekStart: 'Sunday',
27
+ events: () => []
28
+ })
29
+
30
+ const emit = defineEmits<{
31
+ (e: 'eventClick', event: CalendarEvent): void
32
+ (e: 'eventCreate', event: { start_time: Date, end_time: Date }): void
33
+ }>()
34
+
35
+ const slots = useSlots()
36
+
37
+ // Configuration constants
38
+ const slotHeight = 60
39
+ const slotDuration = 60
40
+ const timeRange = { start: 0, end: 24 }
41
+
42
+ // Drag state
43
+ const dragState = ref({
44
+ isDragging: false,
45
+ start: null as { x: number, y: number } | null,
46
+ end: null as { x: number, y: number } | null,
47
+ startTime: null as Date | null,
48
+ endTime: null as Date | null
49
+ })
50
+
51
+ // Popover state
52
+ const activeEvent = ref<CalendarEvent | null>(null)
53
+ const showPopover = ref(false)
54
+ const popoverPosition = ref({ top: 0, left: 0, width: 0, height: 0 })
55
+ const popoverRef = ref<HTMLElement | null>(null)
56
+
57
+ const popoverState: PopoverState = {
58
+ activeEvent,
59
+ showPopover,
60
+ popoverPosition,
61
+ popoverRef
62
+ }
63
+
64
+ // Time indicators
65
+ const currentTimeTop = ref(0)
66
+ const isToday = ref(false)
67
+ const currentTimeInterval = ref(null as any)
68
+
69
+ // Calculate week days based on start date and week start preference
70
+ const weekDays = computed(() => {
71
+ const days = []
72
+ const start = new Date(props.startDate)
73
+ const weekStartOffset = props.weekStart === 'Sunday' ? 0 : 1
74
+
75
+ // Adjust to start of week
76
+ const dayOfWeek = start.getDay()
77
+ start.setDate(start.getDate() - dayOfWeek + weekStartOffset)
78
+
79
+ // Create array of 7 day dates
80
+ for (let i = 0; i < 7; i++) {
81
+ const date = new Date(start)
82
+ date.setDate(start.getDate() + i)
83
+ days.push(date)
84
+ }
85
+ return days
86
+ })
87
+
88
+ // Generate hourly time slots
89
+ const timeSlots = computed(() => {
90
+ const slots = []
91
+ for (let hour = timeRange.start; hour < timeRange.end; hour++) {
92
+ for (let minute = 0; minute < 60; minute += slotDuration) {
93
+ slots.push({
94
+ hour,
95
+ minute,
96
+ time: `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`
97
+ })
98
+ }
99
+ }
100
+ return slots
101
+ })
102
+
103
+ // Process events for display with positioning calculations
104
+ const processedEvents = computed(() => {
105
+ const events: WeekViewEvent[] = []
106
+ const overlappingGroups: { [key: string]: WeekViewEvent[] } = {}
107
+
108
+ props.events.forEach((event) => {
109
+ const startDate = new Date(event.start_time)
110
+ const endDate = new Date(event.end_time)
111
+
112
+ // Find which day this event belongs to
113
+ const dayIndex = weekDays.value.findIndex(day => day.getDate() === startDate.getDate()
114
+ && day.getMonth() === startDate.getMonth()
115
+ && day.getFullYear() === startDate.getFullYear()
116
+ )
117
+
118
+ if (dayIndex === -1) return
119
+
120
+ // Calculate vertical positioning
121
+ const startMinutes = startDate.getHours() * 60 + startDate.getMinutes()
122
+ const endMinutes = endDate.getHours() * 60 + endDate.getMinutes()
123
+ const top = (startMinutes / slotDuration) * (slotHeight / 2)
124
+ const height = Math.max(((endMinutes - startMinutes) / slotDuration) * (slotHeight / 2), 30)
125
+
126
+ const weekEvent: WeekViewEvent = {
127
+ ...event,
128
+ top,
129
+ height,
130
+ left: 0,
131
+ width: 95,
132
+ overlappingEvents: 0,
133
+ position: 0
134
+ }
135
+
136
+ // Group by day and time range for overlapping calculation
137
+ const key = `${dayIndex}-${Math.floor(startMinutes / 30)}`
138
+ if (!overlappingGroups[key]) {
139
+ overlappingGroups[key] = []
140
+ }
141
+ overlappingGroups[key].push(weekEvent)
142
+ })
143
+
144
+ // Adjust overlapping events
145
+ Object.values(overlappingGroups).forEach((group) => {
146
+ if (group.length > 1) {
147
+ const groupWidth = 95 / group.length
148
+ group.forEach((event, index) => {
149
+ event.overlappingEvents = group.length
150
+ event.position = index
151
+ event.width = groupWidth
152
+ event.left = index * groupWidth
153
+ })
154
+ }
155
+ events.push(...group)
156
+ })
157
+
158
+ return events
159
+ })
160
+
161
+ // Mouse event handlers for drag-to-create functionality
162
+ function handleMouseDown(e: MouseEvent) {
163
+ const target = e.target as HTMLElement
164
+ if (!target.closest('.time-slot')) return
165
+
166
+ dragState.value.isDragging = true
167
+ dragState.value.start = { x: e.clientX, y: e.clientY }
168
+ dragState.value.startTime = getTimeFromPosition(e.clientX, e.clientY)
169
+
170
+ document.addEventListener('mousemove', handleMouseMove)
171
+ document.addEventListener('mouseup', handleMouseUp)
172
+ }
173
+
174
+ function handleMouseMove(e: MouseEvent) {
175
+ if (!dragState.value.isDragging) return
176
+
177
+ dragState.value.end = { x: e.clientX, y: e.clientY }
178
+ dragState.value.endTime = getTimeFromPosition(e.clientX, e.clientY)
179
+ }
180
+
181
+ function handleMouseUp() {
182
+ if (!dragState.value.isDragging || !dragState.value.startTime || !dragState.value.endTime) return
183
+
184
+ let start = new Date(dragState.value.startTime)
185
+ let end = new Date(dragState.value.endTime)
186
+
187
+ // Ensure end time is after start time
188
+ if (end < start) [start, end] = [end, start]
189
+
190
+ emit('eventCreate', { start_time: start, end_time: end })
191
+
192
+ // Reset drag state
193
+ dragState.value = {
194
+ isDragging: false,
195
+ start: null,
196
+ end: null,
197
+ startTime: null,
198
+ endTime: null
199
+ }
200
+
201
+ document.removeEventListener('mousemove', handleMouseMove)
202
+ document.removeEventListener('mouseup', handleMouseUp)
203
+ }
204
+
205
+ function getTimeFromPosition(x: number, y: number): Date {
206
+ const rect = document.querySelector('.time-slots')?.getBoundingClientRect()
207
+ if (!rect) return new Date()
208
+
209
+ const dayIndex = Math.floor((x - rect.left) / (rect.width / 7))
210
+ const minutes = Math.floor((y - rect.top) / (slotHeight / 2)) * slotDuration
211
+
212
+ const date = new Date(weekDays.value[dayIndex])
213
+ date.setHours(Math.floor(minutes / 60))
214
+ date.setMinutes(minutes % 60)
215
+
216
+ return date
217
+ }
218
+
219
+ // Update the current time indicator position
220
+ function updateCurrentTimeIndicator() {
221
+ const now = new Date()
222
+
223
+ // Check if today is in our current week view
224
+ isToday.value = weekDays.value.some(day => day.getDate() === now.getDate()
225
+ && day.getMonth() === now.getMonth()
226
+ && day.getFullYear() === now.getFullYear()
227
+ )
228
+
229
+ // Calculate position for the current time line
230
+ const minutes = now.getHours() * 60 + now.getMinutes()
231
+ currentTimeTop.value = (minutes / slotDuration) * (slotHeight / 2)
232
+ }
233
+
234
+ // Wrapper functions for popover utilities
235
+ function openPopover(event: CalendarEvent, e: MouseEvent) {
236
+ openPopoverUtil(
237
+ event,
238
+ e,
239
+ popoverState,
240
+ !!slots.eventContent,
241
+ (evt) => { emit('eventClick', evt) }
242
+ )
243
+ }
244
+
245
+ function closePopover() {
246
+ closePopoverUtil(popoverState)
247
+ }
248
+
249
+ // Lifecycle hooks
250
+ onMounted(() => {
251
+ document.addEventListener('mousedown', handleMouseDown)
252
+
253
+ // Initialize current time indicator and set up interval to update it
254
+ updateCurrentTimeIndicator()
255
+ currentTimeInterval.value = setInterval(updateCurrentTimeIndicator, 60000)
256
+ })
257
+
258
+ onUnmounted(() => {
259
+ document.removeEventListener('mousedown', handleMouseDown)
260
+ document.removeEventListener('mousemove', handleMouseMove)
261
+ document.removeEventListener('mouseup', handleMouseUp)
262
+
263
+ if (currentTimeInterval.value) {
264
+ clearInterval(currentTimeInterval.value)
265
+ }
266
+ })
267
+ </script>
268
+
269
+ <template>
270
+ <div class="w-100p overflow-hidden m_overflow h-100p grid">
271
+ <div class="weekGrid border-bottom me-1">
272
+ <div />
273
+ <div
274
+ v-for="day in weekDays" :key="day.toISOString()"
275
+ class="day-header p-05 txt-center"
276
+ >
277
+ {{ formatDate(day, 'DDD') }}
278
+ <span
279
+ class="txt-12 round p-025"
280
+ :class="{
281
+ 'color-gray': day.toDateString() !== new Date().toDateString(),
282
+ 'bg-primary color-white': day.toDateString() === new Date().toDateString(),
283
+ }"
284
+ >
285
+ {{ formatDate(day, 'DD') }}
286
+ </span>
287
+ </div>
288
+ </div>
289
+ <div class="overflow h-100p pe-05">
290
+ <div class="weekGrid border-end relative" @mousedown="handleMouseDown">
291
+ <div>
292
+ <div v-for="slot in timeSlots" :key="slot.time" class="txt-light txt-12 color-gray flex justify-content-center" :style="{ height: `${slotHeight}px` }">
293
+ {{ slot.time }}
294
+ </div>
295
+ </div>
296
+
297
+ <div v-if="isToday" class=" absolute end w-100p z-2 flex pointer-events-none ps-4-5" :style="{ top: `${currentTimeTop}px` }">
298
+ <div class="current-time-dot h-10px aspect-ratio-1 round bg-primary" />
299
+ <div class="current-time-line w-100p bg-primary" />
300
+ </div>
301
+
302
+ <div v-for="day in weekDays" :key="day.toISOString()" class="day-column top bottom border-start relative">
303
+ <template
304
+ v-for="event in processedEvents.filter(e =>
305
+ new Date(e.start_time).toDateString() === day.toDateString())"
306
+ :key="event.id"
307
+ >
308
+ <div
309
+ class="event absolute radius-05 overflow-hidden pointer transition z-1"
310
+ :style="{
311
+ top: `${event.top}px`,
312
+ height: `${event.height}px`,
313
+ left: `${event.left}%`,
314
+ width: `${event.width}%`,
315
+ backgroundColor: event.color || 'var(--bgl-primary)',
316
+ }"
317
+ @click.stop="slots.eventContent ? openPopover(event, $event) : emit('eventClick', event)"
318
+ >
319
+ <div class="overflow-hidden color-text-light p-025 txt12 h-100p">
320
+ <div class="white-space ellipsis-1">
321
+ {{ event.title }}
322
+ </div>
323
+ <div class="txt10 opacity-8">
324
+ {{ formatDate(event.start_time, 'HH:mm') }}
325
+ </div>
326
+ </div>
327
+ </div>
328
+ </template>
329
+ </div>
330
+
331
+ <!-- Drag selection preview -->
332
+ <div
333
+ v-if="dragState.isDragging && dragState.start && dragState.end"
334
+ class="drag-preview absolute bg-primary pointer-events-none"
335
+ :style="{
336
+ left: `${Math.min(dragState.start.x, dragState.end.x)}px`,
337
+ top: `${Math.min(dragState.start.y, dragState.end.y)}px`,
338
+ width: `${Math.abs(dragState.end.x - dragState.start.x)}px`,
339
+ height: `${Math.abs(dragState.end.y - dragState.start.y)}px`,
340
+ }"
341
+ />
342
+ </div>
343
+ </div>
344
+
345
+ <!-- Custom Popover -->
346
+ <Card
347
+ v-if="showPopover && activeEvent"
348
+ ref="popoverRef"
349
+ v-click-outside="closePopover"
350
+ thin
351
+ class="custom-popover fixed z-999 radius-05 bg-white w350"
352
+ :style="{
353
+ top: `${popoverPosition.top}px`,
354
+ left: `${popoverPosition.left}px`,
355
+ maxWidth: `${popoverPosition.width}px`,
356
+ }"
357
+ >
358
+ <slot name="eventContent" :event="activeEvent" />
359
+ </Card>
360
+ <div class="border-bottom me-1" />
361
+ </div>
362
+ </template>
363
+
364
+ <style scoped>
365
+ .weekGrid{
366
+ display: grid;
367
+ grid-template-columns: 5rem repeat(7, 1fr);
368
+ }
369
+
370
+ .days-column {
371
+ flex-grow: 1;
372
+ display: flex;
373
+
374
+ }
375
+
376
+ .time-slot {
377
+ height: 30px;
378
+ display: flex;
379
+ align-items: center;
380
+ justify-content: center;
381
+ font-size: 0.8rem;
382
+ color: var(--text-muted);
383
+ }
384
+
385
+ .time-slots {
386
+ flex-grow: 1;
387
+ display: flex;
388
+ overflow: auto;
389
+ position: relative;
390
+ }
391
+
392
+ .day-column {
393
+ flex: 1;
394
+ }
395
+
396
+ .event {
397
+ margin-right: 2px;
398
+ }
399
+
400
+ .event:hover {
401
+ z-index: 1;
402
+ }
403
+
404
+ .drag-preview {
405
+ border: 2px solid var(--bgl-primary);
406
+ }
407
+
408
+ .current-time-line {
409
+ height: 2px;
410
+ }
411
+
412
+ .custom-popover {
413
+ min-width: 250px;
414
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
415
+ animation: fadeIn 0.2s ease;
416
+ transform-origin: center left;
417
+ }
418
+
419
+ @keyframes fadeIn {
420
+ from {
421
+ opacity: 0;
422
+ transform: scale(0.95);
423
+ }
424
+ to {
425
+ opacity: 1;
426
+ transform: scale(1);
427
+ }
428
+ }
429
+ @media screen and (max-width: 910px) {
430
+
431
+ }
432
+ </style>