@bagelink/vue 1.5.17 → 1.5.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 (133) hide show
  1. package/bin/experimentalGenTypedRoutes.ts +15 -15
  2. package/bin/generateFormSchema.ts +12 -12
  3. package/bin/utils.ts +4 -4
  4. package/dist/components/Dropdown.vue.d.ts.map +1 -1
  5. package/dist/components/calendar/CalendarPopover.vue.d.ts.map +1 -1
  6. package/dist/components/form/BagelForm.vue.d.ts.map +1 -1
  7. package/dist/components/form/FieldArray.vue.d.ts +5 -4
  8. package/dist/components/form/FieldArray.vue.d.ts.map +1 -1
  9. package/dist/components/form/inputs/CheckInput.vue.d.ts.map +1 -1
  10. package/dist/components/form/inputs/RichText/index.vue.d.ts +1 -0
  11. package/dist/components/form/inputs/RichText/index.vue.d.ts.map +1 -1
  12. package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
  13. package/dist/components/form/inputs/ToggleInput.vue.d.ts.map +1 -1
  14. package/dist/components/form/inputs/Upload/UploadInput.vue.d.ts.map +1 -1
  15. package/dist/composables/useFormField.d.ts.map +1 -1
  16. package/dist/composables/useSchemaField.d.ts.map +1 -1
  17. package/dist/index.cjs +17 -14
  18. package/dist/index.mjs +511 -422
  19. package/dist/style.css +1 -1
  20. package/package.json +1 -1
  21. package/src/components/AccordionItem.vue +2 -2
  22. package/src/components/AddToCalendar.vue +1 -1
  23. package/src/components/BglVideo.vue +8 -8
  24. package/src/components/Btn.vue +9 -9
  25. package/src/components/Card.vue +4 -4
  26. package/src/components/Carousel.vue +44 -44
  27. package/src/components/DataPreview.vue +1 -1
  28. package/src/components/DragOver.vue +6 -6
  29. package/src/components/Dropdown.vue +14 -14
  30. package/src/components/Flag.vue +3 -3
  31. package/src/components/Icon/Icon.vue +13 -13
  32. package/src/components/Image.vue +4 -4
  33. package/src/components/ImportData.vue +79 -79
  34. package/src/components/ListItem.vue +7 -7
  35. package/src/components/MapEmbed/Index.vue +6 -6
  36. package/src/components/Modal.vue +10 -10
  37. package/src/components/ModalForm.vue +4 -4
  38. package/src/components/NavBar.vue +2 -2
  39. package/src/components/Pagination.vue +9 -9
  40. package/src/components/Pill.vue +1 -1
  41. package/src/components/Rating.vue +2 -2
  42. package/src/components/Slider.vue +77 -77
  43. package/src/components/Spreadsheet/Index.vue +34 -34
  44. package/src/components/Spreadsheet/SpreadsheetTable.vue +3 -3
  45. package/src/components/Zoomer.vue +28 -28
  46. package/src/components/analytics/BarChart.vue +6 -6
  47. package/src/components/analytics/KpiCard.vue +2 -2
  48. package/src/components/analytics/LineChart.vue +14 -14
  49. package/src/components/analytics/PieChart.vue +11 -11
  50. package/src/components/calendar/CalendarPopover.vue +1 -1
  51. package/src/components/calendar/Index.vue +1 -1
  52. package/src/components/calendar/views/AgendaView.vue +2 -2
  53. package/src/components/calendar/views/DayView.vue +6 -6
  54. package/src/components/calendar/views/MonthView.vue +2 -2
  55. package/src/components/calendar/views/WeekView.vue +18 -18
  56. package/src/components/dataTable/DataTable.vue +3 -3
  57. package/src/components/dataTable/useSorting.ts +1 -1
  58. package/src/components/dataTable/useTableData.ts +15 -15
  59. package/src/components/dataTable/useTableSelection.ts +8 -8
  60. package/src/components/dataTable/useTableVirtualization.ts +1 -1
  61. package/src/components/draggable/useDraggable.ts +42 -42
  62. package/src/components/form/BagelForm.vue +66 -23
  63. package/src/components/form/BglMultiStepForm.vue +18 -18
  64. package/src/components/form/FieldArray.vue +177 -67
  65. package/src/components/form/inputs/CheckInput.vue +2 -1
  66. package/src/components/form/inputs/CodeEditor/Index.vue +1 -1
  67. package/src/components/form/inputs/CodeEditor/format.ts +7 -7
  68. package/src/components/form/inputs/CodeEditor/useHighlight.ts +6 -6
  69. package/src/components/form/inputs/DateInput.vue +6 -6
  70. package/src/components/form/inputs/DatePicker.vue +19 -19
  71. package/src/components/form/inputs/EmailInput.vue +14 -14
  72. package/src/components/form/inputs/NumberInput.vue +6 -6
  73. package/src/components/form/inputs/OTP.vue +3 -3
  74. package/src/components/form/inputs/RadioGroup.vue +1 -1
  75. package/src/components/form/inputs/RadioPillsInput.vue +8 -8
  76. package/src/components/form/inputs/RichText/components/EditorToolbar.vue +10 -10
  77. package/src/components/form/inputs/RichText/components/TableGridSelector.vue +1 -1
  78. package/src/components/form/inputs/RichText/composables/useCommands.ts +1 -1
  79. package/src/components/form/inputs/RichText/composables/useEditor.ts +12 -12
  80. package/src/components/form/inputs/RichText/composables/useEditorKeyboard.ts +1 -1
  81. package/src/components/form/inputs/RichText/index.vue +143 -134
  82. package/src/components/form/inputs/RichText/utils/commands.ts +69 -69
  83. package/src/components/form/inputs/RichText/utils/debug.ts +1 -1
  84. package/src/components/form/inputs/RichText/utils/formatting.ts +39 -39
  85. package/src/components/form/inputs/RichText/utils/media.ts +6 -6
  86. package/src/components/form/inputs/RichText/utils/selection.ts +28 -28
  87. package/src/components/form/inputs/RichText/utils/table.ts +19 -19
  88. package/src/components/form/inputs/SelectBtn.vue +1 -1
  89. package/src/components/form/inputs/SelectInput.vue +50 -26
  90. package/src/components/form/inputs/SignaturePad.vue +15 -15
  91. package/src/components/form/inputs/TableField.vue +1 -1
  92. package/src/components/form/inputs/TelInput.vue +6 -6
  93. package/src/components/form/inputs/TextInput.vue +5 -5
  94. package/src/components/form/inputs/ToggleInput.vue +2 -1
  95. package/src/components/form/inputs/Upload/UploadInput.vue +155 -102
  96. package/src/components/form/inputs/Upload/upload.ts +1 -1
  97. package/src/components/form/inputs/Upload/useFileUpload.ts +6 -6
  98. package/src/components/form/useBagelFormState.ts +5 -5
  99. package/src/components/layout/AppContent.vue +1 -1
  100. package/src/components/layout/AppLayout.vue +1 -1
  101. package/src/components/layout/Layout.vue +4 -4
  102. package/src/components/layout/TabbedLayout.vue +1 -1
  103. package/src/components/layout/Tabs.vue +2 -2
  104. package/src/components/layout/TabsNav.vue +7 -7
  105. package/src/components/lightbox/Lightbox.vue +8 -8
  106. package/src/components/lightbox/index.ts +8 -8
  107. package/src/composables/index.ts +2 -2
  108. package/src/composables/useAddToCalendar.ts +13 -13
  109. package/src/composables/useDevice.ts +2 -2
  110. package/src/composables/useExcel.ts +6 -6
  111. package/src/composables/useFormField.ts +5 -9
  112. package/src/composables/usePolling.ts +8 -8
  113. package/src/composables/useSchemaField.ts +53 -38
  114. package/src/composables/useTheme.ts +9 -9
  115. package/src/composables/useValidateFieldValue.ts +2 -2
  116. package/src/directives/pattern.ts +25 -25
  117. package/src/directives/ripple.ts +4 -4
  118. package/src/directives/vResize.ts +6 -6
  119. package/src/plugins/bagel.ts +4 -4
  120. package/src/plugins/useModal.ts +3 -3
  121. package/src/styles/layout.css +7 -1
  122. package/src/utils/BagelFormUtils.ts +7 -7
  123. package/src/utils/calendar/Helpers.ts +8 -8
  124. package/src/utils/calendar/dateUtils.ts +22 -22
  125. package/src/utils/calendar/time.ts +25 -25
  126. package/src/utils/calendar/week.ts +25 -25
  127. package/src/utils/elementUtils.ts +27 -27
  128. package/src/utils/index.ts +22 -22
  129. package/src/utils/sizeParsing.ts +2 -2
  130. package/src/utils/strings.ts +5 -5
  131. package/src/utils/tapDetector.ts +11 -11
  132. package/src/utils/useSearch.ts +29 -29
  133. package/vite.config.ts +1 -1
@@ -36,7 +36,7 @@ export function useDraggable(options: DraggableOptions = {}) {
36
36
  const dropTarget = ref<DraggableElement | null>(null)
37
37
 
38
38
  // Only run in browser environment
39
- const isBrowser = typeof window !== 'undefined'
39
+ const isBrowser = 'undefined' !== typeof window
40
40
 
41
41
  // Move style injection into setup
42
42
  if (isBrowser) {
@@ -79,7 +79,7 @@ export function useDraggable(options: DraggableOptions = {}) {
79
79
  const POSITION_CACHE = new Map<number, { top: number, bottom: number }>()
80
80
 
81
81
  function createGhost(el: DraggableElement) {
82
- if (!isBrowser) return null
82
+ if (!isBrowser) {return null}
83
83
  const ghost = el.cloneNode(true) as HTMLElement
84
84
  const rect = el.getBoundingClientRect()
85
85
  ghost.style.position = 'fixed'
@@ -99,7 +99,7 @@ export function useDraggable(options: DraggableOptions = {}) {
99
99
  }
100
100
 
101
101
  function createDropIndicator(el: DraggableElement) {
102
- if (!isBrowser) return null
102
+ if (!isBrowser) {return null}
103
103
  const line = document.createElement('div')
104
104
  line.classList.add(defaultOptions.dropIndicatorClass!)
105
105
  line.style.position = 'fixed'
@@ -127,7 +127,7 @@ export function useDraggable(options: DraggableOptions = {}) {
127
127
  }
128
128
 
129
129
  function updateDropIndicator(target: DraggableElement, isAfter: boolean) {
130
- if (!dropIndicator.value) return
130
+ if (!dropIndicator.value) {return}
131
131
 
132
132
  const rect = target.getBoundingClientRect()
133
133
  dropIndicator.value.style.display = 'block'
@@ -144,7 +144,7 @@ export function useDraggable(options: DraggableOptions = {}) {
144
144
 
145
145
  function findDraggableParent(element: Element | null): DraggableElement | null {
146
146
  let current = element
147
- while (current && (!('__drag_group' in current) || (current as any).dataset.draggable === 'false')) {
147
+ while (current && (!('__drag_group' in current) || 'false' === (current as any).dataset.draggable)) {
148
148
  current = current.parentElement
149
149
  }
150
150
  return current as DraggableElement | null
@@ -185,11 +185,11 @@ export function useDraggable(options: DraggableOptions = {}) {
185
185
  const now = Date.now()
186
186
  if (now - lastUpdateTime < UPDATE_THRESHOLD) {
187
187
  // Return last calculated index if we're within threshold
188
- return lastDropIndex !== -1 ? lastDropIndex : dragIndex
188
+ return -1 !== lastDropIndex ? lastDropIndex : dragIndex
189
189
  }
190
190
 
191
191
  // Use cached positions if available, otherwise calculate new ones
192
- if (POSITION_CACHE.size === 0) {
192
+ if (0 === POSITION_CACHE.size) {
193
193
  cacheElementPositions(draggedList)
194
194
  }
195
195
 
@@ -197,7 +197,7 @@ export function useDraggable(options: DraggableOptions = {}) {
197
197
  const targetIndex = draggedList.indexOf(newDropTarget)
198
198
  const targetPos = POSITION_CACHE.get(targetIndex)
199
199
 
200
- if (!targetPos) return dragIndex
200
+ if (!targetPos) {return dragIndex}
201
201
 
202
202
  const elementHeight = targetPos.bottom - targetPos.top
203
203
  const relativeY = mouseY - targetPos.top
@@ -211,19 +211,19 @@ export function useDraggable(options: DraggableOptions = {}) {
211
211
  // Different behavior based on context
212
212
  if (targetIndex === dragIndex) {
213
213
  // On original element - require significant movement
214
- if (relativeY > lowerSticky) dropIndex += 1
214
+ if (relativeY > lowerSticky) {dropIndex += 1}
215
215
  } else if (targetIndex === lastDropIndex) {
216
216
  // On previously targeted element - use sticky zones
217
217
  if (targetIndex > dragIndex) {
218
- if (relativeY < upperSticky) dropIndex = targetIndex
219
- else dropIndex = targetIndex + 1
218
+ if (relativeY < upperSticky) {dropIndex = targetIndex}
219
+ else {dropIndex = targetIndex + 1}
220
220
  } else {
221
- if (relativeY > lowerSticky) dropIndex = targetIndex + 1
222
- else dropIndex = targetIndex
221
+ if (relativeY > lowerSticky) {dropIndex = targetIndex + 1}
222
+ else {dropIndex = targetIndex}
223
223
  }
224
224
  } else {
225
225
  // On new element - use 60/40 split
226
- if (relativeY > elementHeight * 0.6) dropIndex += 1
226
+ if (relativeY > elementHeight * 0.6) {dropIndex += 1}
227
227
  }
228
228
 
229
229
  // Update state
@@ -234,7 +234,7 @@ export function useDraggable(options: DraggableOptions = {}) {
234
234
  }
235
235
 
236
236
  function cleanup() {
237
- if (!isBrowser) return
237
+ if (!isBrowser) {return}
238
238
 
239
239
  document.removeEventListener('mousemove', onDragMove)
240
240
  document.removeEventListener('mouseup', onDragEnd)
@@ -294,23 +294,23 @@ export function useDraggable(options: DraggableOptions = {}) {
294
294
  }
295
295
 
296
296
  function onKeyDown(e: KeyboardEvent) {
297
- if (e.key === 'Escape' && isDragging.value) {
297
+ if ('Escape' === e.key && isDragging.value) {
298
298
  cleanup()
299
299
  }
300
300
  }
301
301
 
302
302
  function onDragStart(e: MouseEvent) {
303
- if (!isBrowser || defaultOptions.disabled) return
304
- if (e.button !== 0) return // Only left mouse button
305
- if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey) return
303
+ if (!isBrowser || defaultOptions.disabled) {return}
304
+ if (0 !== e.button) {return} // Only left mouse button
305
+ if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey) {return}
306
306
 
307
307
  const dragEl = findDraggableParent(e.target as Element)
308
- if (!dragEl || dragEl.dataset.draggable === 'false') return
308
+ if (!dragEl || 'false' === dragEl.dataset.draggable) {return}
309
309
 
310
310
  // If handle is specified, check if clicked element matches
311
311
  if (defaultOptions.handle) {
312
312
  const handleEl = (e.target as Element).closest(defaultOptions.handle)
313
- if (!handleEl || !dragEl.contains(handleEl)) return
313
+ if (!handleEl || !dragEl.contains(handleEl)) {return}
314
314
  }
315
315
 
316
316
  e.preventDefault()
@@ -332,13 +332,13 @@ export function useDraggable(options: DraggableOptions = {}) {
332
332
  }
333
333
 
334
334
  // Only create drop indicator in line mode
335
- if (defaultOptions.mode === 'line') {
335
+ if ('line' === defaultOptions.mode) {
336
336
  dropIndicator.value = createDropIndicator(dragEl)
337
337
  }
338
338
 
339
339
  // Apply mode-specific styles and get shift amount
340
340
  dragEl.classList.add(defaultOptions.dragClass!)
341
- shiftAmount = defaultOptions.mode === 'ghost'
341
+ shiftAmount = 'ghost' === defaultOptions.mode
342
342
  ? handleGhostMode(dragEl)
343
343
  : handleLineMode(dragEl)
344
344
 
@@ -370,8 +370,8 @@ export function useDraggable(options: DraggableOptions = {}) {
370
370
  }
371
371
 
372
372
  function autoScroll(e: MouseEvent) {
373
- if (!dragElement.value) return
374
- if (scrollRAF) cancelAnimationFrame(scrollRAF)
373
+ if (!dragElement.value) {return}
374
+ if (scrollRAF) {cancelAnimationFrame(scrollRAF)}
375
375
 
376
376
  scrollRAF = requestAnimationFrame(() => {
377
377
  const scrollParent = findScrollParent(dragElement.value!) as HTMLElement
@@ -394,7 +394,7 @@ export function useDraggable(options: DraggableOptions = {}) {
394
394
  }
395
395
 
396
396
  function onDragMove(e: MouseEvent) {
397
- if (!isDragging.value || !dragElement.value) return
397
+ if (!isDragging.value || !dragElement.value) {return}
398
398
 
399
399
  // Move ghost element with cursor
400
400
  if (ghostElement.value) {
@@ -405,7 +405,7 @@ export function useDraggable(options: DraggableOptions = {}) {
405
405
 
406
406
  // Get the draggable list and current positions
407
407
  const list = dragElement.value.__drag_list!
408
- const draggedList = list.filter(el => el.dataset.draggable !== 'false')
408
+ const draggedList = list.filter(el => 'false' !== el.dataset.draggable)
409
409
  const dragIndex = draggedList.indexOf(dragElement.value)
410
410
 
411
411
  // Find the element at cursor position
@@ -428,7 +428,7 @@ export function useDraggable(options: DraggableOptions = {}) {
428
428
  dropTarget.value.__intended_index = dropIndex
429
429
 
430
430
  // Update line indicator
431
- if (dropIndicator.value && defaultOptions.mode === 'line') {
431
+ if (dropIndicator.value && 'line' === defaultOptions.mode) {
432
432
  const isAfter = dropIndex > dragIndex
433
433
  updateDropIndicator(newDropTarget, isAfter)
434
434
  }
@@ -441,7 +441,7 @@ export function useDraggable(options: DraggableOptions = {}) {
441
441
  el.style.transform = 'translate3d(0, 0, 0)'
442
442
 
443
443
  if (el === dragElement.value) {
444
- if (defaultOptions.mode === 'ghost') {
444
+ if ('ghost' === defaultOptions.mode) {
445
445
  const offset = (dropIndex - dragIndex) * shift
446
446
  el.style.transform = `translate3d(0, ${offset}px, 0)`
447
447
  }
@@ -475,11 +475,11 @@ export function useDraggable(options: DraggableOptions = {}) {
475
475
  return
476
476
  }
477
477
 
478
- const draggedList = list.filter(el => el.dataset.draggable !== 'false')
478
+ const draggedList = list.filter(el => 'false' !== el.dataset.draggable)
479
479
  const actualDragIndex = draggedList.indexOf(dragElement.value)
480
480
  const actualDropIndex = dropTarget.value.__intended_index!
481
481
 
482
- if (actualDragIndex !== -1 && actualDropIndex !== -1) {
482
+ if (-1 !== actualDragIndex && -1 !== actualDropIndex) {
483
483
  list.forEach((el) => {
484
484
  el.style.transition = 'none'
485
485
  el.style.transform = ''
@@ -499,18 +499,18 @@ export function useDraggable(options: DraggableOptions = {}) {
499
499
  }
500
500
 
501
501
  function onTouchStart(e: TouchEvent) {
502
- if (!isBrowser || defaultOptions.disabled || !e.target) return
502
+ if (!isBrowser || defaultOptions.disabled || !e.target) {return}
503
503
 
504
504
  const touch = e.touches[0]
505
- if (!touch) return
505
+ if (!touch) {return}
506
506
 
507
507
  const target = e.target as Element
508
508
  const draggableParent = findDraggableParent(target)
509
509
 
510
- if (!draggableParent) return
510
+ if (!draggableParent) {return}
511
511
 
512
512
  const { handle } = defaultOptions
513
- if (handle && !target.closest(handle)) return
513
+ if (handle && !target.closest(handle)) {return}
514
514
 
515
515
  e.preventDefault() // Prevent scrolling
516
516
  isDragging.value = true
@@ -530,13 +530,13 @@ export function useDraggable(options: DraggableOptions = {}) {
530
530
  }
531
531
 
532
532
  // Only create drop indicator in line mode
533
- if (defaultOptions.mode === 'line') {
533
+ if ('line' === defaultOptions.mode) {
534
534
  dropIndicator.value = createDropIndicator(draggableParent)
535
535
  }
536
536
 
537
537
  // Apply mode-specific styles and get shift amount
538
538
  dragElement.value.classList.add(defaultOptions.dragClass!)
539
- shiftAmount = defaultOptions.mode === 'ghost'
539
+ shiftAmount = 'ghost' === defaultOptions.mode
540
540
  ? handleGhostMode(dragElement.value)
541
541
  : handleLineMode(dragElement.value)
542
542
 
@@ -558,7 +558,7 @@ export function useDraggable(options: DraggableOptions = {}) {
558
558
  function onTouchMove(e: TouchEvent) {
559
559
  e.preventDefault() // Prevent scrolling
560
560
  const touch = e.touches[0]
561
- if (!touch) return
561
+ if (!touch) {return}
562
562
 
563
563
  const mouseEvent = {
564
564
  clientX: touch.clientX,
@@ -572,7 +572,7 @@ export function useDraggable(options: DraggableOptions = {}) {
572
572
 
573
573
  function onTouchEnd(e: TouchEvent) {
574
574
  const touch = e.changedTouches[0]
575
- if (!touch) return
575
+ if (!touch) {return}
576
576
 
577
577
  const mouseEvent = {
578
578
  clientX: touch.clientX,
@@ -587,7 +587,7 @@ export function useDraggable(options: DraggableOptions = {}) {
587
587
  }
588
588
 
589
589
  function initDraggableContainer(container: HTMLElement) {
590
- if (!isBrowser) return
590
+ if (!isBrowser) {return}
591
591
  cleanupFn?.()
592
592
 
593
593
  // Reset state
@@ -607,12 +607,12 @@ export function useDraggable(options: DraggableOptions = {}) {
607
607
 
608
608
  let currentIndex = 0
609
609
  elements.forEach((el, index) => {
610
- if (el.dataset.draggable !== 'false') {
610
+ if ('false' !== el.dataset.draggable) {
611
611
  el.style.userSelect = 'none'
612
612
  el.style.webkitUserSelect = 'none'
613
613
  el.__drag_group = options.group
614
614
  el.__drag_index = currentIndex++
615
- el.__drag_list = elements.filter(e => e.dataset.draggable !== 'false')
615
+ el.__drag_list = elements.filter(e => 'false' !== e.dataset.draggable)
616
616
 
617
617
  if (options.items) {
618
618
  el.__drag_data = options.items[index]
@@ -42,37 +42,80 @@ const isDirty = computed(() => {
42
42
 
43
43
  // Initialize on mount
44
44
  onMounted(() => {
45
- if (props.modelValue) initialFormData.value = clone(props.modelValue)
46
- applyDefaultValues()
45
+ if (props.modelValue) {
46
+ initialFormData.value = clone(props.modelValue)
47
+ // Ensure formData is properly initialized with the model value
48
+ if (0 === Object.keys(formData.value).length && 0 < Object.keys(props.modelValue).length) {
49
+ formData.value = clone(props.modelValue)
50
+ }
51
+ }
52
+ // Apply defaults after ensuring model value is set
53
+ setTimeout(() => {
54
+ applyDefaultValues()
55
+ }, 10)
47
56
  })
48
57
 
49
58
  // Watch for model changes
50
59
  watch(() => props.modelValue, (val) => {
51
- if (val !== undefined) formData.value = clone(val)
60
+ if (val !== undefined) {formData.value = clone(val)}
52
61
  }, { immediate: true, deep: true })
53
62
 
63
+ let isApplyingDefaults = false
64
+
54
65
  function applyDefaultValues() {
55
- const schema = resolvedSchema.value as unknown as Array<BaseBagelField<T, any>> | undefined
56
- if (!schema) return
57
-
58
- const walk = (nodes: any[]) => {
59
- for (const node of nodes) {
60
- if (!node || typeof node !== 'object') continue
61
- const hasId = typeof node.id === 'string' && node.id.length > 0
62
- const hasDefault = Object.prototype.hasOwnProperty.call(node, 'defaultValue') && node.defaultValue !== undefined
63
- if (hasId && hasDefault) {
64
- const current = getNestedValue(formData.value as any, node.id as string, undefined)
65
- if (current === undefined || current === '') {
66
- updateFormData({ fieldId: node.id, value: node.defaultValue })
66
+ if (isApplyingDefaults) {return}
67
+ isApplyingDefaults = true
68
+
69
+ try {
70
+ const schema = resolvedSchema.value as unknown as Array<BaseBagelField<T, any>> | undefined
71
+ if (!schema) {return}
72
+
73
+ const walk = (nodes: any[]) => {
74
+ for (const node of nodes) {
75
+ if (!node || 'object' !== typeof node) {continue}
76
+ const hasId = 'string' === typeof node.id && 0 < node.id.length
77
+ const hasDefault = Object.hasOwn(node, 'defaultValue') && node.defaultValue !== undefined
78
+ if (hasId && hasDefault) {
79
+ const current = getNestedValue(formData.value as any, node.id as string, undefined)
80
+
81
+ // Skip arrays completely - let FieldArray manage its own defaults
82
+ if ('array' === node.$el || 'array' === node.type) {
83
+ // Don't apply any defaults to arrays - let FieldArray handle it
84
+ continue
85
+ } else {
86
+ // Don't restore defaultValue for regular inputs - let user control their content
87
+ // Only apply defaultValue on initial load when truly undefined/null
88
+ if (current === undefined || null === current) {
89
+ updateFormData({ fieldId: node.id, value: node.defaultValue })
90
+ }
91
+ }
67
92
  }
93
+ if (Array.isArray(node.children) && node.children.length) {walk(node.children)}
94
+ // Also check nested fields in array/object configurations
95
+ if (Array.isArray(node.fields) && node.fields.length) {walk(node.fields)}
68
96
  }
69
- if (Array.isArray(node.children) && node.children.length) walk(node.children)
70
97
  }
98
+ walk(schema as any[])
99
+ } finally {
100
+ // Reset the flag after a short delay to allow for multiple synchronous calls
101
+ setTimeout(() => {
102
+ isApplyingDefaults = false
103
+ }, 0)
71
104
  }
72
- walk(schema as any[])
73
105
  }
74
106
 
75
- watch(resolvedSchema, () => { applyDefaultValues() }, { deep: true })
107
+ // Use a more conservative watch that doesn't trigger on every change
108
+ const schemaVersion = ref(0)
109
+ watch(resolvedSchema, () => {
110
+ // Increment version to track schema changes
111
+ schemaVersion.value++
112
+ // Only apply defaults after a small delay to avoid rapid firing
113
+ setTimeout(() => {
114
+ if (!isApplyingDefaults) {
115
+ applyDefaultValues()
116
+ }
117
+ }, 10)
118
+ }, { immediate: false })
76
119
 
77
120
  // Update form data
78
121
  function updateFormData({ fieldId, value }: { fieldId?: string, value: any }) {
@@ -82,7 +125,7 @@ function updateFormData({ fieldId, value }: { fieldId?: string, value: any }) {
82
125
 
83
126
  for (let i = 0; i < keys.length - 1; i++) {
84
127
  const key = keys[i]
85
- if (!current[key] || typeof current[key] !== 'object') current[key] = {}
128
+ if (!current[key] || 'object' !== typeof current[key]) {current[key] = {}}
86
129
  current = current[key]
87
130
  }
88
131
 
@@ -99,8 +142,8 @@ const formError = ref<Error>()
99
142
  async function handleSubmit() {
100
143
  try {
101
144
  const valid = validateForm()
102
- if (!valid) return
103
- if (formState.value === 'submitting') return
145
+ if (!valid) {return}
146
+ if ('submitting' === formState.value) {return}
104
147
  formState.value = 'submitting'
105
148
  await props.onSubmit?.(formData.value)
106
149
  initialFormData.value = clone(formData.value)
@@ -118,7 +161,7 @@ const { renderField } = useSchemaField<T>({
118
161
  mode: 'form',
119
162
  getFormData: () => formData.value,
120
163
  onUpdateModelValue: (field, value) => {
121
- if (!field.id) return
164
+ if (!field.id) {return}
122
165
 
123
166
  updateFormData({ fieldId: field.id, value })
124
167
  field.onUpdate?.(value, formData.value)
@@ -131,7 +174,7 @@ const renderSchemaField = (field: any) => renderField(field as BaseBagelField<T,
131
174
  function handleSlotInputChange(event: Event) {
132
175
  const input = event.target as HTMLInputElement
133
176
  if (input.name) {
134
- const value = input.type === 'checkbox' ? input.checked : input.value
177
+ const value = 'checkbox' === input.type ? input.checked : input.value
135
178
  updateFormData({ fieldId: input.name, value })
136
179
  }
137
180
  }
@@ -49,7 +49,7 @@ const previousStep = ref(0)
49
49
  const validatedSteps = ref<number[]>([])
50
50
 
51
51
  function reportValidity() {
52
- if (!formRef.value) return false
52
+ if (!formRef.value) {return false}
53
53
  const isValid = formRef.value.validateForm()
54
54
 
55
55
  if (isValid && !validatedSteps.value.includes(currentStep.value)) {
@@ -71,15 +71,15 @@ const filteredSchema = computed(() => {
71
71
  if ((step as any).vIf !== undefined || (step as any)['v-if'] !== undefined) {
72
72
  const condition = (step as any).vIf ?? (step as any)['v-if']
73
73
  // If condition is a function, evaluate it with current form data
74
- if (typeof condition === 'function') {
74
+ if ('function' === typeof condition) {
75
75
  return condition(undefined, formData.value)
76
76
  }
77
77
  // If condition is a boolean, use it directly
78
- if (typeof condition === 'boolean') {
78
+ if ('boolean' === typeof condition) {
79
79
  return condition
80
80
  }
81
81
  // If condition is a string, evaluate it (treat non-empty as true)
82
- if (typeof condition === 'string') {
82
+ if ('string' === typeof condition) {
83
83
  return !!condition
84
84
  }
85
85
  }
@@ -98,11 +98,11 @@ const schemaIndexMap = computed(() => {
98
98
  let shouldInclude = true
99
99
 
100
100
  if (vIfCondition !== undefined) {
101
- if (typeof vIfCondition === 'function') {
101
+ if ('function' === typeof vIfCondition) {
102
102
  shouldInclude = vIfCondition(undefined, formData.value)
103
- } else if (typeof vIfCondition === 'boolean') {
103
+ } else if ('boolean' === typeof vIfCondition) {
104
104
  shouldInclude = vIfCondition
105
- } else if (typeof vIfCondition === 'string') {
105
+ } else if ('string' === typeof vIfCondition) {
106
106
  shouldInclude = !!vIfCondition
107
107
  }
108
108
  }
@@ -127,7 +127,7 @@ watch(
127
127
  () => currentStep.value,
128
128
  (newStep, oldStep) => {
129
129
  // Set direction based on step change
130
- if (props.direction === 'auto') {
130
+ if ('auto' === props.direction) {
131
131
  slideDirection.value = props.rtl
132
132
  ? (newStep > oldStep ? 'right' : 'left')
133
133
  : (newStep > oldStep ? 'left' : 'right')
@@ -155,12 +155,12 @@ const isStepValid = ref(false)
155
155
 
156
156
  async function checkCurrentStepValidity() {
157
157
  await nextTick()
158
- if (!props.validateOnSteps) isStepValid.value = true
159
- else isStepValid.value = formRef.value?.checkValidity() ?? false
158
+ if (!props.validateOnSteps) {isStepValid.value = true}
159
+ else {isStepValid.value = formRef.value?.checkValidity() ?? false}
160
160
  }
161
161
 
162
162
  function prevStep() {
163
- if (currentStep.value > 0) currentStep.value--
163
+ if (0 < currentStep.value) {currentStep.value--}
164
164
  }
165
165
 
166
166
  const formContainer = ref<HTMLElement>()
@@ -168,8 +168,8 @@ const formContainer = ref<HTMLElement>()
168
168
  async function nextStep() {
169
169
  // Always use reportValidity when attempting to move to next step
170
170
  // This will show validation errors to the user
171
- if (props.validateOnSteps && reportValidity() === false) return
172
- if (!isLastStep.value) currentStep.value++
171
+ if (props.validateOnSteps && false === reportValidity()) {return}
172
+ if (!isLastStep.value) {currentStep.value++}
173
173
  await sleep(400)
174
174
  checkCurrentStepValidity()
175
175
  }
@@ -184,7 +184,7 @@ async function goToStep(stepIndex: number) {
184
184
  // For forward navigation, validate each step sequentially until target or invalid step
185
185
  if (stepIndex > currentStep.value) {
186
186
  // Validate current step first
187
- if (props.validateOnSteps && reportValidity() === false) {
187
+ if (props.validateOnSteps && false === reportValidity()) {
188
188
  return false
189
189
  }
190
190
 
@@ -205,12 +205,12 @@ async function goToStep(stepIndex: number) {
205
205
  if (!isValid) {
206
206
  // If this step is invalid, stop here
207
207
  return false
208
- } else {
208
+ }
209
209
  // Mark this step as validated
210
210
  if (!validatedSteps.value.includes(step)) {
211
211
  validatedSteps.value.push(step)
212
212
  }
213
- }
213
+
214
214
  }
215
215
  }
216
216
 
@@ -222,7 +222,7 @@ async function goToStep(stepIndex: number) {
222
222
 
223
223
  function handleSubmit() {
224
224
  // Show validation errors to the user when submitting
225
- if (reportValidity() === false) return
225
+ if (false === reportValidity()) {return}
226
226
  emits('submit', formData.value)
227
227
  }
228
228
 
@@ -234,7 +234,7 @@ function reset() {
234
234
  // Re-evaluate filtered steps when formData changes
235
235
  watch(() => formData.value, () => {
236
236
  checkCurrentStepValidity()
237
- if (currentStep.value >= numberOfSteps.value && numberOfSteps.value > 0) {
237
+ if (currentStep.value >= numberOfSteps.value && 0 < numberOfSteps.value) {
238
238
  currentStep.value = 0
239
239
  }
240
240
  }, { deep: true })