@bagelink/vue 1.2.39 → 1.2.43

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 (54) hide show
  1. package/dist/components/calendar/CalendarPopover.vue.d.ts +179 -0
  2. package/dist/components/calendar/CalendarPopover.vue.d.ts.map +1 -0
  3. package/dist/components/calendar/CalendarTypes.d.ts +15 -0
  4. package/dist/components/calendar/CalendarTypes.d.ts.map +1 -1
  5. package/dist/components/calendar/Index.vue.d.ts +20 -12
  6. package/dist/components/calendar/Index.vue.d.ts.map +1 -1
  7. package/dist/components/calendar/views/AgendaView.vue.d.ts +8 -0
  8. package/dist/components/calendar/views/AgendaView.vue.d.ts.map +1 -1
  9. package/dist/components/calendar/views/CalendarPopover.vue.d.ts +175 -0
  10. package/dist/components/calendar/views/CalendarPopover.vue.d.ts.map +1 -0
  11. package/dist/components/calendar/views/DayView.vue.d.ts +10 -32
  12. package/dist/components/calendar/views/DayView.vue.d.ts.map +1 -1
  13. package/dist/components/calendar/views/MonthView.vue.d.ts +10 -170
  14. package/dist/components/calendar/views/MonthView.vue.d.ts.map +1 -1
  15. package/dist/components/calendar/views/WeekView.vue.d.ts +12 -168
  16. package/dist/components/calendar/views/WeekView.vue.d.ts.map +1 -1
  17. package/dist/components/form/FieldArray.vue.d.ts +4 -4
  18. package/dist/components/form/FieldArray.vue.d.ts.map +1 -1
  19. package/dist/components/form/inputs/DateInput.vue.d.ts.map +1 -1
  20. package/dist/components/form/inputs/DatePicker.vue.d.ts.map +1 -1
  21. package/dist/composables/useDevice.d.ts +3 -0
  22. package/dist/composables/useDevice.d.ts.map +1 -1
  23. package/dist/composables/useSchemaField.d.ts +1 -1
  24. package/dist/composables/useSchemaField.d.ts.map +1 -1
  25. package/dist/index.cjs +426 -280
  26. package/dist/index.mjs +426 -280
  27. package/dist/style.css +210 -167
  28. package/dist/types/BagelForm.d.ts +20 -17
  29. package/dist/types/BagelForm.d.ts.map +1 -1
  30. package/dist/utils/BagelFormUtils.d.ts +14 -20
  31. package/dist/utils/BagelFormUtils.d.ts.map +1 -1
  32. package/dist/utils/calendar/dateUtils.d.ts +7 -7
  33. package/dist/utils/index.d.ts +2 -4
  34. package/dist/utils/index.d.ts.map +1 -1
  35. package/package.json +1 -1
  36. package/src/components/calendar/CalendarPopover.vue +102 -0
  37. package/src/components/calendar/CalendarTypes.ts +14 -0
  38. package/src/components/calendar/Index.vue +75 -34
  39. package/src/components/calendar/views/AgendaView.vue +26 -2
  40. package/src/components/calendar/views/DayView.vue +83 -104
  41. package/src/components/calendar/views/MonthView.vue +21 -49
  42. package/src/components/calendar/views/WeekView.vue +227 -134
  43. package/src/components/form/FieldArray.vue +4 -3
  44. package/src/components/form/inputs/DateInput.vue +3 -1
  45. package/src/components/form/inputs/DatePicker.vue +7 -0
  46. package/src/composables/useDevice.ts +13 -2
  47. package/src/composables/useSchemaField.ts +4 -4
  48. package/src/styles/layout.css +14 -0
  49. package/src/styles/mobilLayout.css +12 -0
  50. package/src/types/BagelForm.ts +39 -59
  51. package/src/utils/BagelFormUtils.ts +16 -21
  52. package/src/utils/calendar/dateUtils.ts +22 -22
  53. package/src/utils/index.ts +3 -3
  54. package/src/components/calendar/utils.ts +0 -70
@@ -1,13 +1,8 @@
1
1
  <script setup lang="ts">
2
2
  import type { SetupContext } from 'vue'
3
3
  import type { CalendarEvent } from '../CalendarTypes'
4
- import type { PopoverState } from '../utils'
5
4
  import { formatDate } from '@bagelink/vue'
6
5
  import { ref, computed, onMounted, onUnmounted, useSlots } from 'vue'
7
- import {
8
- openPopover as openPopoverUtil,
9
- closePopover as closePopoverUtil,
10
- } from '../utils'
11
6
 
12
7
  const props = defineProps<{
13
8
  events: CalendarEvent[]
@@ -17,6 +12,7 @@ const props = defineProps<{
17
12
  const emit = defineEmits<{
18
13
  (e: 'eventClick', event: CalendarEvent): void
19
14
  (e: 'eventCreate', event: { start_time: Date, end_time: Date }): void
15
+ (e: 'openPopover', event: CalendarEvent, position?: { top: number, left: number }): void
20
16
  }>()
21
17
 
22
18
  const slots: SetupContext['slots'] = useSlots()
@@ -40,19 +36,6 @@ const currentTimeTop = ref(0)
40
36
  const isToday = ref(false)
41
37
  const currentTimeInterval = ref(null as any)
42
38
 
43
- // Popover state
44
- const activeEvent = ref<CalendarEvent | null>(null)
45
- const showPopover = ref(false)
46
- const popoverPosition = ref({ top: 0, left: 0, width: 0, height: 0 })
47
- const popoverRef = ref<HTMLElement | null>(null)
48
-
49
- const popoverState: PopoverState = {
50
- activeEvent,
51
- showPopover,
52
- popoverPosition,
53
- popoverRef
54
- }
55
-
56
39
  // Generate hourly time slots
57
40
  const timeSlots = computed(() => {
58
41
  const slots = []
@@ -100,7 +83,7 @@ function updateCurrentTimeIndicator() {
100
83
  // Check if today is the selected day
101
84
  isToday.value = now.toDateString() === props.startDate.toDateString()
102
85
 
103
- // Calculate the position for the current time line
86
+ // Calculate the position for the current time line - use same formula as events
104
87
  const minutes = now.getHours() * 60 + now.getMinutes()
105
88
  currentTimeTop.value = (minutes / slotDuration) * slotHeight
106
89
  }
@@ -153,27 +136,39 @@ function getTimeFromPosition(y: number): Date {
153
136
  const rect = document.querySelector('.time-slots')?.getBoundingClientRect()
154
137
  if (!rect) return new Date()
155
138
 
156
- const minutes = Math.floor((y - rect.top) / slotHeight) * slotDuration
139
+ // Calculate time using the same formula as for events
140
+ const relativeY = y - rect.top
141
+ const minutesPerSlot = slotDuration
142
+ const slotsFromTop = relativeY / slotHeight
143
+ const minutes = Math.floor(slotsFromTop * minutesPerSlot)
144
+
157
145
  const date = new Date(props.startDate)
158
146
  date.setHours(Math.floor(minutes / 60))
159
147
  date.setMinutes(minutes % 60)
148
+ date.setSeconds(0)
149
+ date.setMilliseconds(0)
160
150
 
161
151
  return date
162
152
  }
163
153
 
164
- // Popover handling functions
165
- function openPopover(event: CalendarEvent, e: MouseEvent) {
166
- openPopoverUtil(
167
- event,
168
- e,
169
- popoverState,
170
- !!slots.eventContent,
171
- (evt) => { emit('eventClick', evt) }
172
- )
173
- }
154
+ // Update event handling to emit the openPopover event
155
+ function handleEventSelection(event: CalendarEvent, domEvent?: MouseEvent) {
156
+ if (!slots.eventContent) {
157
+ emit('eventClick', event)
158
+ return
159
+ }
174
160
 
175
- function closePopover() {
176
- closePopoverUtil(popoverState)
161
+ // Calculate position from DOM event if available
162
+ if (domEvent) {
163
+ const rect = (domEvent.currentTarget as HTMLElement).getBoundingClientRect()
164
+ const position = {
165
+ top: rect.top + window.scrollY + (rect.height / 2),
166
+ left: rect.left + window.scrollX + rect.width + 10
167
+ }
168
+ emit('openPopover', event, position)
169
+ } else {
170
+ emit('openPopover', event)
171
+ }
177
172
  }
178
173
 
179
174
  // Lifecycle hooks
@@ -218,7 +213,7 @@ onUnmounted(() => {
218
213
  </div>
219
214
  <div class="events-column">
220
215
  <!-- Current time indicator -->
221
- <div v-if="isToday" class=" absolute end w-100p z-2 flex pointer-events-none" :style="{ top: `${currentTimeTop}px` }">
216
+ <div v-if="isToday" class="absolute end w-100p z-2 flex pointer-events-none" :style="{ top: `${currentTimeTop}px` }">
222
217
  <div class="current-time-dot h-10px aspect-ratio-1 round bg-primary" />
223
218
  <div class="current-time-line w-100p bg-primary" />
224
219
  </div>
@@ -231,14 +226,14 @@ onUnmounted(() => {
231
226
  height: `${event.height}px`,
232
227
  backgroundColor: event.color || 'var(--bgl-primary)',
233
228
  }"
234
- @click.stop="slots.eventContent ? openPopover(event, $event) : emit('eventClick', event)"
229
+ @click.stop="handleEventSelection(event, $event)"
235
230
  >
236
231
  <div class="event-content">
237
- <div class=" white-space ellipsis-1">
232
+ <div class="white-space ellipsis-1">
238
233
  {{ event.title }}
239
234
  </div>
240
235
  <div class="event-time opacity-8">
241
- {{ formatDate(new Date(event.start_time)) }}
236
+ {{ formatDate(new Date(event.start_time), { fmt: 'HH:mm' }) }} - {{ formatDate(new Date(event.end_time), { fmt: 'HH:mm' }) }}
242
237
  </div>
243
238
  </div>
244
239
  </div>
@@ -247,128 +242,112 @@ onUnmounted(() => {
247
242
  <!-- Drag selection preview -->
248
243
  <div
249
244
  v-if="dragState.isDragging && dragState.start && dragState.end"
250
- class="drag-preview absolute bg-primary pointer-events-none"
245
+ class="drag-preview absolute bg-primary-tint pointer-events-none z-1"
251
246
  :style="{
252
247
  top: `${Math.min(dragState.start.y, dragState.end.y)}px`,
253
248
  height: `${Math.abs(dragState.end.y - dragState.start.y)}px`,
249
+ left: '10px',
250
+ right: '10px',
254
251
  }"
255
- />
252
+ >
253
+ <div class="color-primary txt-12 p-025">
254
+ {{ dragState.startTime ? formatDate(dragState.startTime, { fmt: 'HH:mm' }) : '' }}
255
+ -
256
+ {{ dragState.endTime ? formatDate(dragState.endTime, { fmt: 'HH:mm' }) : '' }}
257
+ </div>
258
+ </div>
256
259
  </div>
257
260
  </div>
258
261
 
259
- <!-- Custom Popover -->
260
- <div
261
- v-if="showPopover && activeEvent"
262
- ref="popoverRef"
263
- v-click-outside="closePopover"
264
- class="custom-popover"
265
- :style="{
266
- top: `${popoverPosition.top}px`,
267
- left: `${popoverPosition.left}px`,
268
- maxWidth: `${popoverPosition.width}px`,
269
- }"
270
- >
271
- <slot name="eventContent" :event="activeEvent" />
272
- </div>
273
262
  <div class="border-bottom me-1" />
274
263
  </div>
275
264
  </template>
276
265
 
277
266
  <style scoped>
278
- .dayGrid{
267
+ .dayGrid {
279
268
  display: grid;
280
269
  grid-template-columns: 5rem 1fr;
281
270
  }
282
271
 
283
272
  .time-column {
284
- width: 80px;
285
- flex-shrink: 0;
273
+ width: 80px;
274
+ flex-shrink: 0;
286
275
  }
287
276
 
288
277
  .events-column {
289
- flex-grow: 1;
290
- position: relative;
291
- border-inline-start: 1px solid var(--border-color);
278
+ flex-grow: 1;
279
+ position: relative;
280
+ border-inline-start: 1px solid var(--border-color);
281
+ min-height: 100%; /* Ensure the column fills the full height */
292
282
  }
293
283
 
294
284
  .date-header {
295
- padding: 0.5rem;
296
- text-align: center;
285
+ padding: 0.5rem;
286
+ text-align: center;
297
287
  }
288
+
298
289
  .day-header .events-column {
299
- border-inline-start: 1px solid transparent;
290
+ border-inline-start: 1px solid transparent;
300
291
  }
301
292
 
302
293
  .time-slot {
303
- height: 30px;
304
- display: flex;
305
- align-items: center;
306
- justify-content: center;
294
+ height: 60px; /* Match this with the slotHeight variable */
295
+ display: flex;
296
+ align-items: flex-start; /* Align to top to match events */
297
+ justify-content: center;
298
+ padding: 0.5rem 0;
299
+ box-sizing: border-box;
307
300
  }
308
301
 
309
302
  .time-slots {
310
- flex-grow: 1;
311
- display: flex;
312
- overflow: auto;
313
- position: relative;
303
+ flex-grow: 1;
304
+ display: flex;
305
+ overflow: auto;
306
+ position: relative;
314
307
  }
315
308
 
316
309
  .event {
317
- left: 10px;
318
- right: 10px;
310
+ left: 10px;
311
+ right: 10px;
312
+ box-sizing: border-box;
319
313
  }
320
314
 
321
315
  .event:hover {
322
- z-index: 2;
323
- transform: scale(1.02);
316
+ z-index: 2;
317
+ transform: scale(1.02);
324
318
  }
325
319
 
326
320
  .event-content {
327
- padding: 0.5rem;
328
- color: white;
329
- font-size: 0.9rem;
330
- height: 100%;
331
- overflow: hidden;
321
+ padding: 0.5rem;
322
+ color: white;
323
+ font-size: 0.9rem;
324
+ height: 100%;
325
+ overflow: hidden;
332
326
  }
333
327
 
334
328
  .event-title {
335
- white-space: nowrap;
336
- overflow: hidden;
337
- text-overflow: ellipsis;
329
+ white-space: nowrap;
330
+ overflow: hidden;
331
+ text-overflow: ellipsis;
338
332
  }
339
333
 
340
334
  .event-time {
341
- font-size: 0.8rem;
335
+ font-size: 0.8rem;
342
336
  }
343
337
 
344
338
  .drag-preview {
339
+ border: 1px solid var(--bgl-primary);
345
340
  background-color: rgba(var(--bgl-primary-rgb), 0.1);
341
+ box-sizing: border-box;
346
342
  }
347
343
 
348
344
  .current-time-line {
349
- height: 2px;
350
- }
351
-
352
- .custom-popover {
353
- position: fixed;
354
- z-index: 1000;
355
- min-width: 250px;
356
- max-width: 350px;
357
- background-color: white;
358
- border-radius: 4px;
359
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
360
- animation: fadeIn 0.2s ease;
361
- transform-origin: center left;
345
+ height: 2px;
346
+ background-color: var(--bgl-primary);
362
347
  }
363
348
 
364
- @keyframes fadeIn {
365
- from {
366
- opacity: 0;
367
- transform: scale(0.95);
368
- }
369
- to {
370
- opacity: 1;
371
- transform: scale(1);
372
- }
349
+ .current-time-dot {
350
+ background-color: var(--bgl-primary);
351
+ margin-right: -5px; /* Adjust dot position */
373
352
  }
374
353
  </style>
@@ -1,13 +1,8 @@
1
1
  <script setup lang="ts">
2
2
  import type { SetupContext } from 'vue'
3
3
  import type { CalendarEvent } from '../CalendarTypes'
4
- import type { PopoverState } from '../utils'
5
- import { Card, fmtDate } from '@bagelink/vue'
6
- import { ref, computed, useSlots } from 'vue'
7
- import {
8
- openPopover as openPopoverUtil,
9
- closePopover as closePopoverUtil,
10
- } from '../utils'
4
+ import { fmtDate } from '@bagelink/vue'
5
+ import { computed, useSlots } from 'vue'
11
6
 
12
7
  interface MonthViewEvent {
13
8
  date: Date
@@ -23,6 +18,7 @@ const props = defineProps<{
23
18
 
24
19
  const emit = defineEmits<{
25
20
  (e: 'eventClick', event: CalendarEvent): void
21
+ (e: 'openPopover', event: CalendarEvent, position?: { top: number, left: number }): void
26
22
  }>()
27
23
 
28
24
  const slots: SetupContext['slots'] = useSlots()
@@ -30,19 +26,6 @@ const slots: SetupContext['slots'] = useSlots()
30
26
  // Responsive state
31
27
  const isMobile = computed(() => window.innerWidth < 768)
32
28
 
33
- // Popover state
34
- const activeEvent = ref<CalendarEvent | null>(null)
35
- const showPopover = ref(false)
36
- const popoverPosition = ref({ top: 0, left: 0, width: 0, height: 0 })
37
- const popoverRef = ref<HTMLElement | null>(null)
38
-
39
- const popoverState: PopoverState = {
40
- activeEvent,
41
- showPopover,
42
- popoverPosition,
43
- popoverRef
44
- }
45
-
46
29
  // Calendar data
47
30
  const weekDays = computed(() => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'])
48
31
 
@@ -102,19 +85,24 @@ const currentMonth = computed(() => {
102
85
  return days
103
86
  })
104
87
 
105
- // Popover handling functions
106
- function openPopover(event: CalendarEvent, e: MouseEvent) {
107
- openPopoverUtil(
108
- event,
109
- e,
110
- popoverState,
111
- !!slots.eventContent,
112
- (evt) => { emit('eventClick', evt) }
113
- )
114
- }
88
+ // Update event handling to emit the openPopover event
89
+ function handleEventSelection(event: CalendarEvent, domEvent?: MouseEvent) {
90
+ if (!slots.eventContent) {
91
+ emit('eventClick', event)
92
+ return
93
+ }
115
94
 
116
- function closePopover() {
117
- closePopoverUtil(popoverState)
95
+ // Calculate position from DOM event if available
96
+ if (domEvent) {
97
+ const rect = (domEvent.currentTarget as HTMLElement).getBoundingClientRect()
98
+ const position = {
99
+ top: rect.top + window.scrollY + (rect.height / 2),
100
+ left: rect.left + window.scrollX + rect.width + 10
101
+ }
102
+ emit('openPopover', event, position)
103
+ } else {
104
+ emit('openPopover', event)
105
+ }
118
106
  }
119
107
  </script>
120
108
 
@@ -149,7 +137,7 @@ function closePopover() {
149
137
  :key="event.id"
150
138
  class="event-item"
151
139
  :style="{ backgroundColor: event.color || 'var(--bgl-primary)' }"
152
- @click.stop="slots.eventContent ? openPopover(event, $event) : emit('eventClick', event)"
140
+ @click.stop="handleEventSelection(event, $event)"
153
141
  >
154
142
  <div class="event-title">
155
143
  {{ event.title }}
@@ -162,22 +150,6 @@ function closePopover() {
162
150
  </div>
163
151
  </div>
164
152
  </div>
165
-
166
- <!-- Custom Popover -->
167
- <Card
168
- v-if="showPopover && activeEvent"
169
- ref="popoverRef"
170
- v-click-outside="closePopover"
171
- thin
172
- class="custom-popover"
173
- :style="{
174
- top: `${popoverPosition.top}px`,
175
- left: `${popoverPosition.left}px`,
176
- maxWidth: `${popoverPosition.width}px`,
177
- }"
178
- >
179
- <slot name="eventContent" :event="activeEvent" />
180
- </Card>
181
153
  </div>
182
154
  </template>
183
155