@bagelink/vue 1.2.15 → 1.2.20

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 +2241 -3891
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.mjs +2242 -3892
  29. package/dist/style.css +567 -633
  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 +373 -0
  56. package/src/components/calendar/views/MonthView.vue +313 -0
  57. package/src/components/calendar/views/WeekView.vue +431 -0
  58. package/src/components/form/BglMultiStepForm.vue +383 -69
  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 +35 -30
  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
@@ -3,7 +3,7 @@ import type { BglFormSchemaFnT } from '@bagelink/vue'
3
3
 
4
4
  import type { ComponentExposed, ComponentProps } from 'vue-component-type-helpers'
5
5
  import { BagelForm, Btn, useBglSchema } from '@bagelink/vue'
6
- import { watch } from 'vue'
6
+ import { ref, watch, computed } from 'vue'
7
7
 
8
8
  const props = withDefaults(
9
9
  defineProps<{
@@ -14,56 +14,176 @@ const props = withDefaults(
14
14
  )
15
15
  >
16
16
  schema: BglFormSchemaFnT<T>
17
+ showProgress?: boolean
18
+ rtl?: boolean
19
+ stepLabels?: string[]
20
+ allowStepNavigation?: boolean
21
+ validateOnSteps?: boolean
22
+ /** Animation direction - auto detects based on step change or can be forced */
23
+ direction?: 'auto' | 'left' | 'right'
17
24
  }>(),
18
25
  {
19
- bagelFormProps: () => ({})
26
+ bagelFormProps: () => ({}),
27
+ showProgress: false,
28
+ rtl: false,
29
+ allowStepNavigation: false,
30
+ validateOnSteps: true,
31
+ direction: 'auto'
20
32
  }
21
33
  )
22
34
 
23
- const emits = defineEmits(['submit'])
35
+ const emits = defineEmits(['submit', 'stepChange'])
24
36
 
25
37
  type BagelFormT = ComponentExposed<typeof BagelForm<T, P>>
26
38
 
27
- const formRef = $ref<BagelFormT>()
39
+ const formRef = ref<BagelFormT>()
28
40
 
29
- const formData = defineModel<T>(
30
- 'modelValue',
31
- { default: () => {}, required: true }
32
- )
41
+ const formData = defineModel<T>('modelValue', {
42
+ default: () => ({}),
43
+ required: true
44
+ })
45
+
46
+ const currentStep = ref(0)
47
+ const previousStep = ref(0)
48
+ const validatedSteps = ref<number[]>([])
33
49
 
34
50
  function reportValidity() {
35
- if (!formRef) return false
36
- return formRef.validateForm()
51
+ if (!formRef.value) return false
52
+ const isValid = formRef.value.validateForm()
53
+
54
+ if (isValid && !validatedSteps.value.includes(currentStep.value)) {
55
+ validatedSteps.value.push(currentStep.value)
56
+ }
57
+
58
+ return isValid
37
59
  }
38
60
 
39
- const computedSchema = $computed(
61
+ const computedSchema = computed(
40
62
  () => useBglSchema({ schema: props.schema })
41
63
  )
42
64
 
43
- const numberOfSteps = $ref(computedSchema.length)
65
+ // Filter out steps with vIf conditions that evaluate to false
66
+ const filteredSchema = computed(() => {
67
+ const schema = computedSchema.value
68
+ return schema.filter((step, index) => {
69
+ // Skip steps that have vIf or v-if returning false
70
+ if (step.vIf !== undefined || step['v-if'] !== undefined) {
71
+ const condition = step.vIf ?? step['v-if']
72
+ // If condition is a function, evaluate it with current form data
73
+ if (typeof condition === 'function') {
74
+ return condition(undefined, formData.value)
75
+ }
76
+ // If condition is a boolean, use it directly
77
+ if (typeof condition === 'boolean') {
78
+ return condition
79
+ }
80
+ // If condition is a string, evaluate it (treat non-empty as true)
81
+ if (typeof condition === 'string') {
82
+ return !!condition
83
+ }
84
+ }
85
+ // Include steps with no vIf condition or ones that evaluate to true
86
+ return true
87
+ })
88
+ })
89
+
90
+ const numberOfSteps = computed(() => filteredSchema.value.length)
91
+
92
+ // Map the filtered step index to the actual schema index
93
+ const schemaIndexMap = computed(() => {
94
+ const map: number[] = []
95
+ computedSchema.value.forEach((step, index) => {
96
+ const vIfCondition = step.vIf ?? step['v-if']
97
+ let shouldInclude = true
98
+
99
+ if (vIfCondition !== undefined) {
100
+ if (typeof vIfCondition === 'function') {
101
+ shouldInclude = vIfCondition(undefined, formData.value)
102
+ } else if (typeof vIfCondition === 'boolean') {
103
+ shouldInclude = vIfCondition
104
+ } else if (typeof vIfCondition === 'string') {
105
+ shouldInclude = !!vIfCondition
106
+ }
107
+ }
44
108
 
45
- let currentStep = $ref(0)
109
+ if (shouldInclude) {
110
+ map.push(index)
111
+ }
112
+ })
113
+ return map
114
+ })
46
115
 
47
- const currentStepSchema = $computed(() => [computedSchema[currentStep]])
116
+ // Get current step schema using the mapping
117
+ const currentStepSchema = computed(() => {
118
+ const actualIndex = schemaIndexMap.value[currentStep.value]
119
+ return [computedSchema.value[actualIndex]]
120
+ })
48
121
 
49
- let isStepping = $ref(false)
122
+ const isStepping = ref(false)
50
123
  let isSteppingTO: NodeJS.Timeout
124
+
125
+ // Tracks which way we're sliding (left or right)
126
+ const slideDirection = ref(props.rtl ? 'right' : 'left')
127
+
51
128
  watch(
52
- () => currentStep,
53
- () => {
129
+ () => currentStep.value,
130
+ (newStep, oldStep) => {
131
+ // Set direction based on step change
132
+ if (props.direction === 'auto') {
133
+ slideDirection.value = props.rtl
134
+ ? (newStep > oldStep ? 'right' : 'left')
135
+ : (newStep > oldStep ? 'left' : 'right')
136
+ } else {
137
+ slideDirection.value = props.direction
138
+ }
139
+
140
+ previousStep.value = oldStep
54
141
  clearTimeout(isSteppingTO)
55
- isStepping = true
56
- isSteppingTO = setTimeout(() => (isStepping = false), 600)
142
+ isStepping.value = true
143
+ isSteppingTO = setTimeout(() => (isStepping.value = false), 200)
144
+ emits('stepChange', {
145
+ newStep,
146
+ oldStep,
147
+ totalSteps: numberOfSteps.value,
148
+ direction: slideDirection.value
149
+ })
57
150
  }
58
151
  )
59
152
 
60
- const canDoNext = $computed(() => currentStep < numberOfSteps - 1)
153
+ const canDoNext = computed(() => currentStep.value < numberOfSteps.value - 1)
61
154
 
62
- function prevStep() { if (currentStep > 0) currentStep-- }
155
+ const isStepValidated = computed(() => (stepIndex: number) => validatedSteps.value.includes(stepIndex))
156
+
157
+ function prevStep() {
158
+ if (currentStep.value > 0) currentStep.value--
159
+ }
160
+
161
+ const formContainer = ref<HTMLElement>()
63
162
 
64
163
  function nextStep() {
65
- if (reportValidity() === false) return
66
- if (canDoNext) currentStep++
164
+ if (props.validateOnSteps && reportValidity() === false) return
165
+ if (canDoNext.value) currentStep.value++
166
+ }
167
+
168
+ function goToStep(stepIndex: number) {
169
+ // Can always go back, or to already validated steps
170
+ if (stepIndex < currentStep.value || validatedSteps.value.includes(stepIndex)) {
171
+ currentStep.value = stepIndex
172
+ return true
173
+ }
174
+
175
+ // For forward navigation to non-validated steps, validate current step first if needed
176
+ if (props.validateOnSteps && reportValidity() === false) {
177
+ return false
178
+ }
179
+
180
+ // Can only move one step forward at a time (prevent skipping)
181
+ if (stepIndex === currentStep.value + 1) {
182
+ currentStep.value = stepIndex
183
+ return true
184
+ }
185
+
186
+ return false
67
187
  }
68
188
 
69
189
  function handleSubmit() {
@@ -71,56 +191,250 @@ function handleSubmit() {
71
191
  emits('submit', formData.value)
72
192
  }
73
193
 
194
+ function reset() {
195
+ validatedSteps.value = []
196
+ currentStep.value = 0
197
+ // Clear form if BagelForm supports it
198
+ // if (formRef.value && typeof formRef.value.clearForm === 'function') {
199
+ // formRef.value.clearForm()
200
+ // }
201
+ }
202
+
203
+ // Re-evaluate filtered steps when formData changes
204
+ watch(() => formData.value, () => {
205
+ // If current step index is now invalid after filtering, reset to first valid step
206
+ if (currentStep.value >= numberOfSteps.value && numberOfSteps.value > 0) {
207
+ currentStep.value = 0
208
+ }
209
+ }, { deep: true })
210
+
74
211
  defineExpose({
75
212
  submit: handleSubmit,
76
- validateForm: formRef?.validateForm,
77
- // deleteItem: formRef?.deleteItem, // ! TODO: if (does not exist) remove!()
78
- isDirty: formRef?.isDirty,
79
- // clearForm: formRef?.clearForm, // ! TODO: if (does not exist) remove!()
213
+ validateForm: reportValidity,
214
+ isDirty: computed(() => formRef.value?.isDirty),
215
+ reset,
216
+ goToStep,
217
+ currentStep: computed(() => currentStep.value),
218
+ totalSteps: computed(() => numberOfSteps.value),
219
+ nextStep,
220
+ prevStep,
80
221
  })
81
222
  </script>
82
223
 
83
224
  <template>
84
- <transition
85
- :duration="600"
86
- name="fade"
87
- mode="out-in"
88
- >
89
- <template v-if="!isStepping">
90
- <div>
91
- <BagelForm
92
- ref="formRef"
93
- v-model=" formData"
94
- :schema="currentStepSchema"
95
- v-bind="bagelFormProps"
96
- >
97
- <template #success>
98
- <slot name="success" />
99
- </template>
100
- <template #error>
101
- <slot name="error" />
102
- </template>
103
- </BagelForm>
104
- </div>
105
- </template>
106
- </transition>
107
-
108
- <slot name="steppers" v-bind="{ prevStep, nextStep, submit: handleSubmit }">
109
- <Btn
110
- :disabled="currentStep === 0"
111
- value="Back"
112
- @click="prevStep"
113
- />
114
-
115
- <Btn
116
- v-if="canDoNext"
117
- value="Next"
118
- @click="nextStep"
119
- />
120
- <Btn
121
- v-else
122
- value="Submit"
123
- @click="handleSubmit"
124
- />
125
- </slot>
225
+ <div class="bgl-multi-step-form">
226
+ <!-- Progress indicator -->
227
+ <div v-if="showProgress" class="bgl-step-progress">
228
+ <slot
229
+ name="progress" v-bind="{
230
+ currentStep,
231
+ totalSteps: numberOfSteps,
232
+ goToStep,
233
+ stepLabels: props.stepLabels,
234
+ allowStepNavigation: props.allowStepNavigation,
235
+ isStepValidated,
236
+ }"
237
+ >
238
+ <div class="bgl-steps-indicator">
239
+ <div
240
+ v-for="(_, index) in numberOfSteps"
241
+ :key="index"
242
+ class="bgl-step-indicator" :class="[
243
+ { active: index === currentStep },
244
+ { completed: index < currentStep || isStepValidated(index) },
245
+ { clickable: props.allowStepNavigation },
246
+ ]"
247
+ @click="props.allowStepNavigation && goToStep(index)"
248
+ >
249
+ <span>{{ index + 1 }}</span>
250
+ <span v-if="props.stepLabels && props.stepLabels[index]" class="bgl-step-label">
251
+ {{ props.stepLabels[index] }}
252
+ </span>
253
+ </div>
254
+ </div>
255
+ </slot>
256
+ </div>
257
+
258
+ <div class="bgl-form-wrapper">
259
+ <transition
260
+ :name="slideDirection === 'right' ? 'slide-right' : 'slide-left'"
261
+ mode="out-in"
262
+ >
263
+ <div v-if="!isStepping" :key="currentStep" ref="formContainer" class="bgl-form-container">
264
+ <BagelForm
265
+ ref="formRef"
266
+ v-model="formData"
267
+ :schema="currentStepSchema"
268
+ v-bind="bagelFormProps"
269
+ >
270
+ <template v-if="$slots.success" #success>
271
+ <slot name="success" />
272
+ </template>
273
+ <template v-if="$slots.error" #error>
274
+ <slot name="error" />
275
+ </template>
276
+ </BagelForm>
277
+
278
+ <!-- Navigation buttons inside the form container to animate together -->
279
+ <div class="bgl-step-controls">
280
+ <slot
281
+ name="steppers" v-bind="{
282
+ prevStep,
283
+ nextStep,
284
+ submit: handleSubmit,
285
+ currentStep,
286
+ totalSteps: numberOfSteps,
287
+ canDoNext,
288
+ }"
289
+ >
290
+ <Btn :disabled="currentStep === 0" flat value="Back" class="px-3" @click="prevStep" />
291
+ <Btn v-if="canDoNext" value="Next" class="px-3" @click="nextStep" />
292
+ <Btn v-else value="Submit" @click="handleSubmit" />
293
+ </slot>
294
+ </div>
295
+ </div>
296
+ </transition>
297
+ </div>
298
+ </div>
126
299
  </template>
300
+
301
+ <style scoped>
302
+ .bgl-multi-step-form {
303
+ display: flex;
304
+ flex-direction: column;
305
+ gap: 1rem;
306
+ /* Default transition duration */
307
+ --transition-duration: 200ms;
308
+ --move-distance: 35%;
309
+ --ease-in: ease-in-out;
310
+ --ease-out: ease-in-out;
311
+ /* --ease-in: cubic-bezier(0.42, 0, 0.58, 1); */
312
+ /* --ease-out: cubic-bezier(0.5, 0, 0.75, 0); */
313
+ }
314
+
315
+ .bgl-steps-indicator {
316
+ display: flex;
317
+ justify-content: space-between;
318
+ align-items: center;
319
+ margin-bottom: 1rem;
320
+ }
321
+
322
+ .bgl-step-indicator {
323
+ display: flex;
324
+ flex-direction: column;
325
+ align-items: center;
326
+ position: relative;
327
+ }
328
+
329
+ .bgl-step-indicator::before {
330
+ content: '';
331
+ position: absolute;
332
+ top: 50%;
333
+ right: 50%;
334
+ height: 2px;
335
+ width: 100%;
336
+ background: #e0e0e0;
337
+ z-index: -1;
338
+ }
339
+
340
+ .bgl-step-indicator:first-child::before {
341
+ display: none;
342
+ }
343
+
344
+ .bgl-step-indicator > span:first-child {
345
+ width: 30px;
346
+ height: 30px;
347
+ border-radius: 50%;
348
+ background: #e0e0e0;
349
+ color: #555;
350
+ display: flex;
351
+ align-items: center;
352
+ justify-content: center;
353
+ margin-bottom: 0.5rem;
354
+ }
355
+
356
+ .bgl-step-indicator.active > span:first-child {
357
+ background: var(--primary-color, #4CAF50);
358
+ color: white;
359
+ }
360
+
361
+ .bgl-step-indicator.completed > span:first-child {
362
+ background: var(--success-color, #8BC34A);
363
+ color: white;
364
+ }
365
+
366
+ .bgl-step-indicator.clickable {
367
+ cursor: pointer;
368
+ }
369
+
370
+ .bgl-step-label {
371
+ font-size: 0.8rem;
372
+ max-width: 100px;
373
+ text-align: center;
374
+ }
375
+
376
+ .bgl-form-wrapper {
377
+ display: grid;
378
+ overflow: clip;
379
+ height: auto;
380
+ min-height: 300px;
381
+ transition: height var(--transition-duration) ease;
382
+ interpolate-size: allow-keywords;
383
+ }
384
+
385
+ .bgl-form-wrapper > div {
386
+ grid-area: 1 / 1;
387
+ }
388
+
389
+ .bgl-form-container {
390
+ width: 100%;
391
+ display: flex;
392
+ flex-direction: column;
393
+ }
394
+
395
+ .bgl-step-controls {
396
+ display: flex;
397
+ justify-content: center;
398
+ gap: 1rem;
399
+ margin-top: 1.5rem;
400
+ }
401
+
402
+ /* Slide Left Animation (going forward) */
403
+ .slide-left-enter-active {
404
+ transition: opacity, transform calc(var(--transition-duration) * 1.2) var(--ease-in);
405
+ }
406
+
407
+ .slide-left-leave-active {
408
+ transition: opacity, transform var(--transition-duration) var(--ease-out);
409
+ }
410
+
411
+ .slide-left-enter-from {
412
+ opacity: 0;
413
+ transform: translateX(var(--move-distance));
414
+ }
415
+
416
+ .slide-left-leave-to {
417
+ opacity: 0;
418
+ transform: translateX(-30%);
419
+ }
420
+
421
+ /* Slide Right Animation (going back) */
422
+ .slide-right-enter-active {
423
+ transition: all calc(var(--transition-duration) * 1.2) var(--ease-in);
424
+ }
425
+
426
+ .slide-right-leave-active {
427
+ transition: all var(--transition-duration) var(--ease-out);
428
+ transition-property: opacity, transform;
429
+ }
430
+
431
+ .slide-right-enter-from {
432
+ opacity: 0;
433
+ transform: translateX(-30%);
434
+ }
435
+
436
+ .slide-right-leave-to {
437
+ opacity: 0;
438
+ transform: translateX(var(--move-distance));
439
+ }
440
+ </style>
@@ -1,4 +1,5 @@
1
1
  export { default as BglForm } from './BagelForm.vue'
2
2
  export { default as BagelForm } from './BagelForm.vue'
3
+ export { default as BagelMultiStepForm } from './BglMultiStepForm.vue'
3
4
  export { default as FieldArray } from './FieldArray.vue'
4
5
  export * from './inputs'
@@ -151,6 +151,17 @@ pre code.hljs{
151
151
  background: #282c34;
152
152
  height: max-content;
153
153
  }
154
+ .code-editor-wrap:focus-within, .code-editor-wrap:focus-visible, .code-editor-wrap:focus {
155
+ box-shadow: inset 0 0 10px #00000021;
156
+ outline: solid 1px var(--border-color);
157
+ /* outline: -webkit-focus-ring-color auto 1px; */
158
+
159
+ }
160
+
161
+ .code-editor-wrap:focus-within:has(textarea:focus) + .label,
162
+ .label:has(+ .code-editor-wrap:focus-within) {
163
+ color: var(--bgl-primary) !important;
164
+ }
154
165
 
155
166
  .code-editor {
156
167
  color: transparent;
@@ -1,9 +1,9 @@
1
1
  <script setup lang="ts">
2
- import type { ModeType } from '../../calendar/typings/types'
2
+ import type { ModeType } from '../../../utils/calendar/typings'
3
3
  import { TextInput, Dropdown, formatDate } from '@bagelink/vue'
4
4
  import { onClickOutside } from '@vueuse/core'
5
5
  import { ref, onMounted } from 'vue'
6
- import { WEEK_START_DAY } from '../../calendar/helpers/Time'
6
+ import { WEEK_START_DAY } from '../../../utils/calendar/time'
7
7
  import DatePicker from './DatePicker.vue'
8
8
 
9
9
  const props = withDefaults(
@@ -30,7 +30,7 @@ const props = withDefaults(
30
30
  enableTime: false,
31
31
  editMode: true,
32
32
  small: false,
33
- mode: 'day',
33
+ mode: () => ({ mode: 'day' }),
34
34
  firstDayOfWeek: WEEK_START_DAY.SUNDAY,
35
35
  locale: ''
36
36
  },
@@ -1,8 +1,8 @@
1
1
  <script setup lang="ts">
2
- import type { DateViewMode, ModeType } from '../../calendar/typings/types'
2
+ import type { ModeType } from '../../../utils/calendar/typings'
3
3
  import { Btn, NumberInput } from '@bagelink/vue'
4
4
  import { computed, ref } from 'vue'
5
- import Time, { WEEK_START_DAY } from '../../calendar/helpers/Time'
5
+ import Time, { WEEK_START_DAY } from '../../../utils/calendar/time'
6
6
 
7
7
  const props = withDefaults(
8
8
  defineProps<{
@@ -15,7 +15,7 @@ const props = withDefaults(
15
15
  enableTime?: boolean
16
16
  }>(),
17
17
  {
18
- mode: 'day',
18
+ mode: () => ({ mode: 'day' }),
19
19
  firstDayOfWeek: WEEK_START_DAY.SUNDAY,
20
20
  locale: '',
21
21
  enableTime: false
@@ -26,7 +26,7 @@ const emit = defineEmits(['update:modelValue'])
26
26
 
27
27
  // State
28
28
  const currentMonth = ref(new Date())
29
- const currentView = ref<DateViewMode>('days')
29
+ const currentView = ref('days')
30
30
 
31
31
  // Time helper instance
32
32
  const time = new Time(props.firstDayOfWeek, props.locale)
@@ -85,7 +85,21 @@ function useCalendarView() {
85
85
  const currentMonthDays = computed(() => {
86
86
  const year = currentMonth.value.getFullYear()
87
87
  const month = currentMonth.value.getMonth()
88
- return time.getCalendarMonthSplitInWeeks(year, month).flat()
88
+
89
+ // Get the weeks for the current month
90
+ const weeksInMonth = time.getCalendarMonthSplitInWeeks(year, month)
91
+
92
+ // Always ensure we have 6 rows (42 days) in our calendar
93
+ // If we have less than 6 weeks, add extra week(s) from the next month
94
+ while (weeksInMonth.length < 6) {
95
+ const lastWeek = weeksInMonth[weeksInMonth.length - 1]
96
+ const lastDay = lastWeek[lastWeek.length - 1]
97
+ const nextDay = new Date(lastDay.getFullYear(), lastDay.getMonth(), lastDay.getDate() + 1)
98
+ const nextWeek = time.getCalendarWeekDateObjects(nextDay)
99
+ weeksInMonth.push(nextWeek)
100
+ }
101
+
102
+ return weeksInMonth.flat()
89
103
  })
90
104
 
91
105
  const currentMonthValue = computed(() => ({
@@ -263,21 +277,21 @@ function selectDate(date: Date | null) {
263
277
  <div class="calendar-section m_border-none pe-05 m_p-0">
264
278
  <div class="flex space-between pb-1">
265
279
  <template v-if="currentView === 'days'">
266
- <Btn flat icon="chevron_left" @click="previousMonth" />
280
+ <Btn flat thin icon="chevron_left" @click="previousMonth" />
267
281
  <div class="flex gap-05">
268
- <Btn flat class="month-btn" @click="currentView = 'months'">
282
+ <Btn flat thin class="month-btn" @click="currentView = 'months'">
269
283
  {{ currentMonthValue.formatted.month }}
270
284
  </Btn>
271
- <Btn flat class="year-btn" @click="currentView = 'years'">
285
+ <Btn flat thin class="year-btn" @click="currentView = 'years'">
272
286
  {{ currentMonthValue.formatted.year }}
273
287
  </Btn>
274
288
  </div>
275
- <Btn flat icon="chevron_right" @click="nextMonth" />
289
+ <Btn flat thin icon="chevron_right" @click="nextMonth" />
276
290
  </template>
277
291
  <template v-else>
278
- <Btn flat icon="chevron_left" @click="previousYear" />
292
+ <Btn flat thin icon="chevron_left" @click="previousYear" />
279
293
  <span class="month-year">{{ currentMonthValue.formatted.year }}</span>
280
- <Btn flat icon="chevron_right" @click="nextYear" />
294
+ <Btn flat thin icon="chevron_right" @click="nextYear" />
281
295
  </template>
282
296
  </div>
283
297
 
@@ -309,35 +323,26 @@ function selectDate(date: Date | null) {
309
323
  </div>
310
324
 
311
325
  <div v-else-if="currentView === 'months'" class="month-grid grid gap-05 p-05">
312
- <button
326
+ <Btn
313
327
  v-for="month in months"
314
328
  :key="month.value"
315
- class="month-item flex align-items-center justify-content-center pointer rounded p-05 txt14 border-none"
316
- :class="{
317
- selected: month.value === currentMonthValue.month,
318
- disabled: month.disabled,
319
- }"
329
+ thin
330
+ :flat="month.value !== currentMonthValue.month"
320
331
  :disabled="month.disabled"
332
+ :value="month.name"
321
333
  @click="selectMonth(month.value)"
322
- >
323
- {{ month.name }}
324
- </button>
334
+ />
325
335
  </div>
326
336
 
327
337
  <div v-else class="year-grid grid gap-05 p-0">
328
- <button
338
+ <Btn
329
339
  v-for="year in years"
330
- :key="year.value"
331
- class="year-item flex align-items-center justify-content-center pointer rounded p-05 txt14 border-none"
332
- :class="{
333
- selected: year.value === currentMonthValue.year,
334
- disabled: year.disabled,
335
- }"
340
+ :key="year.value" thin
341
+ :flat="year.value !== currentMonthValue.year"
336
342
  :disabled="year.disabled"
343
+ :value="year.value.toString()"
337
344
  @click="selectYear(year.value)"
338
- >
339
- {{ year.value }}
340
- </button>
345
+ />
341
346
  </div>
342
347
  </div>
343
348
 
@@ -237,6 +237,7 @@ onMounted(() => {
237
237
  :placement="placement"
238
238
  class="bagel-input selectinput"
239
239
  no-auto-focus
240
+ @click.stop
240
241
  >
241
242
  <template #trigger>
242
243
  <label>
@@ -298,6 +299,7 @@ onMounted(() => {
298
299
  <Card
299
300
  class="p-05"
300
301
  :style="{ width: fullWidth ? '100%' : 'auto' }"
302
+ @click.stop
301
303
  >
302
304
  <div ref="selectOptions" class="selectinput-options" :class="{ multiselect }">
303
305
  <div