@bagelink/vue 1.14.13 → 1.15.0
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/AddressSearch.vue.d.ts +6 -7
- package/dist/components/Alert.vue.d.ts.map +1 -1
- package/dist/components/Avatar.vue.d.ts.map +1 -1
- package/dist/components/Badge.vue.d.ts.map +1 -1
- package/dist/components/Btn.vue.d.ts +1 -1
- package/dist/components/Btn.vue.d.ts.map +1 -1
- package/dist/components/Card.vue.d.ts.map +1 -1
- package/dist/components/Carousel.vue.d.ts +0 -11
- package/dist/components/Dropdown.vue.d.ts +0 -2
- package/dist/components/Dropdown.vue.d.ts.map +1 -1
- package/dist/components/Filter.vue.d.ts +30 -0
- package/dist/components/Filter.vue.d.ts.map +1 -0
- package/dist/components/FilterQuery.vue.d.ts +8 -3
- package/dist/components/Image.vue.d.ts.map +1 -1
- package/dist/components/ImportData.vue.d.ts.map +1 -1
- package/dist/components/ListItem.vue.d.ts.map +1 -1
- package/dist/components/MapEmbed/Index.vue.d.ts.map +1 -1
- package/dist/components/Modal.vue.d.ts +0 -1
- package/dist/components/Pagination.vue.d.ts.map +1 -1
- package/dist/components/Pill.vue.d.ts.map +1 -1
- package/dist/components/QueryFilter.vue.d.ts +30 -0
- package/dist/components/QueryFilter.vue.d.ts.map +1 -0
- package/dist/components/Swiper.vue.d.ts +6 -12
- package/dist/components/Swiper.vue.d.ts.map +1 -1
- package/dist/components/Toast.vue.d.ts.map +1 -1
- package/dist/components/analytics/PieChart.vue.d.ts +2 -2
- package/dist/components/calendar/CalendarPopover.vue.d.ts +8 -4
- package/dist/components/calendar/CalendarPopover.vue.d.ts.map +1 -1
- package/dist/components/calendar/CalendarTypes.d.ts +0 -10
- package/dist/components/calendar/Index.vue.d.ts +4 -20
- package/dist/components/calendar/views/WeekView.vue.d.ts +1 -9
- package/dist/components/dataTable/DataTable.vue.d.ts.map +1 -1
- package/dist/components/form/index.d.ts.map +1 -1
- package/dist/components/form/inputs/ArrayInput.vue.d.ts +2 -4
- package/dist/components/form/inputs/CheckInput.vue.d.ts +1 -2
- package/dist/components/form/inputs/Checkbox.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/CodeEditor/Index.vue.d.ts +0 -54
- package/dist/components/form/inputs/ColorInput.vue.d.ts +1 -3
- package/dist/components/form/inputs/DateInput.vue.d.ts +1 -2
- package/dist/components/form/inputs/DatePicker.vue.d.ts +0 -1
- package/dist/components/form/inputs/EmailInput.vue.d.ts +2 -5
- package/dist/components/form/inputs/JSONInput.vue.d.ts +1 -2
- package/dist/components/form/inputs/MarkdownEditor.vue.d.ts +2 -7
- package/dist/components/form/inputs/NumberInput.vue.d.ts +1 -2
- package/dist/components/form/inputs/OTP.vue.d.ts +1 -2
- package/dist/components/form/inputs/PasswordInput.vue.d.ts +10 -16
- package/dist/components/form/inputs/RadioGroup.vue.d.ts +1 -3
- package/dist/components/form/inputs/RangeInput.vue.d.ts +1 -6
- package/dist/components/form/inputs/RichText/index.vue.d.ts +1 -2
- package/dist/components/form/inputs/RichText/index.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RichText/utils/media.d.ts.map +1 -1
- package/dist/components/form/inputs/SelectBtn.vue.d.ts +2 -2
- package/dist/components/form/inputs/SelectInput.vue.d.ts +13 -20
- package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/SignaturePad.vue.d.ts +1 -6
- package/dist/components/form/inputs/TableField.vue.d.ts +1 -2
- package/dist/components/form/inputs/TelInput.vue.d.ts +1 -2
- package/dist/components/form/inputs/TextInput.vue.d.ts +2 -3
- package/dist/components/form/inputs/ToggleInput.vue.d.ts +1 -2
- package/dist/components/form/inputs/Upload/UploadInput.vue.d.ts +6 -27
- package/dist/components/form/inputs/Upload/upload.d.ts +1 -1
- package/dist/components/form/inputs/index.d.ts +0 -1
- package/dist/components/index.d.ts +1 -3
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/layout/AppContent.vue.d.ts +1 -1
- package/dist/components/layout/AppContent.vue.d.ts.map +1 -1
- package/dist/components/layout/AppLayout.vue.d.ts +0 -2
- package/dist/components/layout/AppLayout.vue.d.ts.map +1 -1
- package/dist/components/layout/AppSidebar.vue.d.ts +1 -5
- package/dist/components/layout/AppSidebar.vue.d.ts.map +1 -1
- package/dist/components/layout/Panel.vue.d.ts.map +1 -1
- package/dist/components/layout/Resizable.vue.d.ts.map +1 -1
- package/dist/components/layout/Skeleton.vue.d.ts.map +1 -1
- package/dist/components/layout/TabsNav.vue.d.ts +1 -12
- package/dist/components/layout/TabsNav.vue.d.ts.map +1 -1
- package/dist/components/layout/appLayoutContext.d.ts +24 -0
- package/dist/components/layout/appLayoutContext.d.ts.map +1 -0
- package/dist/components/layout/index.d.ts.map +1 -1
- package/dist/components/lightbox/Lightbox.vue.d.ts.map +1 -1
- package/dist/composables/index.d.ts.map +1 -1
- package/dist/composables/useDevice.d.ts.map +1 -1
- package/dist/composables/useEscapeKey.d.ts +12 -0
- package/dist/composables/useEscapeKey.d.ts.map +1 -0
- package/dist/composables/useSchemaField.d.ts.map +1 -1
- package/dist/composables/useTheme.d.ts.map +1 -1
- package/dist/dialog/Dialog.vue.d.ts.map +1 -1
- package/dist/dialog/DialogConfirm.vue.d.ts.map +1 -1
- package/dist/form-flow/FormFlow.vue.d.ts.map +1 -1
- package/dist/form-flow/MultiStepForm.vue.d.ts +1 -6
- package/dist/form-flow/form-flow.d.ts +1 -24
- package/dist/form-flow/form-flow.d.ts.map +1 -1
- package/dist/i18n/index.d.ts +0 -838
- package/dist/index.cjs +245 -222
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +42201 -51162
- package/dist/plugins/bagel.d.ts.map +1 -1
- package/dist/style.css +1 -2
- package/dist/types/BagelForm.d.ts +1 -10
- package/dist/types/BagelForm.d.ts.map +1 -1
- package/dist/types/BtnOptions.d.ts.map +1 -1
- package/dist/types/NavLink.d.ts +1 -2
- package/dist/types/TableSchema.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/BagelFormUtils.d.ts +0 -1
- package/dist/utils/calendar/dateUtils.d.ts +2 -2
- package/dist/utils/calendar/dateUtils.d.ts.map +1 -1
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/date.d.ts +116 -0
- package/dist/utils/date.d.ts.map +1 -0
- package/dist/utils/fetch.d.ts +29 -0
- package/dist/utils/fetch.d.ts.map +1 -0
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/string.d.ts +7 -0
- package/dist/utils/string.d.ts.map +1 -0
- package/dist/utils/useSearch.d.ts +1 -1
- package/package.json +3 -10
- package/src/components/AccordionItem.vue +5 -5
- package/src/components/Alert.vue +37 -16
- package/src/components/Avatar.vue +2 -1
- package/src/components/Badge.vue +145 -22
- package/src/components/BglVideo.vue +4 -4
- package/src/components/Btn.vue +81 -69
- package/src/components/Card.vue +7 -6
- package/src/components/Dropdown.vue +7 -14
- package/src/components/FieldSetVue.vue +2 -2
- package/src/components/FilterQuery.vue +3 -3
- package/src/components/Image.vue +5 -3
- package/src/components/JSONSchema.vue +4 -4
- package/src/components/JsonBuilder.vue +3 -3
- package/src/components/ListItem.vue +2 -4
- package/src/components/MapEmbed/Index.vue +18 -17
- package/src/components/NavBar.vue +2 -2
- package/src/components/Spreadsheet/Index.vue +4 -4
- package/src/components/Spreadsheet/SpreadsheetTable.vue +10 -10
- package/src/components/Swiper.vue +3 -1
- package/src/components/Toast.vue +57 -36
- package/src/components/calendar/CalendarPopover.vue +1 -1
- package/src/components/calendar/Index.vue +5 -5
- package/src/components/calendar/views/AgendaView.vue +2 -2
- package/src/components/calendar/views/DayView.vue +1 -1
- package/src/components/calendar/views/MonthView.vue +8 -8
- package/src/components/dataTable/DataTable.vue +68 -10
- package/src/components/form/index.ts +0 -4
- package/src/components/form/inputs/ArrayInput.vue +1 -1
- package/src/components/form/inputs/CheckInput.vue +6 -6
- package/src/components/form/inputs/Checkbox.vue +5 -4
- package/src/components/form/inputs/CodeEditor/Index.vue +1 -1
- package/src/components/form/inputs/ColorInput.vue +5 -5
- package/src/components/form/inputs/DatePicker.vue +3 -3
- package/src/components/form/inputs/EmailInput.vue +15 -15
- package/src/components/form/inputs/NumberInput.vue +11 -11
- package/src/components/form/inputs/OTP.vue +4 -4
- package/src/components/form/inputs/PasswordInput.vue +3 -3
- package/src/components/form/inputs/RadioGroup.vue +1 -1
- package/src/components/form/inputs/RichText/editor.css +4 -4
- package/src/components/form/inputs/RichText/index.vue +39 -39
- package/src/components/form/inputs/RichText/utils/media.ts +1 -92
- package/src/components/form/inputs/RichText/utils/table.ts +4 -4
- package/src/components/form/inputs/SelectBtn.vue +1 -1
- package/src/components/form/inputs/SelectInput.vue +16 -16
- package/src/components/form/inputs/SignaturePad.vue +6 -6
- package/src/components/form/inputs/TableField.vue +7 -7
- package/src/components/form/inputs/TelInput.vue +12 -12
- package/src/components/form/inputs/TextInput.vue +11 -11
- package/src/components/form/inputs/ToggleInput.vue +11 -11
- package/src/components/form/inputs/Upload/upload.css +16 -16
- package/src/components/index.ts +2 -9
- package/src/components/layout/AppContent.vue +5 -19
- package/src/components/layout/AppLayout.vue +47 -18
- package/src/components/layout/AppSidebar.vue +19 -36
- package/src/components/layout/BottomMenu.vue +1 -1
- package/src/components/layout/Resizable.vue +5 -2
- package/src/components/layout/Skeleton.vue +5 -4
- package/src/components/layout/TabsNav.vue +23 -23
- package/src/components/layout/appLayoutContext.ts +44 -0
- package/src/components/layout/index.ts +2 -0
- package/src/components/lightbox/Lightbox.vue +3 -9
- package/src/composables/index.ts +1 -0
- package/src/composables/useDevice.ts +2 -1
- package/src/composables/useEscapeKey.ts +56 -0
- package/src/composables/useSchemaField.ts +2 -17
- package/src/composables/useTheme.ts +23 -19
- package/src/form-flow/FormFlow.vue +2 -0
- package/src/form-flow/form-flow.ts +7 -0
- package/src/index.ts +0 -3
- package/src/plugins/bagel.ts +0 -15
- package/src/styles/app-layout.css +231 -0
- package/src/styles/appearance.css +179 -21
- package/src/styles/bagel.css +103 -97
- package/src/styles/buttons.css +8 -8
- package/src/styles/colors.css +0 -103
- package/src/styles/dark.css +25 -26
- package/src/styles/input-variants.css +11 -11
- package/src/styles/inputs.css +44 -61
- package/src/styles/layout.css +445 -1258
- package/src/styles/loginCard.css +1 -1
- package/src/styles/mobilLayout.css +153 -28
- package/src/styles/text.css +500 -1508
- package/src/styles/theme.css +199 -435
- package/src/styles/transitions.css +4 -4
- package/src/types/BagelForm.ts +46 -151
- package/src/types/BtnOptions.ts +5 -3
- package/src/types/TableSchema.ts +1 -0
- package/src/types/index.ts +0 -5
- package/src/utils/calendar/dateUtils.ts +2 -3
- package/src/utils/constants.ts +7 -0
- package/src/utils/date.ts +482 -0
- package/src/utils/fetch.ts +128 -0
- package/src/utils/index.ts +54 -3
- package/src/utils/sizeParsing.ts +5 -5
- package/src/utils/string.ts +56 -0
- package/vite.config.ts +5 -1
- package/bin/generateFormSchema.ts +0 -1035
- package/bin/utils.ts +0 -223
- package/src/components/Carousel.vue +0 -724
- package/src/components/ImportData.vue +0 -1749
- package/src/components/Modal.vue +0 -184
- package/src/components/ModalConfirm.vue +0 -42
- package/src/components/ModalForm.vue +0 -102
- package/src/components/Pill.vue +0 -149
- package/src/components/Slider.vue +0 -1446
- package/src/components/Title.vue +0 -23
- package/src/components/ToolBar.vue +0 -9
- package/src/components/form/BagelForm.vue +0 -219
- package/src/components/form/BglFieldSet.vue +0 -14
- package/src/components/form/BglMultiStepForm.vue +0 -469
- package/src/components/form/FieldArray.vue +0 -422
- package/src/components/form/useBagelFormState.ts +0 -76
- package/src/composables/useFormField.ts +0 -38
- package/src/dialog/DialogOLD.vue +0 -358
- package/src/plugins/modalTypes.ts +0 -61
- package/src/plugins/useModal.ts +0 -225
- package/src/styles/modal.css +0 -120
- package/src/styles/pillColors.css +0 -0
- package/src/utils/BagelFormUtils.ts +0 -684
|
@@ -1,469 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts" generic="T extends {[key:string]:any}, P extends Path<T>">
|
|
2
|
-
import type { BglFormSchemaT, Path } from '@bagelink/vue'
|
|
3
|
-
|
|
4
|
-
import type { MaybeRefOrGetter } from 'vue'
|
|
5
|
-
import type { ComponentExposed, ComponentProps } from 'vue-component-type-helpers'
|
|
6
|
-
import { BagelForm, Btn, useBglSchema, sleep } from '@bagelink/vue'
|
|
7
|
-
import { ref, watch, computed, nextTick, toValue } from 'vue'
|
|
8
|
-
|
|
9
|
-
const props = withDefaults(
|
|
10
|
-
defineProps<{
|
|
11
|
-
bagelFormProps?: Omit<
|
|
12
|
-
ComponentProps<typeof BagelForm<T, P>>,
|
|
13
|
-
(
|
|
14
|
-
'schema' | `${string}modelValue` | `ref${string}` | `onVnode${string}` | 'onSubmit'
|
|
15
|
-
)
|
|
16
|
-
>
|
|
17
|
-
schema?: MaybeRefOrGetter<BglFormSchemaT<T>>
|
|
18
|
-
showProgress?: boolean
|
|
19
|
-
rtl?: boolean
|
|
20
|
-
stepLabels?: string[]
|
|
21
|
-
allowStepNavigation?: boolean
|
|
22
|
-
validateOnSteps?: boolean
|
|
23
|
-
/** Animation direction - auto detects based on step change or can be forced */
|
|
24
|
-
direction?: 'auto' | 'left' | 'right'
|
|
25
|
-
}>(),
|
|
26
|
-
{
|
|
27
|
-
bagelFormProps: () => ({}),
|
|
28
|
-
showProgress: false,
|
|
29
|
-
rtl: false,
|
|
30
|
-
allowStepNavigation: false,
|
|
31
|
-
validateOnSteps: true,
|
|
32
|
-
direction: 'auto'
|
|
33
|
-
}
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
const emits = defineEmits(['submit', 'stepChange'])
|
|
37
|
-
|
|
38
|
-
type BagelFormT = ComponentExposed<typeof BagelForm<T, P>>
|
|
39
|
-
|
|
40
|
-
const formRef = ref<BagelFormT>()
|
|
41
|
-
|
|
42
|
-
const formData = defineModel<T>('modelValue', {
|
|
43
|
-
default: () => ({}),
|
|
44
|
-
required: true
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
const currentStep = ref(0)
|
|
48
|
-
const previousStep = ref(0)
|
|
49
|
-
const validatedSteps = ref<number[]>([])
|
|
50
|
-
|
|
51
|
-
function reportValidity() {
|
|
52
|
-
if (!formRef.value) { return false }
|
|
53
|
-
const isValid = formRef.value.validateForm()
|
|
54
|
-
|
|
55
|
-
if (isValid && !validatedSteps.value.includes(currentStep.value)) {
|
|
56
|
-
validatedSteps.value.push(currentStep.value)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return isValid
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const computedSchema = computed(
|
|
63
|
-
() => useBglSchema({ schema: toValue(props.schema) })
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
// Filter out steps with vIf conditions that evaluate to false
|
|
67
|
-
const filteredSchema = computed(() => {
|
|
68
|
-
const schema = computedSchema.value
|
|
69
|
-
return schema.filter((step, _index) => {
|
|
70
|
-
// Skip steps that have vIf or v-if returning false
|
|
71
|
-
if ((step as any).vIf !== undefined || (step as any)['v-if'] !== undefined) {
|
|
72
|
-
const condition = (step as any).vIf ?? (step as any)['v-if']
|
|
73
|
-
// If condition is a function, evaluate it with current form data
|
|
74
|
-
if (typeof condition === 'function') {
|
|
75
|
-
return condition(undefined, formData.value)
|
|
76
|
-
}
|
|
77
|
-
// If condition is a boolean, use it directly
|
|
78
|
-
if (typeof condition === 'boolean') {
|
|
79
|
-
return condition
|
|
80
|
-
}
|
|
81
|
-
// If condition is a string, evaluate it (treat non-empty as true)
|
|
82
|
-
if (typeof condition === 'string') {
|
|
83
|
-
return !!condition
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
// Include steps with no vIf condition or ones that evaluate to true
|
|
87
|
-
return true
|
|
88
|
-
})
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
const numberOfSteps = computed(() => filteredSchema.value.length)
|
|
92
|
-
|
|
93
|
-
// Map the filtered step index to the actual schema index
|
|
94
|
-
const schemaIndexMap = computed(() => {
|
|
95
|
-
const map: number[] = []
|
|
96
|
-
computedSchema.value.forEach((step, index) => {
|
|
97
|
-
const vIfCondition = (step as any).vIf ?? (step as any)['v-if']
|
|
98
|
-
let shouldInclude = true
|
|
99
|
-
|
|
100
|
-
if (vIfCondition !== undefined) {
|
|
101
|
-
if (typeof vIfCondition === 'function') {
|
|
102
|
-
shouldInclude = vIfCondition(undefined, formData.value)
|
|
103
|
-
} else if (typeof vIfCondition === 'boolean') {
|
|
104
|
-
shouldInclude = vIfCondition
|
|
105
|
-
} else if (typeof vIfCondition === 'string') {
|
|
106
|
-
shouldInclude = !!vIfCondition
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (shouldInclude) {
|
|
111
|
-
map.push(index)
|
|
112
|
-
}
|
|
113
|
-
})
|
|
114
|
-
return map
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
// Get current step schema using the mapping
|
|
118
|
-
const currentStepSchema = computed(() => {
|
|
119
|
-
const actualIndex = schemaIndexMap.value[currentStep.value]
|
|
120
|
-
return [computedSchema.value[actualIndex]]
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
// Tracks which way we're sliding (left or right)
|
|
124
|
-
const slideDirection = ref(props.rtl ? 'right' : 'left')
|
|
125
|
-
|
|
126
|
-
watch(
|
|
127
|
-
() => currentStep.value,
|
|
128
|
-
(newStep, oldStep) => {
|
|
129
|
-
// Set direction based on step change
|
|
130
|
-
if (props.direction === 'auto') {
|
|
131
|
-
slideDirection.value = props.rtl
|
|
132
|
-
? (newStep > oldStep ? 'right' : 'left')
|
|
133
|
-
: (newStep > oldStep ? 'left' : 'right')
|
|
134
|
-
} else {
|
|
135
|
-
slideDirection.value = props.direction
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
previousStep.value = oldStep
|
|
139
|
-
// We don't need isStepping flag anymore
|
|
140
|
-
emits('stepChange', {
|
|
141
|
-
newStep,
|
|
142
|
-
oldStep,
|
|
143
|
-
totalSteps: numberOfSteps.value,
|
|
144
|
-
direction: slideDirection.value
|
|
145
|
-
})
|
|
146
|
-
}
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
const isLastStep = computed(() => currentStep.value === numberOfSteps.value - 1)
|
|
150
|
-
|
|
151
|
-
const isStepValidated = computed(() => (stepIndex: number) => validatedSteps.value.includes(stepIndex))
|
|
152
|
-
|
|
153
|
-
// Add a computed property to check if current step is valid
|
|
154
|
-
const isStepValid = ref(false)
|
|
155
|
-
|
|
156
|
-
async function checkCurrentStepValidity() {
|
|
157
|
-
await nextTick()
|
|
158
|
-
if (!props.validateOnSteps) { isStepValid.value = true }
|
|
159
|
-
else { isStepValid.value = formRef.value?.checkValidity() ?? false }
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
function prevStep() {
|
|
163
|
-
if (currentStep.value > 0) { currentStep.value-- }
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const formContainer = ref<HTMLElement>()
|
|
167
|
-
|
|
168
|
-
async function nextStep() {
|
|
169
|
-
// Always use reportValidity when attempting to move to next step
|
|
170
|
-
// This will show validation errors to the user
|
|
171
|
-
if (props.validateOnSteps && reportValidity() === false) { return }
|
|
172
|
-
if (!isLastStep.value) { currentStep.value++ }
|
|
173
|
-
await sleep(400)
|
|
174
|
-
checkCurrentStepValidity()
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
async function goToStep(stepIndex: number) {
|
|
178
|
-
// Can always go back, or to already validated steps
|
|
179
|
-
if (stepIndex < currentStep.value || validatedSteps.value.includes(stepIndex)) {
|
|
180
|
-
currentStep.value = stepIndex
|
|
181
|
-
return true
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// For forward navigation, validate each step sequentially until target or invalid step
|
|
185
|
-
if (stepIndex > currentStep.value) {
|
|
186
|
-
// Validate current step first
|
|
187
|
-
if (props.validateOnSteps && reportValidity() === false) {
|
|
188
|
-
return false
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Move forward step by step, validating each one
|
|
192
|
-
for (let step = currentStep.value + 1; step <= stepIndex; step++) {
|
|
193
|
-
// Move to the next step
|
|
194
|
-
currentStep.value = step
|
|
195
|
-
|
|
196
|
-
// Wait for the form to update with new step's fields
|
|
197
|
-
await nextTick()
|
|
198
|
-
await sleep(100) // Give time for form to render
|
|
199
|
-
|
|
200
|
-
// Validate this step if validation is enabled
|
|
201
|
-
if (props.validateOnSteps) {
|
|
202
|
-
// Check if the step is valid without showing validation errors for intermediate steps
|
|
203
|
-
const isValid = formRef.value?.checkValidity() ?? false
|
|
204
|
-
|
|
205
|
-
if (!isValid) {
|
|
206
|
-
// If this step is invalid, stop here
|
|
207
|
-
return false
|
|
208
|
-
}
|
|
209
|
-
// Mark this step as validated
|
|
210
|
-
if (!validatedSteps.value.includes(step)) {
|
|
211
|
-
validatedSteps.value.push(step)
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
return true
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
return false
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
function handleSubmit() {
|
|
223
|
-
// Show validation errors to the user when submitting
|
|
224
|
-
if (reportValidity() === false) { return }
|
|
225
|
-
emits('submit', formData.value)
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function reset() {
|
|
229
|
-
validatedSteps.value = []
|
|
230
|
-
currentStep.value = 0
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Re-evaluate filtered steps when formData changes
|
|
234
|
-
watch(() => formData.value, () => {
|
|
235
|
-
checkCurrentStepValidity()
|
|
236
|
-
if (currentStep.value >= numberOfSteps.value && numberOfSteps.value > 0) {
|
|
237
|
-
currentStep.value = 0
|
|
238
|
-
}
|
|
239
|
-
}, { deep: true })
|
|
240
|
-
|
|
241
|
-
defineExpose({
|
|
242
|
-
submit: handleSubmit,
|
|
243
|
-
validateForm: reportValidity,
|
|
244
|
-
checkValidity: formRef.value?.checkValidity,
|
|
245
|
-
isDirty: computed(() => formRef.value?.isDirty),
|
|
246
|
-
reset,
|
|
247
|
-
isLastStep,
|
|
248
|
-
goToStep,
|
|
249
|
-
currentStep,
|
|
250
|
-
totalSteps: computed(() => numberOfSteps.value),
|
|
251
|
-
isStepValid,
|
|
252
|
-
nextStep,
|
|
253
|
-
prevStep,
|
|
254
|
-
})
|
|
255
|
-
</script>
|
|
256
|
-
|
|
257
|
-
<template>
|
|
258
|
-
<div class="bgl-multi-step-form">
|
|
259
|
-
<!-- Progress indicator -->
|
|
260
|
-
<div v-if="showProgress" class="bgl-step-progress">
|
|
261
|
-
<slot
|
|
262
|
-
name="progress" v-bind="{
|
|
263
|
-
currentStep,
|
|
264
|
-
totalSteps: numberOfSteps,
|
|
265
|
-
goToStep,
|
|
266
|
-
stepLabels: props.stepLabels,
|
|
267
|
-
allowStepNavigation: props.allowStepNavigation,
|
|
268
|
-
isStepValidated,
|
|
269
|
-
}"
|
|
270
|
-
>
|
|
271
|
-
<div class="bgl-steps-indicator">
|
|
272
|
-
<div
|
|
273
|
-
v-for="(_, index) in numberOfSteps" :key="index" class="bgl-step-indicator" :class="[
|
|
274
|
-
{ active: index === currentStep },
|
|
275
|
-
{ completed: index < currentStep || isStepValidated(index) },
|
|
276
|
-
{ clickable: props.allowStepNavigation },
|
|
277
|
-
]" @click="props.allowStepNavigation && goToStep(index)"
|
|
278
|
-
>
|
|
279
|
-
<span>{{ index + 1 }}</span>
|
|
280
|
-
<span v-if="props.stepLabels && props.stepLabels[index]" class="bgl-step-label">
|
|
281
|
-
{{ props.stepLabels[index] }}
|
|
282
|
-
</span>
|
|
283
|
-
</div>
|
|
284
|
-
</div>
|
|
285
|
-
</slot>
|
|
286
|
-
</div>
|
|
287
|
-
|
|
288
|
-
<div class="bgl-form-wrapper">
|
|
289
|
-
<transition :name="slideDirection === 'right' ? 'slide-right' : 'slide-left'" mode="out-in">
|
|
290
|
-
<div :key="currentStep" ref="formContainer" class="bgl-form-container">
|
|
291
|
-
<BagelForm ref="formRef" v-model="formData" :schema="currentStepSchema" v-bind="bagelFormProps">
|
|
292
|
-
<template v-if="$slots.success" #success>
|
|
293
|
-
<slot name="success" />
|
|
294
|
-
</template>
|
|
295
|
-
<template v-if="$slots.error" #error>
|
|
296
|
-
<slot name="error" />
|
|
297
|
-
</template>
|
|
298
|
-
</BagelForm>
|
|
299
|
-
|
|
300
|
-
<!-- Navigation buttons inside the form container to animate together -->
|
|
301
|
-
</div>
|
|
302
|
-
</transition>
|
|
303
|
-
<div class="bgl-step-controls">
|
|
304
|
-
<slot
|
|
305
|
-
name="steppers" v-bind="{
|
|
306
|
-
prevStep,
|
|
307
|
-
nextStep,
|
|
308
|
-
submit: handleSubmit,
|
|
309
|
-
currentStep,
|
|
310
|
-
totalSteps: numberOfSteps,
|
|
311
|
-
isLastStep,
|
|
312
|
-
isStepValid,
|
|
313
|
-
}"
|
|
314
|
-
>
|
|
315
|
-
<Btn v-if="currentStep !== 0" color="gray" icon="arrow_back" @click="prevStep" />
|
|
316
|
-
<Btn
|
|
317
|
-
v-if="!isLastStep" icon="arrow_forward" :disabled="props.validateOnSteps && !isStepValid"
|
|
318
|
-
@click="nextStep"
|
|
319
|
-
/>
|
|
320
|
-
<Btn v-else value="Submit" @click="handleSubmit" />
|
|
321
|
-
</slot>
|
|
322
|
-
</div>
|
|
323
|
-
</div>
|
|
324
|
-
</div>
|
|
325
|
-
</template>
|
|
326
|
-
|
|
327
|
-
<style scoped>
|
|
328
|
-
.bgl-multi-step-form {
|
|
329
|
-
display: flex;
|
|
330
|
-
flex-direction: column;
|
|
331
|
-
gap: 1rem;
|
|
332
|
-
width: 100%;
|
|
333
|
-
/* Default transition duration */
|
|
334
|
-
--transition-duration: 300ms;
|
|
335
|
-
--move-distance: 35%;
|
|
336
|
-
--ease-in: cubic-bezier(0.42, 0, 0.58, 1);
|
|
337
|
-
--ease-out: cubic-bezier(0.42, 0, 0.58, 1);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
.bgl-steps-indicator {
|
|
341
|
-
display: flex;
|
|
342
|
-
justify-content: space-between;
|
|
343
|
-
align-items: center;
|
|
344
|
-
margin-bottom: 1rem;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
.bgl-step-indicator {
|
|
348
|
-
display: flex;
|
|
349
|
-
flex-direction: column;
|
|
350
|
-
align-items: center;
|
|
351
|
-
position: relative;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
.bgl-step-indicator::before {
|
|
355
|
-
content: '';
|
|
356
|
-
position: absolute;
|
|
357
|
-
top: 50%;
|
|
358
|
-
right: 50%;
|
|
359
|
-
height: 2px;
|
|
360
|
-
width: 100%;
|
|
361
|
-
background: #e0e0e0;
|
|
362
|
-
z-index: -1;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
.bgl-step-indicator:first-child::before {
|
|
366
|
-
display: none;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
.bgl-step-indicator>span:first-child {
|
|
370
|
-
width: 30px;
|
|
371
|
-
height: 30px;
|
|
372
|
-
border-radius: 50%;
|
|
373
|
-
background: #e0e0e0;
|
|
374
|
-
color: #555;
|
|
375
|
-
display: flex;
|
|
376
|
-
align-items: center;
|
|
377
|
-
justify-content: center;
|
|
378
|
-
margin-bottom: 0.5rem;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
.bgl-step-indicator.active>span:first-child {
|
|
382
|
-
background: var(--primary-color, #4CAF50);
|
|
383
|
-
color: white;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
.bgl-step-indicator.completed>span:first-child {
|
|
387
|
-
background: var(--success-color, #8BC34A);
|
|
388
|
-
color: white;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
.bgl-step-indicator.clickable {
|
|
392
|
-
cursor: pointer;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
.bgl-step-label {
|
|
396
|
-
font-size: 0.8rem;
|
|
397
|
-
max-width: 100px;
|
|
398
|
-
text-align: center;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
.bgl-form-wrapper {
|
|
402
|
-
display: grid;
|
|
403
|
-
overflow: clip;
|
|
404
|
-
height: auto;
|
|
405
|
-
transition: height var(--transition-duration) ease;
|
|
406
|
-
interpolate-size: allow-keywords;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
.bgl-form-wrapper>div {
|
|
410
|
-
grid-area: 1 / 1;
|
|
411
|
-
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
.bgl-form-container {
|
|
415
|
-
width: 100%;
|
|
416
|
-
display: flex;
|
|
417
|
-
flex-direction: column;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
.bgl-step-controls {
|
|
421
|
-
display: flex;
|
|
422
|
-
justify-content: center;
|
|
423
|
-
gap: 1rem;
|
|
424
|
-
grid-area: unset !important;
|
|
425
|
-
margin-top: 2rem;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
/* Slide Left Animation (going forward) */
|
|
429
|
-
.slide-left-enter-active {
|
|
430
|
-
transition: opacity var(--transition-duration) var(--ease-in),
|
|
431
|
-
transform var(--transition-duration) var(--ease-in);
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
.slide-left-leave-active {
|
|
435
|
-
transition: opacity var(--transition-duration) var(--ease-out),
|
|
436
|
-
transform var(--transition-duration) var(--ease-out);
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
.slide-left-enter-from {
|
|
440
|
-
opacity: 0;
|
|
441
|
-
transform: translateX(var(--move-distance));
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
.slide-left-leave-to {
|
|
445
|
-
opacity: 0;
|
|
446
|
-
transform: translateX(-30%);
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/* Slide Right Animation (going back) */
|
|
450
|
-
.slide-right-enter-active {
|
|
451
|
-
transition: opacity var(--transition-duration) var(--ease-in),
|
|
452
|
-
transform var(--transition-duration) var(--ease-in);
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
.slide-right-leave-active {
|
|
456
|
-
transition: opacity var(--transition-duration) var(--ease-out),
|
|
457
|
-
transform var(--transition-duration) var(--ease-out);
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
.slide-right-enter-from {
|
|
461
|
-
opacity: 0;
|
|
462
|
-
transform: translateX(-30%);
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
.slide-right-leave-to {
|
|
466
|
-
opacity: 0;
|
|
467
|
-
transform: translateX(var(--move-distance));
|
|
468
|
-
}
|
|
469
|
-
</style>
|