@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.
- package/bin/experimentalGenTypedRoutes.ts +15 -15
- package/bin/generateFormSchema.ts +12 -12
- package/bin/utils.ts +4 -4
- package/dist/components/Dropdown.vue.d.ts.map +1 -1
- package/dist/components/RouterWrapper.vue.d.ts.map +1 -1
- package/dist/components/calendar/CalendarPopover.vue.d.ts.map +1 -1
- package/dist/components/form/BagelForm.vue.d.ts.map +1 -1
- package/dist/components/form/FieldArray.vue.d.ts +5 -4
- package/dist/components/form/FieldArray.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/CheckInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RichText/index.vue.d.ts +1 -0
- package/dist/components/form/inputs/RichText/index.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/ToggleInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/Upload/UploadInput.vue.d.ts.map +1 -1
- package/dist/composables/useFormField.d.ts.map +1 -1
- package/dist/composables/useSchemaField.d.ts.map +1 -1
- package/dist/index.cjs +68 -55
- package/dist/index.mjs +34035 -143
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/AccordionItem.vue +2 -2
- package/src/components/AddToCalendar.vue +1 -1
- package/src/components/BglVideo.vue +8 -8
- package/src/components/Btn.vue +9 -9
- package/src/components/Card.vue +4 -4
- package/src/components/Carousel.vue +44 -44
- package/src/components/DataPreview.vue +1 -1
- package/src/components/DragOver.vue +6 -6
- package/src/components/Dropdown.vue +14 -14
- package/src/components/Flag.vue +3 -3
- package/src/components/Icon/Icon.vue +13 -13
- package/src/components/Image.vue +4 -4
- package/src/components/ImportData.vue +79 -79
- package/src/components/ListItem.vue +7 -7
- package/src/components/MapEmbed/Index.vue +6 -6
- package/src/components/Modal.vue +10 -10
- package/src/components/ModalForm.vue +4 -4
- package/src/components/NavBar.vue +2 -2
- package/src/components/Pagination.vue +9 -9
- package/src/components/Pill.vue +1 -1
- package/src/components/Rating.vue +2 -2
- package/src/components/RouterWrapper.vue +3 -3
- package/src/components/Slider.vue +77 -77
- package/src/components/Spreadsheet/Index.vue +34 -34
- package/src/components/Spreadsheet/SpreadsheetTable.vue +3 -3
- package/src/components/Zoomer.vue +28 -28
- package/src/components/analytics/BarChart.vue +6 -6
- package/src/components/analytics/KpiCard.vue +2 -2
- package/src/components/analytics/LineChart.vue +14 -14
- package/src/components/analytics/PieChart.vue +11 -11
- package/src/components/calendar/CalendarPopover.vue +1 -1
- package/src/components/calendar/Index.vue +1 -1
- package/src/components/calendar/views/AgendaView.vue +2 -2
- package/src/components/calendar/views/DayView.vue +6 -6
- package/src/components/calendar/views/MonthView.vue +2 -2
- package/src/components/calendar/views/WeekView.vue +18 -18
- package/src/components/dataTable/DataTable.vue +3 -3
- package/src/components/dataTable/useSorting.ts +1 -1
- package/src/components/dataTable/useTableData.ts +15 -15
- package/src/components/dataTable/useTableSelection.ts +8 -8
- package/src/components/dataTable/useTableVirtualization.ts +1 -1
- package/src/components/draggable/useDraggable.ts +42 -42
- package/src/components/form/BagelForm.vue +66 -23
- package/src/components/form/BglMultiStepForm.vue +18 -18
- package/src/components/form/FieldArray.vue +177 -67
- package/src/components/form/inputs/CheckInput.vue +2 -1
- package/src/components/form/inputs/CodeEditor/Index.vue +1 -1
- package/src/components/form/inputs/CodeEditor/format.ts +7 -7
- package/src/components/form/inputs/CodeEditor/useHighlight.ts +6 -6
- package/src/components/form/inputs/DateInput.vue +6 -6
- package/src/components/form/inputs/DatePicker.vue +19 -19
- package/src/components/form/inputs/EmailInput.vue +14 -14
- package/src/components/form/inputs/NumberInput.vue +6 -6
- package/src/components/form/inputs/OTP.vue +3 -3
- package/src/components/form/inputs/RadioGroup.vue +1 -1
- package/src/components/form/inputs/RadioPillsInput.vue +8 -8
- package/src/components/form/inputs/RichText/components/EditorToolbar.vue +10 -10
- package/src/components/form/inputs/RichText/components/TableGridSelector.vue +1 -1
- package/src/components/form/inputs/RichText/composables/useCommands.ts +1 -1
- package/src/components/form/inputs/RichText/composables/useEditor.ts +12 -12
- package/src/components/form/inputs/RichText/composables/useEditorKeyboard.ts +1 -1
- package/src/components/form/inputs/RichText/index.vue +300 -132
- package/src/components/form/inputs/RichText/utils/commands.ts +69 -69
- package/src/components/form/inputs/RichText/utils/debug.ts +1 -1
- package/src/components/form/inputs/RichText/utils/formatting.ts +39 -39
- package/src/components/form/inputs/RichText/utils/media.ts +6 -6
- package/src/components/form/inputs/RichText/utils/selection.ts +28 -28
- package/src/components/form/inputs/RichText/utils/table.ts +19 -19
- package/src/components/form/inputs/SelectBtn.vue +1 -1
- package/src/components/form/inputs/SelectInput.vue +50 -26
- package/src/components/form/inputs/SignaturePad.vue +15 -15
- package/src/components/form/inputs/TableField.vue +1 -1
- package/src/components/form/inputs/TelInput.vue +6 -6
- package/src/components/form/inputs/TextInput.vue +5 -5
- package/src/components/form/inputs/ToggleInput.vue +2 -1
- package/src/components/form/inputs/Upload/UploadInput.vue +155 -102
- package/src/components/form/inputs/Upload/upload.ts +1 -1
- package/src/components/form/inputs/Upload/useFileUpload.ts +6 -6
- package/src/components/form/useBagelFormState.ts +5 -5
- package/src/components/layout/AppContent.vue +1 -1
- package/src/components/layout/AppLayout.vue +1 -1
- package/src/components/layout/Layout.vue +4 -4
- package/src/components/layout/TabbedLayout.vue +1 -1
- package/src/components/layout/Tabs.vue +2 -2
- package/src/components/layout/TabsNav.vue +7 -7
- package/src/components/lightbox/Lightbox.vue +8 -8
- package/src/components/lightbox/index.ts +8 -8
- package/src/composables/index.ts +2 -2
- package/src/composables/useAddToCalendar.ts +13 -13
- package/src/composables/useDevice.ts +2 -2
- package/src/composables/useExcel.ts +6 -6
- package/src/composables/useFormField.ts +5 -9
- package/src/composables/usePolling.ts +8 -8
- package/src/composables/useSchemaField.ts +53 -38
- package/src/composables/useTheme.ts +9 -9
- package/src/composables/useValidateFieldValue.ts +2 -2
- package/src/directives/pattern.ts +25 -25
- package/src/directives/ripple.ts +4 -4
- package/src/directives/vResize.ts +6 -6
- package/src/plugins/bagel.ts +4 -4
- package/src/plugins/useModal.ts +3 -3
- package/src/styles/layout.css +7 -1
- package/src/utils/BagelFormUtils.ts +7 -7
- package/src/utils/calendar/Helpers.ts +8 -8
- package/src/utils/calendar/dateUtils.ts +22 -22
- package/src/utils/calendar/time.ts +25 -25
- package/src/utils/calendar/week.ts +25 -25
- package/src/utils/elementUtils.ts +27 -27
- package/src/utils/index.ts +22 -22
- package/src/utils/sizeParsing.ts +2 -2
- package/src/utils/strings.ts +5 -5
- package/src/utils/tapDetector.ts +11 -11
- package/src/utils/useSearch.ts +29 -29
- package/vite.config.ts +1 -1
|
@@ -14,7 +14,7 @@ export type CalendarProvider = 'google' | 'apple' | 'outlook' | 'outlookcom' | '
|
|
|
14
14
|
export function useAddToCalendar(event: CalendarEvent) {
|
|
15
15
|
// Parse dates if they're strings
|
|
16
16
|
const parseDate = (date: Date | string): Date => {
|
|
17
|
-
return typeof date
|
|
17
|
+
return 'string' === typeof date ? new Date(date) : date
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
const eventStartDate = parseDate(event.startDate)
|
|
@@ -33,7 +33,7 @@ export function useAddToCalendar(event: CalendarEvent) {
|
|
|
33
33
|
|
|
34
34
|
// Check if location is a URL
|
|
35
35
|
const isUrl = (text?: string): boolean => {
|
|
36
|
-
if (!text || text.length
|
|
36
|
+
if (!text || 0 === text.length) {
|
|
37
37
|
return false
|
|
38
38
|
}
|
|
39
39
|
return /^https?:\/\/.+/.test(text.trim())
|
|
@@ -77,13 +77,13 @@ export function useAddToCalendar(event: CalendarEvent) {
|
|
|
77
77
|
`SUMMARY:${event.title}`,
|
|
78
78
|
]
|
|
79
79
|
|
|
80
|
-
if (event.description && event.description.length
|
|
80
|
+
if (event.description && 0 < event.description.length) {
|
|
81
81
|
// ICS descriptions need special handling of newlines and character limits
|
|
82
82
|
const description = event.description.replace(/\n/g, '\\n')
|
|
83
83
|
icsContent.push(`DESCRIPTION:${description}`)
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
if (event.location && event.location.length
|
|
86
|
+
if (event.location && 0 < event.location.length) {
|
|
87
87
|
icsContent.push(`LOCATION:${event.location}`)
|
|
88
88
|
// If location is a URL, also add it as the URL field
|
|
89
89
|
if (locationIsUrl) {
|
|
@@ -104,11 +104,11 @@ export function useAddToCalendar(event: CalendarEvent) {
|
|
|
104
104
|
dates: `${formatDateISO(eventStartDate)}/${formatDateISO(eventEndDate)}`,
|
|
105
105
|
})
|
|
106
106
|
|
|
107
|
-
if (event.description && event.description.length
|
|
107
|
+
if (event.description && 0 < event.description.length) {
|
|
108
108
|
params.append('details', event.description)
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
if (event.location && event.location.length
|
|
111
|
+
if (event.location && 0 < event.location.length) {
|
|
112
112
|
params.append('location', event.location)
|
|
113
113
|
}
|
|
114
114
|
|
|
@@ -125,11 +125,11 @@ export function useAddToCalendar(event: CalendarEvent) {
|
|
|
125
125
|
enddt: eventEndDate.toISOString(),
|
|
126
126
|
})
|
|
127
127
|
|
|
128
|
-
if (event.description && event.description.length
|
|
128
|
+
if (event.description && 0 < event.description.length) {
|
|
129
129
|
params.append('body', event.description)
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
if (event.location && event.location.length
|
|
132
|
+
if (event.location && 0 < event.location.length) {
|
|
133
133
|
params.append('location', event.location)
|
|
134
134
|
}
|
|
135
135
|
|
|
@@ -146,11 +146,11 @@ export function useAddToCalendar(event: CalendarEvent) {
|
|
|
146
146
|
enddt: eventEndDate.toISOString(),
|
|
147
147
|
})
|
|
148
148
|
|
|
149
|
-
if (event.description && event.description.length
|
|
149
|
+
if (event.description && 0 < event.description.length) {
|
|
150
150
|
params.append('body', event.description)
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
if (event.location && event.location.length
|
|
153
|
+
if (event.location && 0 < event.location.length) {
|
|
154
154
|
params.append('location', event.location)
|
|
155
155
|
}
|
|
156
156
|
|
|
@@ -168,11 +168,11 @@ export function useAddToCalendar(event: CalendarEvent) {
|
|
|
168
168
|
dur: duration.toString(),
|
|
169
169
|
})
|
|
170
170
|
|
|
171
|
-
if (event.description && event.description.length
|
|
171
|
+
if (event.description && 0 < event.description.length) {
|
|
172
172
|
params.append('desc', event.description)
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
if (event.location && event.location.length
|
|
175
|
+
if (event.location && 0 < event.location.length) {
|
|
176
176
|
params.append('in_loc', event.location)
|
|
177
177
|
}
|
|
178
178
|
|
|
@@ -214,7 +214,7 @@ export function useAddToCalendar(event: CalendarEvent) {
|
|
|
214
214
|
|
|
215
215
|
// Add to calendar action
|
|
216
216
|
const addToCalendar = (provider: CalendarProvider) => {
|
|
217
|
-
if (
|
|
217
|
+
if ('apple' === provider || 'ics' === provider) {
|
|
218
218
|
downloadICS()
|
|
219
219
|
} else {
|
|
220
220
|
const url = getCalendarUrl(provider)
|
|
@@ -2,7 +2,7 @@ import { onMounted, onUnmounted, ref } from 'vue'
|
|
|
2
2
|
|
|
3
3
|
export function useDevice() {
|
|
4
4
|
const innerWidth = ref(window.innerWidth)
|
|
5
|
-
const isMobile = ref(window.innerWidth
|
|
5
|
+
const isMobile = ref(768 > window.innerWidth)
|
|
6
6
|
const scrollY = ref(window.scrollY)
|
|
7
7
|
const scrollX = ref(window.scrollX)
|
|
8
8
|
const innerHeight = ref(window.innerHeight)
|
|
@@ -20,7 +20,7 @@ export function useDevice() {
|
|
|
20
20
|
|
|
21
21
|
// Update current values
|
|
22
22
|
innerWidth.value = window.innerWidth
|
|
23
|
-
isMobile.value = window.innerWidth
|
|
23
|
+
isMobile.value = 768 > window.innerWidth
|
|
24
24
|
scrollY.value = window.scrollY
|
|
25
25
|
scrollX.value = window.scrollX
|
|
26
26
|
innerHeight.value = window.innerHeight
|
|
@@ -65,7 +65,7 @@ export function useExcel() {
|
|
|
65
65
|
const XLSX = await ensureXLSXLoaded()
|
|
66
66
|
|
|
67
67
|
const formattedData = formatData(data, schema)
|
|
68
|
-
const headers = schema.length
|
|
68
|
+
const headers = 0 < schema.length
|
|
69
69
|
? schema.map((sf) => {
|
|
70
70
|
const { id, label } = sf as unknown as Field<T>
|
|
71
71
|
return { v: (label as any) || (id as any), t: 's' }
|
|
@@ -73,7 +73,7 @@ export function useExcel() {
|
|
|
73
73
|
: []
|
|
74
74
|
const ws = XLSX.utils.json_to_sheet(formattedData)
|
|
75
75
|
|
|
76
|
-
if (headers.length
|
|
76
|
+
if (0 < headers.length) {
|
|
77
77
|
XLSX.utils.sheet_add_aoa(ws, [headers.map(h => h.v)], { origin: 'A1' })
|
|
78
78
|
}
|
|
79
79
|
|
|
@@ -124,7 +124,7 @@ export function useExcel() {
|
|
|
124
124
|
// Read the raw sheet data as arrays
|
|
125
125
|
const rawSheetData = XLSX.utils.sheet_to_json(worksheet, { header: 1 }) as any[][]
|
|
126
126
|
|
|
127
|
-
if (rawSheetData.length
|
|
127
|
+
if (0 === rawSheetData.length) {
|
|
128
128
|
return { headers: [], data: [] }
|
|
129
129
|
}
|
|
130
130
|
|
|
@@ -196,10 +196,10 @@ export function useExcel() {
|
|
|
196
196
|
// Helper function for date detection and conversion
|
|
197
197
|
function isExcelSerialDate(value: any): boolean {
|
|
198
198
|
return (
|
|
199
|
-
|
|
199
|
+
'number' === typeof value
|
|
200
200
|
&& Number.isInteger(value)
|
|
201
|
-
&& value
|
|
202
|
-
&& value
|
|
201
|
+
&& 20000 <= value
|
|
202
|
+
&& 50000 >= value
|
|
203
203
|
)
|
|
204
204
|
}
|
|
205
205
|
|
|
@@ -12,21 +12,17 @@ export function useFormField<T>(props: {
|
|
|
12
12
|
|
|
13
13
|
const fieldData = computed({
|
|
14
14
|
get: () => {
|
|
15
|
-
if (!props.fieldID || !formState) return props.modelValue ?? props.field.defaultValue ?? ''
|
|
15
|
+
if (!props.fieldID || !formState) {return props.modelValue ?? props.field.defaultValue ?? ''}
|
|
16
16
|
const value = formState.getFieldData(props.fieldID)
|
|
17
17
|
// For nested form containers, default to empty object
|
|
18
|
-
if (props.field.$el
|
|
19
|
-
//
|
|
20
|
-
if ((value === undefined || value === null || value === '') && props.field.defaultValue !== undefined) {
|
|
21
|
-
formState.updateField(props.fieldID, props.field.defaultValue)
|
|
22
|
-
return props.field.defaultValue
|
|
23
|
-
}
|
|
18
|
+
if ('form' === props.field.$el && !value) {return {}}
|
|
19
|
+
// Don't auto-restore defaultValue - let user control their content
|
|
24
20
|
return value ?? ''
|
|
25
21
|
},
|
|
26
22
|
set: (val: any) => {
|
|
27
|
-
if (!props.fieldID || !formState) return
|
|
23
|
+
if (!props.fieldID || !formState) {return}
|
|
28
24
|
const currentValue = formState.getFieldData(props.fieldID)
|
|
29
|
-
if (JSON.stringify(val) === JSON.stringify(currentValue)) return
|
|
25
|
+
if (JSON.stringify(val) === JSON.stringify(currentValue)) {return}
|
|
30
26
|
|
|
31
27
|
if (props.field.onUpdate) {
|
|
32
28
|
props.field.onUpdate(val, currentValue)
|
|
@@ -25,13 +25,13 @@ export function usePolling(
|
|
|
25
25
|
const pollingId = ref<number | null>(null)
|
|
26
26
|
|
|
27
27
|
const isTabActive = () => {
|
|
28
|
-
return !pauseInBackground || document.visibilityState
|
|
28
|
+
return !pauseInBackground || 'visible' === document.visibilityState
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
// Stop polling permanently - cannot be resumed
|
|
32
32
|
const stopPolling = () => {
|
|
33
33
|
isPolling.value = false // Permanently set to false
|
|
34
|
-
if (pollingId.value
|
|
34
|
+
if (null !== pollingId.value) {
|
|
35
35
|
clearTimeout(pollingId.value)
|
|
36
36
|
pollingId.value = null
|
|
37
37
|
}
|
|
@@ -39,7 +39,7 @@ export function usePolling(
|
|
|
39
39
|
|
|
40
40
|
// Pause polling temporarily - can be resumed
|
|
41
41
|
const pausePolling = () => {
|
|
42
|
-
if (pollingId.value
|
|
42
|
+
if (null !== pollingId.value) {
|
|
43
43
|
clearTimeout(pollingId.value)
|
|
44
44
|
pollingId.value = null
|
|
45
45
|
}
|
|
@@ -49,7 +49,7 @@ export function usePolling(
|
|
|
49
49
|
// Start polling with intelligent checks
|
|
50
50
|
const startPolling = () => {
|
|
51
51
|
// Clear any existing polling timeout
|
|
52
|
-
if (pollingId.value
|
|
52
|
+
if (null !== pollingId.value) {
|
|
53
53
|
clearTimeout(pollingId.value)
|
|
54
54
|
pollingId.value = null
|
|
55
55
|
}
|
|
@@ -70,13 +70,13 @@ export function usePolling(
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
const resumePolling = () => {
|
|
73
|
-
if (isPolling.value) startPolling()
|
|
74
|
-
else console.warn('Cannot resume polling that was stopped')
|
|
73
|
+
if (isPolling.value) {startPolling()}
|
|
74
|
+
else {console.warn('Cannot resume polling that was stopped')}
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
function updateVisibility() {
|
|
78
|
-
if (document.visibilityState
|
|
79
|
-
if (isPolling.value) startPolling()
|
|
78
|
+
if ('visible' === document.visibilityState) {
|
|
79
|
+
if (isPolling.value) {startPolling()}
|
|
80
80
|
} else if (pauseInBackground) {
|
|
81
81
|
pausePolling()
|
|
82
82
|
}
|
|
@@ -40,19 +40,19 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
40
40
|
|
|
41
41
|
// Helper function to render objects recursively
|
|
42
42
|
function renderObject(obj: T, depth = 0): string {
|
|
43
|
-
if (
|
|
44
|
-
if (typeof obj
|
|
45
|
-
if (Array.isArray(obj)) return obj.map(item => renderObject(item, depth + 1)).join(', ')
|
|
43
|
+
if (null === obj || obj === undefined) {return ''}
|
|
44
|
+
if ('object' !== typeof obj) {return String(obj)}
|
|
45
|
+
if (Array.isArray(obj)) {return obj.map(item => renderObject(item, depth + 1)).join(', ')}
|
|
46
46
|
|
|
47
47
|
// For objects, format as key: value pairs
|
|
48
|
-
const indent =
|
|
48
|
+
const indent = 0 < depth ? ' '.repeat(depth) : ''
|
|
49
49
|
const nextIndent = ' '.repeat(depth + 1)
|
|
50
50
|
|
|
51
51
|
const entries = Object.entries(obj)
|
|
52
|
-
if (entries.length
|
|
52
|
+
if (0 === entries.length) {return '{}'}
|
|
53
53
|
|
|
54
54
|
// For nested objects, format with newlines and indentation
|
|
55
|
-
if (
|
|
55
|
+
if (0 < depth) {
|
|
56
56
|
return `{\n${entries
|
|
57
57
|
.map(([key, value]) => `${nextIndent}${key}: ${renderObject(value, depth + 1)}`)
|
|
58
58
|
.join(',\n')}\n${indent}}`
|
|
@@ -61,7 +61,7 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
61
61
|
// For top-level objects, format as a flat list
|
|
62
62
|
return entries
|
|
63
63
|
.map(([key, value]) => {
|
|
64
|
-
const valueStr = typeof value
|
|
64
|
+
const valueStr = 'object' === typeof value && null !== value
|
|
65
65
|
? renderObject(value, depth + 1)
|
|
66
66
|
: String(value)
|
|
67
67
|
return `${key}: ${valueStr}`
|
|
@@ -90,18 +90,18 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
90
90
|
email: EmailInput
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
if (field.$el
|
|
93
|
+
if ('textarea' === field.$el && !field.attrs?.multiline) {
|
|
94
94
|
field.attrs = { ...field.attrs, multiline: true }
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
return typeof field.$el
|
|
97
|
+
return 'object' === typeof field.$el
|
|
98
98
|
? field.$el
|
|
99
99
|
: (componentMap[field.$el as keyof typeof componentMap] ?? field.$el ?? 'div')
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
function renderChild(child: SchemaChild<T, Path<T>>, slots?: BaseBagelField<T, Path<T>>['slots']) {
|
|
103
|
-
if (typeof child
|
|
104
|
-
if (isVNode(child)) return child
|
|
103
|
+
if ('string' === typeof child) {return child}
|
|
104
|
+
if (isVNode(child)) {return child}
|
|
105
105
|
return renderField(
|
|
106
106
|
child as BaseBagelField<T, Path<T>>,
|
|
107
107
|
slots
|
|
@@ -113,14 +113,14 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
113
113
|
slots?: BaseBagelField<T, Path<T>>['slots']
|
|
114
114
|
): VNode | undefined {
|
|
115
115
|
const Component = getComponent(field as Field<T>)
|
|
116
|
-
if (!Component) return
|
|
116
|
+
if (!Component) {return}
|
|
117
117
|
|
|
118
118
|
const rowData = (getFormData?.() || {}) as T | undefined
|
|
119
119
|
|
|
120
120
|
// Check vIf condition first
|
|
121
121
|
const condition = field.vIf ?? field['v-if']
|
|
122
122
|
if (condition !== undefined) {
|
|
123
|
-
if (typeof condition
|
|
123
|
+
if ('function' === typeof condition) {
|
|
124
124
|
// Compute currentValue for the vIf check
|
|
125
125
|
const vIfCurrentValue = field.id
|
|
126
126
|
? ('get' in (rowData || {})
|
|
@@ -134,7 +134,7 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
134
134
|
if (!vIfResult) {
|
|
135
135
|
return
|
|
136
136
|
}
|
|
137
|
-
} else if (typeof condition
|
|
137
|
+
} else if ('string' === typeof condition) {
|
|
138
138
|
if (!getNestedValue(rowData, condition)) {
|
|
139
139
|
return
|
|
140
140
|
}
|
|
@@ -156,6 +156,7 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
156
156
|
label,
|
|
157
157
|
placeholder,
|
|
158
158
|
disabled,
|
|
159
|
+
defaultValue,
|
|
159
160
|
...fieldProps
|
|
160
161
|
} = field
|
|
161
162
|
|
|
@@ -177,9 +178,9 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
177
178
|
const boundFieldProps = bindAttrs(fieldProps as Attributes<T, Path<T>> | undefined, currentValue, rowData)
|
|
178
179
|
|
|
179
180
|
// Check if this component should receive value as slot
|
|
180
|
-
const isSlotValueComponent = typeof Component
|
|
181
|
+
const isSlotValueComponent = 'string' === typeof Component && SLOT_VALUE_COMPONENTS.has(Component)
|
|
181
182
|
// Check if this component should receive value as src
|
|
182
|
-
const isSrcValueComponent = typeof Component
|
|
183
|
+
const isSrcValueComponent = 'string' === typeof Component && SRC_VALUE_COMPONENTS.has(Component)
|
|
183
184
|
|
|
184
185
|
const props: { [key: string]: any } = {
|
|
185
186
|
...boundFieldProps,
|
|
@@ -191,10 +192,24 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
191
192
|
id,
|
|
192
193
|
getFormData,
|
|
193
194
|
onUpdate,
|
|
195
|
+
defaultValue,
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Special handling for FieldArray component to pass attrs.schema as schema prop
|
|
199
|
+
if (Component === FieldArray && field.attrs?.schema) {
|
|
200
|
+
props.schema = field.attrs.schema
|
|
201
|
+
}
|
|
202
|
+
// Special handling for FieldArray component to pass attrs.type as type prop
|
|
203
|
+
if (Component === FieldArray && field.attrs?.type) {
|
|
204
|
+
props.type = field.attrs.type
|
|
205
|
+
}
|
|
206
|
+
// Special handling for FieldArray component to pass collapsed prop
|
|
207
|
+
if (Component === FieldArray && 'collapsed' in field) {
|
|
208
|
+
props.collapsed = (field as any).collapsed
|
|
194
209
|
}
|
|
195
210
|
|
|
196
211
|
// Wire top-level onClick with conditional args
|
|
197
|
-
if (typeof (field as any).onClick
|
|
212
|
+
if ('function' === typeof (field as any).onClick) {
|
|
198
213
|
const original = (field as any).onClick as (val?: any, row?: T) => void
|
|
199
214
|
props.onClick = () => {
|
|
200
215
|
if (id) {
|
|
@@ -206,7 +221,7 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
206
221
|
}
|
|
207
222
|
|
|
208
223
|
// For form mode, always use the original value for modelValue
|
|
209
|
-
if (
|
|
224
|
+
if ('form' === mode) {
|
|
210
225
|
props.modelValue = currentValue
|
|
211
226
|
props['onUpdate:modelValue'] = (value: any) => {
|
|
212
227
|
onUpdateModelValue?.(field, value)
|
|
@@ -233,7 +248,7 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
233
248
|
if (field.options) {
|
|
234
249
|
if (Array.isArray(field.options)) {
|
|
235
250
|
props.options = field.options
|
|
236
|
-
} else if (typeof field.options
|
|
251
|
+
} else if ('function' === typeof field.options) {
|
|
237
252
|
const fn = field.options as any
|
|
238
253
|
// Component-aware mapping
|
|
239
254
|
if (Component === SelectInput) {
|
|
@@ -241,18 +256,18 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
241
256
|
const row = getFormData?.()
|
|
242
257
|
const val = currentValue
|
|
243
258
|
// If author expects (query) only, call directly
|
|
244
|
-
if (typeof fn
|
|
259
|
+
if ('function' === typeof fn && 1 === fn.length) {
|
|
245
260
|
return fn(query)
|
|
246
261
|
}
|
|
247
262
|
// If author expects (query, val, row), pass it directly
|
|
248
|
-
if (typeof fn
|
|
263
|
+
if ('function' === typeof fn && 3 <= fn.length) {
|
|
249
264
|
return fn(query, val, row)
|
|
250
265
|
}
|
|
251
266
|
// Otherwise evaluate (val,row) → array | (query)=>Promise | Promise
|
|
252
267
|
const out = fn(val, row)
|
|
253
|
-
if (Array.isArray(out)) return out
|
|
254
|
-
if (typeof out
|
|
255
|
-
if (out && typeof out.then
|
|
268
|
+
if (Array.isArray(out)) {return out}
|
|
269
|
+
if ('function' === typeof out) {return out(query)}
|
|
270
|
+
if (out && 'function' === typeof out.then) {return out}
|
|
256
271
|
return []
|
|
257
272
|
}
|
|
258
273
|
} else {
|
|
@@ -261,10 +276,10 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
261
276
|
const row = getFormData?.()
|
|
262
277
|
const val = currentValue
|
|
263
278
|
const out = fn(val, row)
|
|
264
|
-
if (Array.isArray(out)) return out
|
|
265
|
-
if (typeof out
|
|
266
|
-
if (out && typeof out.then
|
|
267
|
-
if (fn.length
|
|
279
|
+
if (Array.isArray(out)) {return out}
|
|
280
|
+
if ('function' === typeof out) {return await out('')}
|
|
281
|
+
if (out && 'function' === typeof out.then) {return await out}
|
|
282
|
+
if (3 <= fn.length) {return await fn('', val, row)}
|
|
268
283
|
return []
|
|
269
284
|
}
|
|
270
285
|
}
|
|
@@ -278,10 +293,10 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
278
293
|
const boundAttrs = bindAttrs(field.attrs, currentValue, rowData)
|
|
279
294
|
Object.entries(boundAttrs).forEach(([key, value]) => {
|
|
280
295
|
// Skip $el as it's not a DOM attribute
|
|
281
|
-
if (
|
|
296
|
+
if ('$el' === key) {return}
|
|
282
297
|
|
|
283
|
-
if (typeof value
|
|
284
|
-
if (
|
|
298
|
+
if ('function' === typeof value) {
|
|
299
|
+
if ('onClick' === key) {
|
|
285
300
|
const original = value as (val?: any, row?: T) => void
|
|
286
301
|
props.onClick = () => {
|
|
287
302
|
if (id) {
|
|
@@ -309,7 +324,7 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
309
324
|
const componentSlots: Parameters<typeof h>[1] = {}
|
|
310
325
|
|
|
311
326
|
// Add default slot if there are children
|
|
312
|
-
if (children && children.length
|
|
327
|
+
if (children && 0 < children.length) {
|
|
313
328
|
componentSlots.default = () => children
|
|
314
329
|
.map(child => renderChild(child, slots))
|
|
315
330
|
.filter(Boolean) // Filter out null results from vIf
|
|
@@ -327,7 +342,7 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
327
342
|
if (Array.isArray(slot)) {
|
|
328
343
|
// Handle BglFormSchemaT array
|
|
329
344
|
return slot.map((schemaField) => {
|
|
330
|
-
if (typeof schemaField
|
|
345
|
+
if ('function' === typeof schemaField) {
|
|
331
346
|
// Handle function slot
|
|
332
347
|
const slotFn = schemaField
|
|
333
348
|
return slotFn({ row: rowData, field })
|
|
@@ -354,19 +369,19 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
354
369
|
// ? (slots[field.id])({ row: rowData, field })
|
|
355
370
|
// : undefined
|
|
356
371
|
|
|
357
|
-
if (
|
|
372
|
+
if ('preview' === mode) {
|
|
358
373
|
// Skip rendering if value is unset and includeUnset is false
|
|
359
|
-
if (!includeUnset && (transformedValue === undefined ||
|
|
360
|
-
|| (typeof transformedValue
|
|
374
|
+
if (!includeUnset && (transformedValue === undefined || null === transformedValue
|
|
375
|
+
|| ('string' === typeof transformedValue && 0 === transformedValue.length))) {
|
|
361
376
|
return
|
|
362
377
|
}
|
|
363
378
|
|
|
364
379
|
return h('div', { class: 'preview-field' }, [
|
|
365
380
|
h('div', { class: 'field-label' }, `${field.label || keyToLabel(field.id || '')}:`),
|
|
366
381
|
h('div', { class: 'field-value' }, [
|
|
367
|
-
slotContent || (typeof field.$el
|
|
382
|
+
slotContent || ('object' === typeof field.$el
|
|
368
383
|
? h(Component as any, props, componentSlots)
|
|
369
|
-
: typeof transformedValue
|
|
384
|
+
: 'object' === typeof transformedValue && null !== transformedValue
|
|
370
385
|
? h('pre', {
|
|
371
386
|
style: 'margin: 0; white-space: pre-wrap; font-family: inherit; font-size: inherit;'
|
|
372
387
|
}, renderObject(transformedValue))
|
|
@@ -50,17 +50,17 @@ function applyTheme(themeValue: string) {
|
|
|
50
50
|
|
|
51
51
|
// Remove all theme classes
|
|
52
52
|
themeOptions.value.forEach((t) => {
|
|
53
|
-
if (t.class
|
|
53
|
+
if ('system' !== t.class) {
|
|
54
54
|
root.classList.remove(t.class)
|
|
55
55
|
}
|
|
56
56
|
})
|
|
57
57
|
|
|
58
58
|
// Handle system theme
|
|
59
|
-
if (
|
|
59
|
+
if ('system' === themeValue) {
|
|
60
60
|
const systemIsDark = getSystemPrefersDark()
|
|
61
61
|
isDark.value = systemIsDark
|
|
62
|
-
const darkTheme = themeOptions.value.find(t => t.value
|
|
63
|
-
const lightTheme = themeOptions.value.find(t => t.value
|
|
62
|
+
const darkTheme = themeOptions.value.find(t => 'dark' === t.value)
|
|
63
|
+
const lightTheme = themeOptions.value.find(t => 'light' === t.value)
|
|
64
64
|
const themeToApply = systemIsDark ? darkTheme : lightTheme
|
|
65
65
|
if (themeToApply) {
|
|
66
66
|
root.classList.add(themeToApply.class)
|
|
@@ -77,9 +77,9 @@ function applyTheme(themeValue: string) {
|
|
|
77
77
|
|
|
78
78
|
function toggleTheme() {
|
|
79
79
|
// Get all non-system themes
|
|
80
|
-
const cyclableThemes = themeOptions.value.filter(t => t.value
|
|
80
|
+
const cyclableThemes = themeOptions.value.filter(t => 'system' !== t.value)
|
|
81
81
|
|
|
82
|
-
if (cyclableThemes.length
|
|
82
|
+
if (0 === cyclableThemes.length) {return}
|
|
83
83
|
|
|
84
84
|
const currentIndex = cyclableThemes.findIndex(t => t.value === colorMode.value)
|
|
85
85
|
const nextIndex = (currentIndex + 1) % cyclableThemes.length
|
|
@@ -91,8 +91,8 @@ function addTheme(theme: ThemeOption) {
|
|
|
91
91
|
const exists = themeOptions.value.some(t => t.value === theme.value)
|
|
92
92
|
if (!exists) {
|
|
93
93
|
// Add before 'system' option
|
|
94
|
-
const systemIndex = themeOptions.value.findIndex(t => t.value
|
|
95
|
-
if (
|
|
94
|
+
const systemIndex = themeOptions.value.findIndex(t => 'system' === t.value)
|
|
95
|
+
if (-1 < systemIndex) {
|
|
96
96
|
themeOptions.value.splice(systemIndex, 0, theme)
|
|
97
97
|
} else {
|
|
98
98
|
themeOptions.value.push(theme)
|
|
@@ -130,7 +130,7 @@ export function useTheme() {
|
|
|
130
130
|
// React to system changes when in "system" mode
|
|
131
131
|
const mq = window.matchMedia('(prefers-color-scheme: dark)')
|
|
132
132
|
const handler = (e: MediaQueryListEvent) => {
|
|
133
|
-
if (colorMode.value
|
|
133
|
+
if ('system' === colorMode.value) {
|
|
134
134
|
applyTheme('system')
|
|
135
135
|
}
|
|
136
136
|
}
|
|
@@ -12,9 +12,9 @@ export function useValidateFieldValue(
|
|
|
12
12
|
inputVal,
|
|
13
13
|
(newVal, oldVal) => {
|
|
14
14
|
getInput?.()?.setCustomValidity('')
|
|
15
|
-
if (!validateFn || newVal === oldVal || !newVal) return
|
|
15
|
+
if (!validateFn || newVal === oldVal || !newVal) {return}
|
|
16
16
|
const isValid = validateFn(newVal, getFormData?.())
|
|
17
|
-
if (typeof isValid
|
|
17
|
+
if ('string' === typeof isValid) {getInput?.()?.setCustomValidity(isValid)}
|
|
18
18
|
},
|
|
19
19
|
{ debounce: 500 },
|
|
20
20
|
)
|