@bagelink/vue 0.0.1224 → 0.0.1232
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/dist/components/BglComponent.vue.d.ts.map +1 -1
- package/dist/components/Btn.vue.d.ts.map +1 -1
- package/dist/components/Calendar/components/week/DayEvent.vue.d.ts.map +1 -1
- package/dist/components/Spreadsheet/Index.vue.d.ts +1 -0
- package/dist/components/Spreadsheet/Index.vue.d.ts.map +1 -1
- package/dist/components/form/BagelForm.vue.d.ts +1 -0
- package/dist/components/form/BagelForm.vue.d.ts.map +1 -1
- package/dist/components/lightbox/Lightbox.vue.d.ts.map +1 -1
- package/dist/components/lightbox/lightbox.types.d.ts +8 -2
- package/dist/components/lightbox/lightbox.types.d.ts.map +1 -1
- package/dist/composables/useSchemaField.d.ts +9 -5
- package/dist/composables/useSchemaField.d.ts.map +1 -1
- package/dist/index.cjs +70 -38
- package/dist/index.mjs +71 -39
- package/dist/style.css +84 -81
- package/dist/types/BagelForm.d.ts +2 -1
- package/dist/types/BagelForm.d.ts.map +1 -1
- package/dist/utils/BagelFormUtils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Btn.vue +3 -0
- package/src/components/Calendar/components/week/DayEvent.vue +0 -1
- package/src/components/Spreadsheet/Index.vue +41 -20
- package/src/components/form/BagelForm.vue +6 -2
- package/src/components/lightbox/Lightbox.vue +5 -5
- package/src/components/lightbox/lightbox.types.ts +3 -2
- package/src/composables/useSchemaField.ts +32 -12
- package/src/types/BagelForm.ts +2 -1
- package/src/utils/BagelFormUtils.ts +2 -1
|
@@ -31,7 +31,7 @@ onMounted(() => {
|
|
|
31
31
|
}
|
|
32
32
|
})
|
|
33
33
|
|
|
34
|
-
const formState = ref<'success' | 'error' | 'idle'>('idle')
|
|
34
|
+
const formState = ref<'success' | 'error' | 'idle' | 'submitting'>('idle')
|
|
35
35
|
|
|
36
36
|
watch(() => props.modelValue, (newValue) => {
|
|
37
37
|
if (newValue !== undefined) {
|
|
@@ -60,9 +60,13 @@ function updateFormData(fieldId: string, value: any) {
|
|
|
60
60
|
|
|
61
61
|
async function handleSubmit() {
|
|
62
62
|
try {
|
|
63
|
+
if (formState.value === 'submitting') return
|
|
64
|
+
formState.value = 'submitting'
|
|
63
65
|
await props.onSubmit?.(formData.value)
|
|
64
66
|
initialFormData.value = structuredClone(formData.value)
|
|
65
67
|
formState.value = 'success'
|
|
68
|
+
// Notify parent window of successful submission
|
|
69
|
+
window.parent.postMessage({ type: 'BAGEL_FORM_SUCCESS', data: formData.value }, '*')
|
|
66
70
|
} catch (error) {
|
|
67
71
|
formState.value = 'error'
|
|
68
72
|
}
|
|
@@ -98,7 +102,7 @@ defineExpose({ form, isDirty, validateForm })
|
|
|
98
102
|
</template>
|
|
99
103
|
</template>
|
|
100
104
|
<slot v-else />
|
|
101
|
-
<slot name="submit" :submit="handleSubmit" :isDirty="isDirty" :validateForm="validateForm" />
|
|
105
|
+
<slot name="submit" :submit="handleSubmit" :isDirty="isDirty" :validateForm="validateForm" :formState="formState" />
|
|
102
106
|
<slot v-if="formState === 'success'" name="success" />
|
|
103
107
|
<slot v-if="formState === 'error'" name="error" />
|
|
104
108
|
</form>
|
|
@@ -100,13 +100,13 @@ defineExpose({ open, close })
|
|
|
100
100
|
<Btn flat class="color-white" icon="add" :disabled="zoom === 3" @click="zoom++" />
|
|
101
101
|
</div>
|
|
102
102
|
<Btn
|
|
103
|
-
v-if="currentItem?.openFile" class="color-white" round thin flat iconEnd="arrow_outward"
|
|
103
|
+
v-if="currentItem?.openFile && currentItem?.src" class="color-white" round thin flat iconEnd="arrow_outward"
|
|
104
104
|
value="Open File"
|
|
105
105
|
:href="currentItem?.src"
|
|
106
106
|
target="_blank"
|
|
107
107
|
/>
|
|
108
108
|
<Btn
|
|
109
|
-
v-if="currentItem?.download" class="color-white" round thin flat icon="download"
|
|
109
|
+
v-if="currentItem?.download && currentItem?.src" class="color-white" round thin flat icon="download"
|
|
110
110
|
value="Download File"
|
|
111
111
|
:href="upgradeHeaders(currentItem?.src)"
|
|
112
112
|
download
|
|
@@ -117,11 +117,11 @@ defineExpose({ open, close })
|
|
|
117
117
|
<Carousel v-model:index="currentIndex" :items="1" class="bgl-lightbox-item" :class="{ zoomed: zoom > 1 }" :freeDrag="zoom === 1">
|
|
118
118
|
<template v-for="item in group" :key="item.src">
|
|
119
119
|
<Zoomer v-if="item.type === 'image'" v-model:zoom="zoom" :disabled="!item?.enableZoom" :mouse-wheel-to-zoom="false">
|
|
120
|
-
<Image :draggable="false" :src="item?.src" alt="Preview" class="vw90 lightbox-image" />
|
|
120
|
+
<Image :draggable="false" :src="item?.src" :pathKey="item?.pathKey" alt="Preview" class="vw90 lightbox-image" />
|
|
121
121
|
</Zoomer>
|
|
122
122
|
|
|
123
123
|
<BglVideo
|
|
124
|
-
v-else-if="item?.type === 'video'"
|
|
124
|
+
v-else-if="item?.type === 'video' && item?.src"
|
|
125
125
|
:src="item?.src"
|
|
126
126
|
autoplay
|
|
127
127
|
controls
|
|
@@ -129,7 +129,7 @@ defineExpose({ open, close })
|
|
|
129
129
|
/>
|
|
130
130
|
|
|
131
131
|
<embed
|
|
132
|
-
v-else-if="item?.type === 'pdf'"
|
|
132
|
+
v-else-if="item?.type === 'pdf' && item?.src"
|
|
133
133
|
:src="normalizeURL(item?.src)"
|
|
134
134
|
type="application/pdf"
|
|
135
135
|
width="100%"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { VNode } from 'vue'
|
|
2
|
-
import type { BaseBagelField } from '../types/BagelForm'
|
|
2
|
+
import type { BaseBagelField, BglFormSchemaT } from '../types/BagelForm'
|
|
3
3
|
import {
|
|
4
4
|
TextInput,
|
|
5
5
|
NumberInput,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
classify,
|
|
18
18
|
keyToLabel
|
|
19
19
|
} from '@bagelink/vue'
|
|
20
|
-
import { h } from 'vue'
|
|
20
|
+
import { h, isVNode } from 'vue'
|
|
21
21
|
|
|
22
22
|
const SLOT_VALUE_COMPONENTS = new Set(['div', 'span', 'p'])
|
|
23
23
|
|
|
@@ -30,6 +30,12 @@ export interface UseSchemaFieldOptions<T> {
|
|
|
30
30
|
includeUnset?: boolean
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
// Add type for supported child types
|
|
34
|
+
type SupportedChild<T> = BaseBagelField<T> | string | VNode
|
|
35
|
+
interface SlotProps<T> { row: T, field: BaseBagelField<T> }
|
|
36
|
+
type SlotFunction<T> = (props: SlotProps<T>) => any
|
|
37
|
+
type SupportedSlot<T> = BglFormSchemaT<T> | VNode | SlotFunction<T>
|
|
38
|
+
|
|
33
39
|
export function useSchemaField<T extends { [key: string]: any }>(options: UseSchemaFieldOptions<T>) {
|
|
34
40
|
const { mode = 'form', getRowData, onUpdate, includeUnset = false } = options
|
|
35
41
|
|
|
@@ -57,9 +63,15 @@ export function useSchemaField<T extends { [key: string]: any }>(options: UseSch
|
|
|
57
63
|
return typeof field.$el === 'object' ? field.$el : componentMap[field.$el as keyof typeof componentMap] ?? field.$el ?? 'div'
|
|
58
64
|
}
|
|
59
65
|
|
|
66
|
+
function renderChild(child: SupportedChild<T>, slots?: Record<string, SupportedSlot<T>>): any {
|
|
67
|
+
if (typeof child === 'string') return child
|
|
68
|
+
if (isVNode(child)) return child
|
|
69
|
+
return renderField(child, slots)
|
|
70
|
+
}
|
|
71
|
+
|
|
60
72
|
function renderField(
|
|
61
73
|
field: BaseBagelField<T>,
|
|
62
|
-
slots?: Record<string,
|
|
74
|
+
slots?: Record<string, SupportedSlot<T>>
|
|
63
75
|
): VNode | null {
|
|
64
76
|
const Component = getComponent(field)
|
|
65
77
|
if (!Component) return null
|
|
@@ -169,10 +181,7 @@ export function useSchemaField<T extends { [key: string]: any }>(options: UseSch
|
|
|
169
181
|
// Add default slot if there are children
|
|
170
182
|
if (children?.length) {
|
|
171
183
|
componentSlots.default = () => children
|
|
172
|
-
.map(
|
|
173
|
-
if (typeof child === 'string') return child
|
|
174
|
-
return renderField(child, slots)
|
|
175
|
-
})
|
|
184
|
+
.map(child => renderChild(child, slots))
|
|
176
185
|
.filter(Boolean) // Filter out null results from vIf
|
|
177
186
|
}
|
|
178
187
|
|
|
@@ -181,18 +190,29 @@ export function useSchemaField<T extends { [key: string]: any }>(options: UseSch
|
|
|
181
190
|
componentSlots.default = () => transformedValue?.toString() || ''
|
|
182
191
|
}
|
|
183
192
|
|
|
184
|
-
//
|
|
193
|
+
// Handle custom slots from the field
|
|
185
194
|
if (fieldSlots) {
|
|
186
195
|
Object.entries(fieldSlots).forEach(([name, slot]) => {
|
|
187
|
-
componentSlots[name] =
|
|
188
|
-
|
|
189
|
-
|
|
196
|
+
componentSlots[name] = () => {
|
|
197
|
+
if (Array.isArray(slot)) {
|
|
198
|
+
// Handle BglFormSchemaT array
|
|
199
|
+
return slot.map(schemaField => renderField(schemaField as BaseBagelField<T>, slots))
|
|
200
|
+
} else if (isVNode(slot)) {
|
|
201
|
+
// Handle VNode
|
|
202
|
+
return slot
|
|
203
|
+
} else if (typeof slot === 'function') {
|
|
204
|
+
// Handle function slot
|
|
205
|
+
const slotFn = slot as (props: SlotProps<T>) => any
|
|
206
|
+
return slotFn({ row: rowData, field })
|
|
207
|
+
}
|
|
208
|
+
return slot
|
|
209
|
+
}
|
|
190
210
|
})
|
|
191
211
|
}
|
|
192
212
|
|
|
193
213
|
// Handle custom slot content from parent
|
|
194
214
|
const slotContent = field.id && slots?.[field.id]
|
|
195
|
-
? slots[field.id]({ row: rowData, field })
|
|
215
|
+
? (slots[field.id] as SlotFunction<T>)({ row: rowData, field })
|
|
196
216
|
: undefined
|
|
197
217
|
|
|
198
218
|
if (mode === 'preview') {
|
package/src/types/BagelForm.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SelectInput, TextInput } from '@bagelink/vue'
|
|
2
|
+
import type { VNode } from 'vue'
|
|
2
3
|
|
|
3
4
|
export type AttributeValue = string | number | boolean | undefined | undefined | { [key: string]: any }
|
|
4
5
|
|
|
@@ -29,7 +30,7 @@ export interface BaseBagelField<T = { [key: string]: any }> {
|
|
|
29
30
|
'id'?: keyof T extends string ? keyof T : string
|
|
30
31
|
'label'?: string
|
|
31
32
|
'placeholder'?: string
|
|
32
|
-
'children'?: (Field<T> | string)[]
|
|
33
|
+
'children'?: (Field<T> | string | VNode)[]
|
|
33
34
|
'class'?: AttributeValue | AttributeFn<T>
|
|
34
35
|
'attrs'?: Attributes<T>
|
|
35
36
|
'required'?: boolean
|
|
@@ -235,7 +235,8 @@ export function findBglFieldById(id: string, _schema: BglFormSchemaT): Field | u
|
|
|
235
235
|
for (const field of _schema) {
|
|
236
236
|
if (field.id === id) return field
|
|
237
237
|
if (field.children && Number(field.children.length) > 0) {
|
|
238
|
-
const
|
|
238
|
+
const fieldChildren = field.children.filter((c): c is Field => typeof c === 'object' && '$el' in c)
|
|
239
|
+
const child = findBglFieldById(id, fieldChildren)
|
|
239
240
|
if (child) return child
|
|
240
241
|
}
|
|
241
242
|
}
|