@bagelink/vue 1.5.15 → 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 (135) 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/RouterWrapper.vue.d.ts.map +1 -1
  6. package/dist/components/calendar/CalendarPopover.vue.d.ts.map +1 -1
  7. package/dist/components/form/BagelForm.vue.d.ts.map +1 -1
  8. package/dist/components/form/FieldArray.vue.d.ts +5 -4
  9. package/dist/components/form/FieldArray.vue.d.ts.map +1 -1
  10. package/dist/components/form/inputs/CheckInput.vue.d.ts.map +1 -1
  11. package/dist/components/form/inputs/RichText/index.vue.d.ts +1 -0
  12. package/dist/components/form/inputs/RichText/index.vue.d.ts.map +1 -1
  13. package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
  14. package/dist/components/form/inputs/ToggleInput.vue.d.ts.map +1 -1
  15. package/dist/components/form/inputs/Upload/UploadInput.vue.d.ts.map +1 -1
  16. package/dist/composables/useFormField.d.ts.map +1 -1
  17. package/dist/composables/useSchemaField.d.ts.map +1 -1
  18. package/dist/index.cjs +68 -55
  19. package/dist/index.mjs +34035 -143
  20. package/dist/style.css +1 -1
  21. package/package.json +1 -1
  22. package/src/components/AccordionItem.vue +2 -2
  23. package/src/components/AddToCalendar.vue +1 -1
  24. package/src/components/BglVideo.vue +8 -8
  25. package/src/components/Btn.vue +9 -9
  26. package/src/components/Card.vue +4 -4
  27. package/src/components/Carousel.vue +44 -44
  28. package/src/components/DataPreview.vue +1 -1
  29. package/src/components/DragOver.vue +6 -6
  30. package/src/components/Dropdown.vue +14 -14
  31. package/src/components/Flag.vue +3 -3
  32. package/src/components/Icon/Icon.vue +13 -13
  33. package/src/components/Image.vue +4 -4
  34. package/src/components/ImportData.vue +79 -79
  35. package/src/components/ListItem.vue +7 -7
  36. package/src/components/MapEmbed/Index.vue +6 -6
  37. package/src/components/Modal.vue +10 -10
  38. package/src/components/ModalForm.vue +4 -4
  39. package/src/components/NavBar.vue +2 -2
  40. package/src/components/Pagination.vue +9 -9
  41. package/src/components/Pill.vue +1 -1
  42. package/src/components/Rating.vue +2 -2
  43. package/src/components/RouterWrapper.vue +3 -3
  44. package/src/components/Slider.vue +77 -77
  45. package/src/components/Spreadsheet/Index.vue +34 -34
  46. package/src/components/Spreadsheet/SpreadsheetTable.vue +3 -3
  47. package/src/components/Zoomer.vue +28 -28
  48. package/src/components/analytics/BarChart.vue +6 -6
  49. package/src/components/analytics/KpiCard.vue +2 -2
  50. package/src/components/analytics/LineChart.vue +14 -14
  51. package/src/components/analytics/PieChart.vue +11 -11
  52. package/src/components/calendar/CalendarPopover.vue +1 -1
  53. package/src/components/calendar/Index.vue +1 -1
  54. package/src/components/calendar/views/AgendaView.vue +2 -2
  55. package/src/components/calendar/views/DayView.vue +6 -6
  56. package/src/components/calendar/views/MonthView.vue +2 -2
  57. package/src/components/calendar/views/WeekView.vue +18 -18
  58. package/src/components/dataTable/DataTable.vue +3 -3
  59. package/src/components/dataTable/useSorting.ts +1 -1
  60. package/src/components/dataTable/useTableData.ts +15 -15
  61. package/src/components/dataTable/useTableSelection.ts +8 -8
  62. package/src/components/dataTable/useTableVirtualization.ts +1 -1
  63. package/src/components/draggable/useDraggable.ts +42 -42
  64. package/src/components/form/BagelForm.vue +66 -23
  65. package/src/components/form/BglMultiStepForm.vue +18 -18
  66. package/src/components/form/FieldArray.vue +177 -67
  67. package/src/components/form/inputs/CheckInput.vue +2 -1
  68. package/src/components/form/inputs/CodeEditor/Index.vue +1 -1
  69. package/src/components/form/inputs/CodeEditor/format.ts +7 -7
  70. package/src/components/form/inputs/CodeEditor/useHighlight.ts +6 -6
  71. package/src/components/form/inputs/DateInput.vue +6 -6
  72. package/src/components/form/inputs/DatePicker.vue +19 -19
  73. package/src/components/form/inputs/EmailInput.vue +14 -14
  74. package/src/components/form/inputs/NumberInput.vue +6 -6
  75. package/src/components/form/inputs/OTP.vue +3 -3
  76. package/src/components/form/inputs/RadioGroup.vue +1 -1
  77. package/src/components/form/inputs/RadioPillsInput.vue +8 -8
  78. package/src/components/form/inputs/RichText/components/EditorToolbar.vue +10 -10
  79. package/src/components/form/inputs/RichText/components/TableGridSelector.vue +1 -1
  80. package/src/components/form/inputs/RichText/composables/useCommands.ts +1 -1
  81. package/src/components/form/inputs/RichText/composables/useEditor.ts +12 -12
  82. package/src/components/form/inputs/RichText/composables/useEditorKeyboard.ts +1 -1
  83. package/src/components/form/inputs/RichText/index.vue +300 -132
  84. package/src/components/form/inputs/RichText/utils/commands.ts +69 -69
  85. package/src/components/form/inputs/RichText/utils/debug.ts +1 -1
  86. package/src/components/form/inputs/RichText/utils/formatting.ts +39 -39
  87. package/src/components/form/inputs/RichText/utils/media.ts +6 -6
  88. package/src/components/form/inputs/RichText/utils/selection.ts +28 -28
  89. package/src/components/form/inputs/RichText/utils/table.ts +19 -19
  90. package/src/components/form/inputs/SelectBtn.vue +1 -1
  91. package/src/components/form/inputs/SelectInput.vue +50 -26
  92. package/src/components/form/inputs/SignaturePad.vue +15 -15
  93. package/src/components/form/inputs/TableField.vue +1 -1
  94. package/src/components/form/inputs/TelInput.vue +6 -6
  95. package/src/components/form/inputs/TextInput.vue +5 -5
  96. package/src/components/form/inputs/ToggleInput.vue +2 -1
  97. package/src/components/form/inputs/Upload/UploadInput.vue +155 -102
  98. package/src/components/form/inputs/Upload/upload.ts +1 -1
  99. package/src/components/form/inputs/Upload/useFileUpload.ts +6 -6
  100. package/src/components/form/useBagelFormState.ts +5 -5
  101. package/src/components/layout/AppContent.vue +1 -1
  102. package/src/components/layout/AppLayout.vue +1 -1
  103. package/src/components/layout/Layout.vue +4 -4
  104. package/src/components/layout/TabbedLayout.vue +1 -1
  105. package/src/components/layout/Tabs.vue +2 -2
  106. package/src/components/layout/TabsNav.vue +7 -7
  107. package/src/components/lightbox/Lightbox.vue +8 -8
  108. package/src/components/lightbox/index.ts +8 -8
  109. package/src/composables/index.ts +2 -2
  110. package/src/composables/useAddToCalendar.ts +13 -13
  111. package/src/composables/useDevice.ts +2 -2
  112. package/src/composables/useExcel.ts +6 -6
  113. package/src/composables/useFormField.ts +5 -9
  114. package/src/composables/usePolling.ts +8 -8
  115. package/src/composables/useSchemaField.ts +53 -38
  116. package/src/composables/useTheme.ts +9 -9
  117. package/src/composables/useValidateFieldValue.ts +2 -2
  118. package/src/directives/pattern.ts +25 -25
  119. package/src/directives/ripple.ts +4 -4
  120. package/src/directives/vResize.ts +6 -6
  121. package/src/plugins/bagel.ts +4 -4
  122. package/src/plugins/useModal.ts +3 -3
  123. package/src/styles/layout.css +7 -1
  124. package/src/utils/BagelFormUtils.ts +7 -7
  125. package/src/utils/calendar/Helpers.ts +8 -8
  126. package/src/utils/calendar/dateUtils.ts +22 -22
  127. package/src/utils/calendar/time.ts +25 -25
  128. package/src/utils/calendar/week.ts +25 -25
  129. package/src/utils/elementUtils.ts +27 -27
  130. package/src/utils/index.ts +22 -22
  131. package/src/utils/sizeParsing.ts +2 -2
  132. package/src/utils/strings.ts +5 -5
  133. package/src/utils/tapDetector.ts +11 -11
  134. package/src/utils/useSearch.ts +29 -29
  135. package/vite.config.ts +1 -1
@@ -5,7 +5,7 @@ import { watch, ref } from 'vue'
5
5
 
6
6
  import { useFileUpload } from './useFileUpload'
7
7
 
8
- const props = withDefaults(defineProps<UploadInputProps & { showIcon?: boolean; icon?: string }>(), {
8
+ const props = withDefaults(defineProps<UploadInputProps & { showIcon?: boolean, icon?: string }>(), {
9
9
  height: '215px',
10
10
  theme: 'dropzone',
11
11
  accept: '*',
@@ -44,16 +44,16 @@ const isDragOver = ref(false)
44
44
  function handleDrag(e: DragEvent, isDragging = false) {
45
45
  e.preventDefault()
46
46
  e.stopPropagation()
47
- if (!props.disabled) isDragOver.value = isDragging
47
+ if (!props.disabled) { isDragOver.value = isDragging }
48
48
  }
49
49
 
50
50
  function updateModelValue() {
51
- if (props.multiple) emit('update:modelValue', pathKeys.value)
52
- else emit('update:modelValue', pathKeys.value[0] || undefined)
51
+ if (props.multiple) { emit('update:modelValue', pathKeys.value) }
52
+ else { emit('update:modelValue', pathKeys.value[0] || undefined) }
53
53
  }
54
54
 
55
55
  async function handleDrop(e: DragEvent) {
56
- if (props.disabled) return
56
+ if (props.disabled) { return }
57
57
  e.preventDefault()
58
58
  e.stopPropagation()
59
59
  emit('addFileStart')
@@ -62,114 +62,167 @@ async function handleDrop(e: DragEvent) {
62
62
  }
63
63
 
64
64
  function fileName(pathKey: string) {
65
- if (!pathKey || typeof pathKey !== 'string') return 'file'
65
+ if (!pathKey || typeof pathKey !== 'string') { return 'file' }
66
66
  return pathKey.split('/').pop() || 'file'
67
67
  }
68
68
  </script>
69
69
 
70
70
  <template>
71
- <div class="bagel-input">
72
- <label v-if="label">{{ label }}</label>
73
- <input v-if="required && !pathKeys.length" placeholder="required" type="text" required class="pixel">
74
- <Card v-if="theme === 'basic'" outline class="flex p-05 gap-1" @dragover="(e) => handleDrag(e, true)" @drop="handleDrop">
75
- <Btn v-if="!pathKeys.length && !fileQueue.length" class="px-1-5" icon="upload" outline :value="btnPlaceholder || 'Upload'" @click="browse()" />
76
- <!-- Loading state during upload -->
77
- <div v-if="fileQueue.length > 0" class="flex align-items-center gap-1 p-05">
78
- <Loading size="20" />
79
- <span class="txt-gray txt-12">
80
- Uploading {{ fileQueue.length }} file{{ fileQueue.length > 1 ? 's' : '' }}...
81
- </span>
82
- </div>
71
+ <div class="bagel-input">
72
+ <label v-if="label">{{ label }}</label>
73
+ <input v-if="required && !pathKeys.length" placeholder="required" type="text" required class="pixel">
74
+ <Card
75
+ v-if="theme === 'basic'" outline class="flex p-05 gap-1" @dragover="(e) => handleDrag(e, true)"
76
+ @drop="handleDrop"
77
+ >
78
+ <Btn
79
+ v-if="!pathKeys.length && !fileQueue.length" class="px-1-5" icon="upload" outline
80
+ :value="btnPlaceholder || 'Upload'" @click="browse()"
81
+ />
82
+ <!-- Loading state during upload -->
83
+ <div v-if="fileQueue.length > 0" class="flex align-items-center gap-1 p-05">
84
+ <Loading size="20" />
85
+ <span class="txt-gray txt-12">
86
+ Uploading {{ fileQueue.length }} file{{ fileQueue.length > 1 ? 's' : '' }}...
87
+ </span>
88
+ </div>
83
89
 
84
- <template v-for="path_key in pathKeys" :key="path_key">
85
- <div class="txt-gray txt-12 flex">
86
- <div class="m-05 flex opacity-8 z-99 gap-025">
87
- <Btn v-tooltip="'Delete'" color="gray" thin icon="delete" @click="removeFile(path_key)" />
88
- <Btn v-tooltip="'Replace'" color="gray" thin icon="autorenew" @click="browse()" />
89
- <Btn icon="download" color="gray" thin :href="pathKeyToURL(path_key)" :download="fileName(path_key)" />
90
- <div class="flex gap-025 rounded pe-1 ps-05 py-025 -my-1 ">
91
- <Icon icon="draft" :size="1.5" />
92
- <p v-lightbox="{ src: pathKeyToURL(path_key), download: true }" class="ellipsis-1 word-break-all h-20 m-0 color-black txt16">
93
- {{ fileName(path_key) }}
94
- </p>
90
+ <template v-for="path_key in pathKeys" :key="path_key">
91
+ <div class="txt-gray txt-12 flex">
92
+ <div class="m-05 flex opacity-8 z-99 gap-025">
93
+ <Btn v-tooltip="'Delete'" color="gray" thin icon="delete" @click="removeFile(path_key)" />
94
+ <Btn v-tooltip="'Replace'" color="gray" thin icon="autorenew" @click="browse()" />
95
+ <Btn
96
+ icon="download" color="gray" thin :href="pathKeyToURL(path_key)"
97
+ :download="fileName(path_key)"
98
+ />
99
+ <div class="flex gap-025 rounded pe-1 ps-05 py-025 -my-1 ">
100
+ <Icon icon="draft" :size="1.5" />
101
+ <p
102
+ v-lightbox="{ src: pathKeyToURL(path_key), download: true }"
103
+ class="ellipsis-1 word-break-all h-20 m-0 color-black txt16"
104
+ >
105
+ {{ fileName(path_key) }}
106
+ </p>
95
107
  </div>
108
+ </div>
109
+ </div>
110
+ </template>
111
+
112
+ <span v-if="!pathKeys.length && !fileQueue.length" class="txt-gray txt-12">
113
+ {{ noFilePlaceholder || 'No file selected' }}
114
+ </span>
115
+ </Card>
116
+
117
+ <div
118
+ v-else class="fileUploadWrap" :class="{
119
+ 'fileDropZone': !pathKeys.length && !fileQueue.length,
120
+ 'dragover': isDragOver,
121
+ 'bgl_oval-upload': oval,
122
+ }" :style="{ width, height }" @click="browse()" @dragover="(e) => handleDrag(e, true)" @drop="handleDrop"
123
+ @dragleave="(e) => handleDrag(e)"
124
+ >
125
+ <slot name="files" :files="pathKeys" :fileQueue>
126
+ <div v-if="multiple" class="bgl-multi-preview">
127
+ <!-- Show uploaded files only if showFileList is true (default) -->
128
+ <template v-if="showFileList !== false">
129
+ <div
130
+ v-for="path_key in pathKeys" :key="path_key"
131
+ v-lightbox="{ src: pathKeyToURL(path_key), download: true }"
132
+ class="multi-image-item-preview" :class="{ 'bgl_fill-image': fill }"
133
+ >
134
+ <Image v-if="isImage(path_key)" :pathKey="path_key" class="multi-preview" />
135
+ <Icon v-else icon="description" class="multi-preview" />
136
+ <p class="m-0">
137
+ {{ fileName(path_key) }}
138
+ </p>
139
+ <Btn thin flat icon="delete" color="red" @click="removeFile(path_key)" />
96
140
  </div>
141
+ </template>
142
+ <!-- File count indicator when showFileList is false and multiple files -->
143
+ <div v-if="showFileList === false && pathKeys.length > 0" class="flex column gap-05 pt-1">
144
+ <p class="color-primary">
145
+ {{ pathKeys.length }} file{{ pathKeys.length > 1 ? 's' : '' }} uploaded
146
+ </p>
147
+ <Btn color="primary" thin icon="autorenew" value="Replace files" @click="browse()" />
148
+ </div>
149
+ <div
150
+ v-for="file in fileQueue" :key="file.name" class="multi-image-item-preview"
151
+ :class="{ 'bgl_fill-image': fill }"
152
+ >
153
+ <img v-if="isImage(file.file.type)" class="multi-preview" :src="file.url" alt="">
154
+ <Icon v-else icon="description" class="multi-preview" />
155
+ <p class="no-margin multi-preview-txt">
156
+ {{ file.name }}
157
+ </p>
158
+ <div
159
+ class="pie" :style="{ '--p': file.progress }" style="--b: 2px"
160
+ :class="{ complete: file.progress === 100 }"
161
+ >
162
+ <span v-if="file.progress < 100" class="progress">
163
+ {{ file.progress.toFixed(0) }}
164
+ </span>
165
+ <Icon class="success" icon="check_circle" />
97
166
  </div>
98
- </template>
99
-
100
- <span v-if="!pathKeys.length && !fileQueue.length" class="txt-gray txt-12">
101
- {{ noFilePlaceholder || 'No file selected' }}
102
- </span>
103
- </Card>
104
-
105
- <div v-else class="fileUploadWrap" :class="{
106
- 'fileDropZone': !pathKeys.length && !fileQueue.length,
107
- 'dragover': isDragOver,
108
- 'bgl_oval-upload': oval,
109
- }" :style="{ width, height }" @click="browse()" @dragover="(e) => handleDrag(e, true)" @drop="handleDrop" @dragleave="(e) => handleDrag(e)">
110
- <slot name="files" :files="pathKeys" :fileQueue>
111
- <div v-if="multiple" class="bgl-multi-preview">
112
- <!-- Show uploaded files only if showFileList is true (default) -->
113
- <div v-if="showFileList !== false" v-for="path_key in pathKeys" :key="path_key" v-lightbox="{ src: pathKeyToURL(path_key), download: true }" class="multi-image-item-preview"
114
- :class="{ 'bgl_fill-image': fill }">
115
- <Image v-if="isImage(path_key)" :pathKey="path_key" class="multi-preview" />
116
- <Icon v-else icon="description" class="multi-preview" />
117
- <p class="m-0">
118
- {{ fileName(path_key) }}
119
- </p>
120
- <Btn thin flat icon="delete" color="red" @click="removeFile(path_key)" />
121
- </div>
122
- <!-- File count indicator when showFileList is false and multiple files -->
123
- <div v-if="showFileList === false && pathKeys.length > 0" class="flex column gap-05 pt-1">
124
- <p class="color-primary">
125
- {{ pathKeys.length }} file{{ pathKeys.length > 1 ? 's' : '' }} uploaded
126
- </p>
127
- <Btn color="primary" thin icon="autorenew" value="Replace files" @click="browse()" />
128
- </div>
129
- <div v-for="file in fileQueue" :key="file.name" class="multi-image-item-preview" :class="{ 'bgl_fill-image': fill }">
130
- <img v-if="isImage(file.file.type)" class="multi-preview" :src="file.url" alt="">
131
- <Icon v-else icon="description" class="multi-preview" />
132
- <p class="no-margin multi-preview-txt">
133
- {{ file.name }}
134
- </p>
135
- <div class="pie" :style="{ '--p': file.progress }" style="--b: 2px" :class="{ complete: file.progress === 100 }">
136
- <span v-if="file.progress < 100" class="progress">
137
- {{ file.progress.toFixed(0) }}
138
- </span>
139
- <Icon class="success" icon="check_circle" />
140
- </div>
141
- </div>
142
- </div>
143
-
144
- <div v-else-if="pathKeys.length > 0 || fileQueue.length > 0" class="bgl-single-preview">
145
- <div v-for="path_key in pathKeys" :key="path_key" class="single-image-item-preview" :class="{ 'bgl_fill-image': fill }">
146
- <div class="flex opacity-8 z-99 gap-025 absolute top-0 start-0" :class="{ 'mx-auto end-0 mt-1 justify-content-center': oval, 'm-05': !oval }">
147
- <Btn v-tooltip="'Delete'" color="white" frame thin icon="delete" @click="removeFile(path_key)" />
148
- <Btn v-tooltip="'Replace'" color="white" frame thin icon="autorenew" @click="browse()" />
149
- <Btn v-tooltip="'Download'" color="white" frame thin icon="download" :href="pathKeyToURL(path_key)" :download="fileName(path_key)" />
150
- </div>
151
- <div v-if="isImage(path_key)" class="h-100">
152
- <Image v-lightbox="{ src: pathKeyToURL(path_key), download: true }" class="single-preview" :pathKey="path_key" alt="" />
153
- </div>
154
- <Icon v-else v-lightbox="{ src: pathKeyToURL(path_key), download: true }" :size="4" weight="2" icon="description" class="color-primary w-100" />
155
- </div>
156
- <div v-for="file in fileQueue" :key="file.name" class="single-image-item-preview" :class="{ 'bgl_fill-image': fill }">
157
- <Loading type="bar" :progress="file.progress" class="absolute bottom-05 end start w-100px mx-auto rounded overflow-hidden" />
158
- <img v-if="isImage(file.file.type)" class="single-preview opacity-5" :src="file.url" alt="">
159
- </div>
160
- </div>
161
- </slot>
162
-
163
- <slot v-if="(!pathKeys.length && !fileQueue.length) || multiple" name="placeholder" :files="pathKeys" :fileQueue :browse>
164
- <p class="p-1 flex column hover fileUploadPlaceHolder justify-content-center mb-05 ">
165
- <Icon v-if="showIcon" :name="icon" class="user-select-none" />
166
- <span class=" pretty balance user-select-none ">
167
- {{ dropPlaceholder || 'Drag and Drop files here or click to upload' }}
168
- </span>
169
- </p>
170
- </slot>
167
+ </div>
168
+ </div>
169
+
170
+ <div v-else-if="pathKeys.length > 0 || fileQueue.length > 0" class="bgl-single-preview">
171
+ <div
172
+ v-for="path_key in pathKeys" :key="path_key" class="single-image-item-preview"
173
+ :class="{ 'bgl_fill-image': fill }"
174
+ >
175
+ <div
176
+ class="flex opacity-8 z-99 gap-025 absolute top-0 start-0"
177
+ :class="{ 'mx-auto end-0 mt-1 justify-content-center': oval, 'm-05': !oval }"
178
+ >
179
+ <Btn
180
+ v-tooltip="'Delete'" color="white" frame thin icon="delete"
181
+ @click="removeFile(path_key)"
182
+ />
183
+ <Btn v-tooltip="'Replace'" color="white" frame thin icon="autorenew" @click="browse()" />
184
+ <Btn
185
+ v-tooltip="'Download'" color="white" frame thin icon="download"
186
+ :href="pathKeyToURL(path_key)" :download="fileName(path_key)"
187
+ />
171
188
  </div>
189
+ <div v-if="isImage(path_key)" class="h-100">
190
+ <Image
191
+ v-lightbox="{ src: pathKeyToURL(path_key), download: true }" class="single-preview"
192
+ :pathKey="path_key" alt=""
193
+ />
172
194
  </div>
195
+ <Icon
196
+ v-else v-lightbox="{ src: pathKeyToURL(path_key), download: true }" :size="4" weight="2"
197
+ icon="description" class="color-primary w-100"
198
+ />
199
+ </div>
200
+ <div
201
+ v-for="file in fileQueue" :key="file.name" class="single-image-item-preview"
202
+ :class="{ 'bgl_fill-image': fill }"
203
+ >
204
+ <Loading
205
+ type="bar" :progress="file.progress"
206
+ class="absolute bottom-05 end start w-100px mx-auto rounded overflow-hidden"
207
+ />
208
+ <img v-if="isImage(file.file.type)" class="single-preview opacity-5" :src="file.url" alt="">
209
+ </div>
210
+ </div>
211
+ </slot>
212
+
213
+ <slot
214
+ v-if="(!pathKeys.length && !fileQueue.length) || multiple" name="placeholder" :files="pathKeys"
215
+ :fileQueue :browse
216
+ >
217
+ <p class="p-1 flex column hover fileUploadPlaceHolder justify-content-center mb-05 ">
218
+ <Icon v-if="showIcon" :name="icon" class="user-select-none" />
219
+ <span class=" pretty balance user-select-none ">
220
+ {{ dropPlaceholder || 'Drag and Drop files here or click to upload' }}
221
+ </span>
222
+ </p>
223
+ </slot>
224
+ </div>
225
+ </div>
173
226
  </template>
174
227
 
175
228
  <style src="./upload.css" scoped></style>
@@ -8,7 +8,7 @@ const getFileVersion = () => getBagelInstance()?.fileVersion ?? 'files_v2'
8
8
 
9
9
  export const files = {
10
10
  setBaseUrl: (baseUrl?: string) => {
11
- if (baseUrl === undefined || baseUrl === '') return
11
+ if (baseUrl === undefined || '' === baseUrl) {return}
12
12
  baseUrl = baseUrl.replace(/\/$/, '')
13
13
  axios.defaults.baseURL = baseUrl
14
14
  },
@@ -32,7 +32,7 @@ export function useFileUpload(props: UseFileUploadProps = {}) {
32
32
  const fileToUrl = (file: File) => URL.createObjectURL(file)
33
33
 
34
34
  function addFile(file?: File | File[] | FileList | null) {
35
- if (!file) return
35
+ if (!file) {return}
36
36
 
37
37
  let filesToAdd: File[] = []
38
38
 
@@ -58,18 +58,18 @@ export function useFileUpload(props: UseFileUploadProps = {}) {
58
58
  }
59
59
 
60
60
  // Call the onFilesQueued callback if provided
61
- if (props.onFileQueued && newQueueFiles.length > 0) {
61
+ if (props.onFileQueued && 0 < newQueueFiles.length) {
62
62
  props.onFileQueued(newQueueFiles)
63
63
  }
64
64
  }
65
65
 
66
66
  async function removeFile(pathKeyOrFile: string | File | QueueFile) {
67
- if (typeof pathKeyOrFile === 'string') {
67
+ if ('string' === typeof pathKeyOrFile) {
68
68
  // Remove from both lists
69
69
  storageFiles.value = storageFiles.value.filter(file => file.path_key !== pathKeyOrFile)
70
70
 
71
71
  const pathKeyIndex = pk.value.indexOf(pathKeyOrFile)
72
- if (pathKeyIndex !== -1) {
72
+ if (-1 !== pathKeyIndex) {
73
73
  pk.value.splice(pathKeyIndex, 1)
74
74
  }
75
75
 
@@ -88,7 +88,7 @@ export function useFileUpload(props: UseFileUploadProps = {}) {
88
88
  && queueFile.namespace === namespace
89
89
  )
90
90
 
91
- if (index !== -1) {
91
+ if (-1 !== index) {
92
92
  fileQueue.value.splice(index, 1)
93
93
  }
94
94
  }
@@ -124,7 +124,7 @@ export function useFileUpload(props: UseFileUploadProps = {}) {
124
124
 
125
125
  // UI interaction
126
126
  function browse(autoFlush = false) {
127
- if (props.disabled) return
127
+ if (props.disabled) {return}
128
128
 
129
129
  const input = document.createElement('input')
130
130
  input.type = 'file'
@@ -13,11 +13,11 @@ export interface BagelFormState<T> {
13
13
 
14
14
  // Helper function to safely clone objects without circular references
15
15
  function safeClone(obj: any): any {
16
- if (obj === null || typeof obj !== 'object') return obj
16
+ if (null === obj || 'object' !== typeof obj) {return obj}
17
17
 
18
18
  const seen = new WeakSet()
19
19
  return JSON.parse(JSON.stringify(obj, (key, value) => {
20
- if (typeof value === 'object' && value !== null) {
20
+ if ('object' === typeof value && null !== value) {
21
21
  if (seen.has(value)) {
22
22
  return undefined // Remove circular reference
23
23
  }
@@ -37,7 +37,7 @@ export function provideBagelFormState<T>(initialData: T) {
37
37
  const keys = path.split(/[.[]/)
38
38
 
39
39
  // Initialize the root if it's not an object
40
- if (typeof data.value !== 'object' || data.value === null) {
40
+ if ('object' !== typeof data.value || null === data.value) {
41
41
  data.value = {} as T
42
42
  }
43
43
 
@@ -46,7 +46,7 @@ export function provideBagelFormState<T>(initialData: T) {
46
46
  // Build the path, ensuring each level is an object
47
47
  for (let i = 0; i < keys.length - 1; i++) {
48
48
  const key = keys[i]
49
- if (!(key in current) || typeof current[key] !== 'object' || current[key] === null) {
49
+ if (!(key in current) || 'object' !== typeof current[key] || null === current[key]) {
50
50
  current[key] = {}
51
51
  }
52
52
  current = current[key]
@@ -71,6 +71,6 @@ export function provideBagelFormState<T>(initialData: T) {
71
71
 
72
72
  export function useBagelFormState<T>(injectionKey: typeof FORM_STATE_KEY = FORM_STATE_KEY): BagelFormState<T> {
73
73
  const state = inject<BagelFormState<T>>(injectionKey)
74
- if (!state) throw new Error('BagelFormState must be provided')
74
+ if (!state) {throw new Error('BagelFormState must be provided')}
75
75
  return state
76
76
  }
@@ -31,7 +31,7 @@ const sidebarCardStyle = inject('sidebarCardStyle', { value: false })
31
31
  const hasSidebarCard = computed(() => {
32
32
  // Check if there's an AppSidebar with card class in the DOM
33
33
  const sidebar = document.querySelector('.app-sidebar .card')
34
- return sidebar !== null || sidebarCardStyle?.value
34
+ return null !== sidebar || sidebarCardStyle?.value
35
35
  })
36
36
  </script>
37
37
 
@@ -17,7 +17,7 @@ const isMobile = ref(false)
17
17
 
18
18
  // Check if mobile
19
19
  function checkMobile() {
20
- isMobile.value = window.innerWidth < 910
20
+ isMobile.value = 910 > window.innerWidth
21
21
  if (isMobile.value) {
22
22
  isOpen.value = false
23
23
  }
@@ -20,19 +20,19 @@ const props = withDefaults(defineProps<LayoutProrps>(), {
20
20
 
21
21
  })
22
22
 
23
- const gridTemplateRows = $computed(() => (props.rows.length > 0 ? props.rows.join(' ') : 'auto'))
23
+ const gridTemplateRows = $computed(() => (0 < props.rows.length ? props.rows.join(' ') : 'auto'))
24
24
  const gapSize = $computed(() => `${props.gap}rem`)
25
25
  const mGapSize = $computed(() => props.mGap !== undefined ? `${props.mGap}rem` : gapSize)
26
26
 
27
27
  const mGridTemplateRows = $computed(() => {
28
- if (props.mRows?.length) return props.mRows.join(' ')
28
+ if (props.mRows?.length) {return props.mRows.join(' ')}
29
29
  return gridTemplateRows
30
30
  })
31
31
 
32
- const gridTemplateColumns = $computed(() => (props.columns.length > 0 ? props.columns.join(' ') : 'auto'))
32
+ const gridTemplateColumns = $computed(() => (0 < props.columns.length ? props.columns.join(' ') : 'auto'))
33
33
 
34
34
  const mGridTemplateColumns = $computed(() => {
35
- if (props.mColumns?.length) return props.mColumns.join(' ')
35
+ if (props.mColumns?.length) {return props.mColumns.join(' ')}
36
36
  return gridTemplateColumns
37
37
  })
38
38
  </script>
@@ -17,7 +17,7 @@ let activeTab = $ref<string>()
17
17
  function changeTab(tab: string) {
18
18
  activeTab = tab
19
19
  emit('update:modelValue', activeTab)
20
- if (!props.router) return
20
+ if (!props.router) {return}
21
21
  void props.router.push({
22
22
  path: props.router.currentRoute.value.path,
23
23
  query: { ...props.router.currentRoute.value.query, t: tab },
@@ -17,7 +17,7 @@ const slots: SetupContext['slots'] = useSlots()
17
17
  const group = Math.random().toString(36).slice(7)
18
18
  const { currentTab } = useTabs(group)
19
19
 
20
- const tabValue = (tab: Tab) => (typeof tab === 'string' ? tab : tab.id)
20
+ const tabValue = (tab: Tab) => ('string' === typeof tab ? tab : tab.id)
21
21
 
22
22
  const slctTab = $computed({
23
23
  get: () => props.modelValue || tabValue(props.tabs[0]),
@@ -31,7 +31,7 @@ const tabComponent = defineComponent({
31
31
  const currentTabIndex = props.tabs.findIndex(
32
32
  tab => tabValue(tab) === currentTab.value
33
33
  )
34
- if (currentTabIndex === -1) return
34
+ if (-1 === currentTabIndex) {return}
35
35
  const slotChildren = slots.default?.()[1]?.children
36
36
 
37
37
  return h('div', (slotChildren as VNode[])[currentTabIndex])
@@ -23,7 +23,7 @@ const props = defineProps<{
23
23
  const emit = defineEmits(['update:modelValue'])
24
24
  const { currentTab } = useTabs(props.group)
25
25
  currentTab.value
26
- = props.modelValue || typeof props.tabs[0] === 'string'
26
+ = props.modelValue || 'string' === typeof props.tabs[0]
27
27
  ? props.tabs[0]
28
28
  : props.tabs[0].id
29
29
 
@@ -32,13 +32,13 @@ const tabs = ref<HTMLElement[]>([])
32
32
 
33
33
  function updateIndicator() {
34
34
  nextTick(() => {
35
- if (!tabsWrap.value) return
35
+ if (!tabsWrap.value) {return}
36
36
  const activeTab = tabs.value.find(tab => tab.classList.contains('active'))
37
37
  if (activeTab) {
38
38
  // Wait a bit more to ensure CSS is fully loaded and elements are properly sized
39
39
  setTimeout(() => {
40
40
  const { offsetLeft, offsetWidth } = activeTab
41
- if (offsetLeft >= 0 && offsetWidth > 0) { // Ensure valid measurements
41
+ if (0 <= offsetLeft && 0 < offsetWidth) { // Ensure valid measurements
42
42
  tabsWrap.value?.style.setProperty('--indicator-left', `${offsetLeft}px`)
43
43
  tabsWrap.value?.style.setProperty('--indicator-width', `${offsetWidth}px`)
44
44
  tabsWrap.value?.style.setProperty('--indicator-opacity', '1')
@@ -49,25 +49,25 @@ function updateIndicator() {
49
49
  }
50
50
 
51
51
  function selectTab(tab: TabType | string) {
52
- currentTab.value = typeof tab === 'string' ? tab : tab.id
52
+ currentTab.value = 'string' === typeof tab ? tab : tab.id
53
53
  emit('update:modelValue', currentTab.value)
54
54
  nextTick(() => { updateIndicator() })
55
55
  }
56
56
 
57
57
  function isActive(tab: TabType | string) {
58
- if (typeof tab === 'string') return currentTab.value === tab
58
+ if ('string' === typeof tab) {return currentTab.value === tab}
59
59
  return currentTab.value === tab.id
60
60
  }
61
61
 
62
62
  function tabLabel(tab: TabType | string) {
63
- if (typeof tab === 'string') return tab
63
+ if ('string' === typeof tab) {return tab}
64
64
  return tab.label
65
65
  }
66
66
 
67
67
  watch(
68
68
  () => props.modelValue,
69
69
  (value) => {
70
- if (value && !isActive(value)) currentTab.value = value
70
+ if (value && !isActive(value)) {currentTab.value = value}
71
71
  nextTick(() => { updateIndicator() })
72
72
  },
73
73
  { immediate: true }
@@ -22,14 +22,14 @@ function close() {
22
22
  }
23
23
 
24
24
  function next() {
25
- if (group.length > 1) {
25
+ if (1 < group.length) {
26
26
  currentIndex = (currentIndex + 1) % group.length
27
27
  currentItem = group[currentIndex]
28
28
  }
29
29
  }
30
30
 
31
31
  function prev() {
32
- if (group.length > 1) {
32
+ if (1 < group.length) {
33
33
  currentIndex = (currentIndex - 1 + group.length) % group.length
34
34
  currentItem = group[currentIndex]
35
35
  }
@@ -41,16 +41,16 @@ function selectItem(index: number) {
41
41
  }
42
42
 
43
43
  watch(() => isOpen, (val) => {
44
- if (val) document.body.style.overflow = 'hidden'
45
- else document.body.style.overflow = ''
44
+ if (val) {document.body.style.overflow = 'hidden'}
45
+ else {document.body.style.overflow = ''}
46
46
  })
47
47
 
48
48
  function handleKeydown(event: KeyboardEvent) {
49
- if (event.key === 'Escape') {
49
+ if ('Escape' === event.key) {
50
50
  close()
51
- } else if (event.key === 'ArrowLeft') {
51
+ } else if ('ArrowLeft' === event.key) {
52
52
  prev()
53
- } else if (event.key === 'ArrowRight') {
53
+ } else if ('ArrowRight' === event.key) {
54
54
  next()
55
55
  }
56
56
  }
@@ -58,7 +58,7 @@ function handleKeydown(event: KeyboardEvent) {
58
58
  const zoom = $ref(1)
59
59
 
60
60
  function clickOutside() {
61
- if (zoom === 1) close()
61
+ if (1 === zoom) {close()}
62
62
  }
63
63
 
64
64
  defineExpose({ open, close })
@@ -32,9 +32,9 @@ const lightboxDirective: Directive = {
32
32
 
33
33
  function groupHandler(item: LightboxItem) {
34
34
  if (item.group) {
35
- if (!groups[item.group]) groups[item.group] = []
35
+ if (!groups[item.group]) {groups[item.group] = []}
36
36
  const currentIndex = groups[item.group].findIndex(i => i.src === item.src)
37
- if (currentIndex === -1) groups[item.group].push(item)
37
+ if (-1 === currentIndex) {groups[item.group].push(item)}
38
38
  }
39
39
  }
40
40
 
@@ -42,7 +42,7 @@ function openClickHandler(e: MouseEvent, el: HTMLElement, binding: DirectiveBind
42
42
  e.stopPropagation()
43
43
  const item = bindingToItem(binding, el)
44
44
  const lightboxInstance = getLightboxInstance()
45
- if (!lightboxInstance || !lightboxInstance.open) return
45
+ if (!lightboxInstance || !lightboxInstance.open) {return}
46
46
  const open = lightboxInstance.open as OpenFunction
47
47
  const group = item && item.group ? groups[item.group] : undefined
48
48
  open(item, group)
@@ -60,18 +60,18 @@ const youtubeRegex = /youtube\.com|youtu\.be/
60
60
  const vimeoRegex = /vimeo\.com/
61
61
 
62
62
  function urlToName(url: string): string {
63
- if (!url || typeof url !== 'string') return ''
63
+ if (!url || 'string' !== typeof url) {return ''}
64
64
  const name = url.split('/').pop() || ''
65
65
  return name.replace(/\.[^/.]+$/, '')
66
66
  }
67
67
 
68
68
  function determineFileType(url: any): string {
69
- if (typeof url !== 'string' || !url) return 'unknown'
69
+ if ('string' !== typeof url || !url) {return 'unknown'}
70
70
  const extension = (url.split('.').pop() || '').toLowerCase()
71
71
  const altExtension = url.split('?')[0].split('.').pop()?.toLowerCase() || ''
72
- if (IMAGE_FORMATS_REGEXP.test(extension) || IMAGE_FORMATS_REGEXP.test(altExtension)) return 'image'
73
- if (VIDEO_FORMATS_REGEXP.test(extension) || youtubeRegex.test(url) || vimeoRegex.test(url)) return 'video'
74
- if (['pdf'].includes(extension)) return 'pdf'
72
+ if (IMAGE_FORMATS_REGEXP.test(extension) || IMAGE_FORMATS_REGEXP.test(altExtension)) {return 'image'}
73
+ if (VIDEO_FORMATS_REGEXP.test(extension) || youtubeRegex.test(url) || vimeoRegex.test(url)) {return 'video'}
74
+ if (['pdf'].includes(extension)) {return 'pdf'}
75
75
  return extension ?? 'unknown'
76
76
  }
77
77
 
@@ -24,7 +24,7 @@ export function useBglSchema<T = { [key: string]: unknown }>(
24
24
 
25
25
  if (_schema) {
26
26
  return (
27
- _columns && _columns.length > 0
27
+ _columns && 0 < _columns.length
28
28
  ? _schema.filter(f => _columns.includes(f.id as string))
29
29
  : _schema
30
30
  ) as BglFormSchemaT<T>
@@ -39,7 +39,7 @@ export function localRef<T>(
39
39
  IfAny<T, Ref<T, T>, T> :
40
40
  Ref<UnwrapRef<T>, T | UnwrapRef<T>> {
41
41
  const storedValue = localStorage.getItem(key)
42
- const initial = storedValue !== null ? JSON.parse(storedValue) : initialValue
42
+ const initial = null !== storedValue ? JSON.parse(storedValue) : initialValue
43
43
  const value = ref<T>(initial)
44
44
 
45
45
  watch(() => value.value, (val) => {