@bagelink/vue 1.15.211 → 1.15.213

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/vue",
3
3
  "type": "module",
4
- "version": "1.15.211",
4
+ "version": "1.15.213",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Bagel Studio",
@@ -251,10 +251,17 @@ function generateLabel(key: string, field: FieldBuilder): string {
251
251
  function getFieldComponent(fieldOrType: FieldBuilder | string) {
252
252
  // display: 'btn' on select/multiselect renders as SelectBtn
253
253
  if (typeof fieldOrType !== 'string' && (fieldOrType._type === 'select' || fieldOrType._type === 'multiselect') && fieldOrType._config.display === 'btn') {
254
- return SelectBtn
254
+ return props.components?.selectBtn ?? SelectBtn
255
255
  }
256
256
 
257
257
  const type = typeof fieldOrType === 'string' ? fieldOrType : fieldOrType._type
258
+ // Host may override any built-in field type via `components` (e.g. auctentic
259
+ // skins radio/select as OfferChoiceField). Named `$.component('X')` refs are
260
+ // resolved separately in `resolveComponent` — type keys only hit here.
261
+ if (type && props.components?.[type] != null) {
262
+ return props.components[type]
263
+ }
264
+
258
265
  const componentMap: Record<string, any> = {
259
266
  text: TextInput,
260
267
  email: EmailInput,
@@ -49,6 +49,10 @@ export interface Props {
49
49
  * the `redirect` event).
50
50
  */
51
51
  redirect?: boolean
52
+ /** Hide the built-in step `<h2>` (host renders its own title). Default false. */
53
+ hideTitle?: boolean
54
+ /** Hide the step-position counter pill in the default nav. Default false. */
55
+ hideCounter?: boolean
52
56
  /** Optional async submit handler; awaited before `complete` is emitted. */
53
57
  onComplete?: (data: Record<string, any>) => Promise<void> | void
54
58
  }
@@ -59,6 +63,8 @@ const props = withDefaults(defineProps<Props>(), {
59
63
  autoAdvanceDelay: 200,
60
64
  dataLayer: true,
61
65
  redirect: true,
66
+ hideTitle: false,
67
+ hideCounter: false,
62
68
  })
63
69
 
64
70
  const emit = defineEmits<{
@@ -75,7 +81,9 @@ const emit = defineEmits<{
75
81
 
76
82
  const { $t } = useI18n()
77
83
  const slots: Slots = useSlots()
78
- const slotNames = computed((): string[] => Object.keys(slots))
84
+ const slotNames = computed((): string[] =>
85
+ Object.keys(slots).filter(name => name !== 'nav' && name !== 'primary-label' && name !== 'step' && name !== 'empty'),
86
+ )
79
87
 
80
88
  // Slide direction for the step transition: 'next' when advancing, 'prev' on
81
89
  // Back. Drives which named transition (and thus which X offset) is used.
@@ -152,6 +160,10 @@ watch(progress, val => emit('progress', val), { immediate: true })
152
160
  const formRef = ref<{ validate: () => boolean } | null>(null)
153
161
  const submitting = ref(false)
154
162
 
163
+ function setFormRef(el: { validate: () => boolean } | null) {
164
+ formRef.value = el
165
+ }
166
+
155
167
  /** Validate the visible current step via the underlying FormFlow. */
156
168
  function validateStep(): boolean {
157
169
  return formRef.value?.validate() ?? true
@@ -258,7 +270,7 @@ defineExpose({ formData, currentKey, nextKey, isTerminal, progress, validateStep
258
270
  <div class="ffp-stage">
259
271
  <Transition :name="transitionName" mode="out-in">
260
272
  <div v-if="currentStep" :key="currentKey" class="ffp-step">
261
- <h2 v-if="currentStep.title" class="ffp-title">
273
+ <h2 v-if="!hideTitle && currentStep.title" class="ffp-title">
262
274
  {{ currentStep.title }}
263
275
  </h2>
264
276
 
@@ -267,6 +279,8 @@ defineExpose({ formData, currentKey, nextKey, isTerminal, progress, validateStep
267
279
  :step="currentStep"
268
280
  :form-data="formData"
269
281
  :step-key="currentKey"
282
+ :schema="currentSchema"
283
+ :set-form-ref="setFormRef"
270
284
  >
271
285
  <FormFlow
272
286
  v-if="currentSchema"
@@ -290,44 +304,64 @@ defineExpose({ formData, currentKey, nextKey, isTerminal, progress, validateStep
290
304
  </Transition>
291
305
  </div>
292
306
 
293
- <div class="ffp-nav flex justify-content-between gap-1">
294
- <Btn
295
- class="ffp-nav-btn"
296
- flat
297
- icon="arrow_back"
298
- :value="$t?.('multiStep.previous') ?? 'Back'"
299
- :disabled="!canGoBack"
300
- @click="onBack"
301
- />
302
-
303
- <span class="ffp-counter flex-center round bg-primary-10 color-primary px-075 txt13 medium tabular-nums">
304
- {{ stepPosition }}
305
- </span>
306
-
307
- <Btn
308
- v-if="isTerminal"
309
- class="ffp-nav-btn"
310
- :value="$t?.('multiStep.complete') ?? 'Submit'"
311
- :loading="submitting"
312
- @click="onPrimary"
313
- >
314
- <slot name="primary-label" :is-terminal="true">
315
- {{ $t?.('multiStep.complete') ?? 'Submit' }}
316
- </slot>
317
- </Btn>
318
- <Btn
319
- v-else
320
- class="ffp-nav-btn"
321
- icon-end="arrow_forward"
322
- :value="$t?.('multiStep.next') ?? 'Next'"
323
- :disabled="submitting"
324
- @click="onPrimary"
325
- >
326
- <slot name="primary-label" :is-terminal="false">
327
- {{ $t?.('multiStep.next') ?? 'Next' }}
328
- </slot>
329
- </Btn>
330
- </div>
307
+ <!--
308
+ Nav slot props use `goBack`/`goPrimary` (not `onBack`/`onPrimary`) —
309
+ Vue treats `on*` as listeners and would swallow those names.
310
+ -->
311
+ <slot
312
+ name="nav"
313
+ :can-go-back="canGoBack"
314
+ :is-terminal="isTerminal"
315
+ :submitting="submitting"
316
+ :go-back="onBack"
317
+ :go-primary="onPrimary"
318
+ :step-position="stepPosition"
319
+ :progress="progress"
320
+ :current-key="currentKey"
321
+ :auto-advances="autoAdvances"
322
+ >
323
+ <div class="ffp-nav flex flex-center gap-1">
324
+ <Btn
325
+ class="ffp-nav-btn"
326
+ flat
327
+ icon="arrow_back"
328
+ :value="$t?.('multiStep.previous') ?? 'Back'"
329
+ :disabled="!canGoBack"
330
+ @click="onBack"
331
+ />
332
+
333
+ <span
334
+ v-if="!hideCounter"
335
+ class="ffp-counter flex-center round bg-primary-10 color-primary px-075 txt13 medium tabular-nums"
336
+ >
337
+ {{ stepPosition }}
338
+ </span>
339
+
340
+ <Btn
341
+ v-if="isTerminal"
342
+ class="ffp-nav-btn"
343
+ :value="$t?.('multiStep.complete') ?? 'Submit'"
344
+ :loading="submitting"
345
+ @click="onPrimary"
346
+ >
347
+ <slot name="primary-label" :is-terminal="true">
348
+ {{ $t?.('multiStep.complete') ?? 'Submit' }}
349
+ </slot>
350
+ </Btn>
351
+ <Btn
352
+ v-else
353
+ class="ffp-nav-btn"
354
+ icon-end="arrow_forward"
355
+ :value="$t?.('multiStep.next') ?? 'Next'"
356
+ :disabled="submitting"
357
+ @click="onPrimary"
358
+ >
359
+ <slot name="primary-label" :is-terminal="false">
360
+ {{ $t?.('multiStep.next') ?? 'Next' }}
361
+ </slot>
362
+ </Btn>
363
+ </div>
364
+ </slot>
331
365
  </div>
332
366
  </template>
333
367
 
@@ -991,6 +991,7 @@ function createFieldFromProperty(
991
991
  field = $.number(config)
992
992
  break
993
993
  case 'tel':
994
+ case 'phone':
994
995
  field = $.tel(config)
995
996
  break
996
997
  case 'url':
@@ -1029,6 +1030,10 @@ function createFieldFromProperty(
1029
1030
  case 'multiselect':
1030
1031
  field = $.multiselect(xOptions ?? resolvedProp.enum ?? [], config)
1031
1032
  break
1033
+ case 'file':
1034
+ case 'upload':
1035
+ field = $.upload(config)
1036
+ break
1032
1037
  case 'array': {
1033
1038
  const arrayConfig: Record<string, any> = { ...config }
1034
1039
  if (xUi.allowAdd !== undefined) arrayConfig.allowAdd = xUi.allowAdd