@bagelink/vue 1.15.253 → 1.15.261

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 (34) hide show
  1. package/dist/components/FilterQuery.vue.d.ts +6 -0
  2. package/dist/components/FilterQuery.vue.d.ts.map +1 -1
  3. package/dist/components/charts/ChartTooltip.vue.d.ts.map +1 -1
  4. package/dist/components/form/inputs/Upload/attachments.d.ts +27 -0
  5. package/dist/components/form/inputs/Upload/attachments.d.ts.map +1 -0
  6. package/dist/components/form/inputs/Upload/upload.d.ts +7 -3
  7. package/dist/components/form/inputs/Upload/upload.d.ts.map +1 -1
  8. package/dist/components/form/inputs/Upload/upload.types.d.ts +13 -0
  9. package/dist/components/form/inputs/Upload/upload.types.d.ts.map +1 -1
  10. package/dist/components/form/inputs/Upload/useAttachments.d.ts +97 -0
  11. package/dist/components/form/inputs/Upload/useAttachments.d.ts.map +1 -0
  12. package/dist/components/form/inputs/index.d.ts +2 -0
  13. package/dist/components/form/inputs/index.d.ts.map +1 -1
  14. package/dist/form-flow/FormFlowPlayer.vue.d.ts +8 -10
  15. package/dist/form-flow/FormFlowPlayer.vue.d.ts.map +1 -1
  16. package/dist/form-flow/structure.d.ts +11 -7
  17. package/dist/form-flow/structure.d.ts.map +1 -1
  18. package/dist/index.cjs +92 -92
  19. package/dist/index.mjs +9546 -9424
  20. package/dist/style.css +1 -1
  21. package/package.json +1 -1
  22. package/src/components/Dropdown.vue +2 -2
  23. package/src/components/FilterQuery.vue +99 -12
  24. package/src/components/ListItem.vue +1 -1
  25. package/src/components/charts/ChartTooltip.vue +39 -4
  26. package/src/components/dataTable/DataTable.vue +1 -1
  27. package/src/components/form/inputs/Upload/attachments.ts +41 -0
  28. package/src/components/form/inputs/Upload/upload.ts +19 -10
  29. package/src/components/form/inputs/Upload/upload.types.ts +18 -0
  30. package/src/components/form/inputs/Upload/useAttachments.ts +175 -0
  31. package/src/components/form/inputs/index.ts +2 -0
  32. package/src/form-flow/FormFlowPlayer.vue +28 -26
  33. package/src/form-flow/structure.ts +12 -7
  34. package/src/styles/dark.css +3 -2
@@ -22,12 +22,15 @@ import { useI18n } from '../i18n'
22
22
  import { fromJSONSchema } from './form-flow'
23
23
  import Btn from '../components/Btn.vue'
24
24
  import FormFlow from './FormFlow.vue'
25
+ import type { FormStepEventPayload } from './structure'
25
26
  import { autoAdvanceFieldKey, entryStepKey, pathProgress, resolveNext, stepAutoAdvances, stepByKey } from './structure'
26
27
 
27
28
  export interface Props {
28
29
  structure: FormStructure
29
30
  modelValue?: Record<string, any>
30
31
  components?: Record<string, any>
32
+ /** Human name of the form, included in step/complete event payloads. */
33
+ formName?: string
31
34
  /** Slide between steps (honors prefers-reduced-motion). Default true. */
32
35
  animated?: boolean
33
36
  /**
@@ -37,12 +40,6 @@ export interface Props {
37
40
  autoAdvance?: boolean
38
41
  /** Delay (ms) before an auto-advance fires, letting the choice paint. */
39
42
  autoAdvanceDelay?: number
40
- /**
41
- * Push each step's `enterEvent` / `submitEvent` payload to `window.dataLayer`
42
- * (GTM). Default true. Set false to suppress (e.g. SSR or when the host wants
43
- * to handle analytics itself via the `dataLayer` event).
44
- */
45
- dataLayer?: boolean
46
43
  /**
47
44
  * Perform `redirectUrl` navigation on submit. Default true. Set false to let
48
45
  * the host own navigation (it can read the URL from the `complete` event or
@@ -58,10 +55,10 @@ export interface Props {
58
55
  }
59
56
 
60
57
  const props = withDefaults(defineProps<Props>(), {
58
+ formName: '',
61
59
  animated: true,
62
60
  autoAdvance: true,
63
61
  autoAdvanceDelay: 200,
64
- dataLayer: true,
65
62
  redirect: true,
66
63
  hideTitle: false,
67
64
  hideCounter: false,
@@ -72,8 +69,10 @@ const emit = defineEmits<{
72
69
  'stepChange': [stepKey: string]
73
70
  /** Best-effort 0–100 progress along the current path; recomputes on change. */
74
71
  'progress': [value: number]
75
- /** A dataLayer payload was pushed. `phase` = which step hook fired it. */
76
- 'dataLayer': [payload: Record<string, any>, phase: 'enter' | 'submit']
72
+ /** Fired when a step is entered (including the first). */
73
+ 'stepEnter': [payload: FormStepEventPayload]
74
+ /** Fired when the form is submitted from a terminal step. */
75
+ 'formComplete': [payload: FormStepEventPayload]
77
76
  /** The form is about to redirect to `url` (fired even if `redirect` is off). */
78
77
  'redirect': [url: string]
79
78
  'complete': [data: Record<string, any>]
@@ -116,24 +115,27 @@ watch(currentKey, (key) => {
116
115
 
117
116
  const currentStep = computed(() => stepByKey(props.structure, currentKey.value ?? null))
118
117
 
119
- // ─── dataLayer (GTM) ─────────────────────────────────────────────────────────
120
- // Push a step's analytics payload to window.dataLayer and notify the host. The
121
- // server stores these payloads verbatim; the client decides when to fire them:
122
- // `enterEvent` on step entry, `submitEvent` on submit-from-a-terminal-step.
123
- function pushDataLayer(payload: Record<string, any> | null | undefined, phase: 'enter' | 'submit') {
124
- if (!payload || typeof payload !== 'object') return
125
- emit('dataLayer', payload, phase)
126
- if (!props.dataLayer || typeof window === 'undefined') return
127
- const w = window as unknown as { dataLayer?: Record<string, any>[] }
128
- w.dataLayer = w.dataLayer || []
129
- w.dataLayer.push({ ...payload })
118
+ // ─── Step event helpers ───────────────────────────────────────────────────────
119
+ // Build a standardised payload for both `stepEnter` and `formComplete` emits.
120
+ function buildPayload(stepKey: string): FormStepEventPayload {
121
+ const step = stepByKey(props.structure, stepKey)
122
+ const prog = pathProgress(props.structure, stepKey, formData.value)
123
+ // Estimate total from progress percentage (progress = position / total * 100).
124
+ const position = history.value.length + 1
125
+ const totalSteps = prog > 0 ? Math.round(position / prog * 100) : null
126
+ return {
127
+ formName: props.formName,
128
+ stepKey,
129
+ stepTitle: step?.title ?? '',
130
+ stepIndex: position,
131
+ totalSteps,
132
+ formData: { ...formData.value },
133
+ }
130
134
  }
131
135
 
132
- // Fire the current step's `enterEvent` whenever we land on it (including the
133
- // first step). `immediate` covers the entry step; the key guard avoids
134
- // re-firing when the same step object recomputes.
136
+ // Fire `stepEnter` whenever we land on a new step (including the first).
135
137
  watch(currentKey, (key, prev) => {
136
- if (key && key !== prev) pushDataLayer(stepByKey(props.structure, key)?.enterEvent, 'enter')
138
+ if (key && key !== prev) emit('stepEnter', buildPayload(key))
137
139
  }, { immediate: true })
138
140
 
139
141
  // Convert the current step's stored JSON Schema into a renderable schema.
@@ -177,8 +179,8 @@ async function onPrimary() {
177
179
  const step = currentStep.value
178
180
  try {
179
181
  await props.onComplete?.({ ...formData.value })
180
- // Fire this terminal step's submit analytics before completing.
181
- pushDataLayer(step?.submitEvent, 'submit')
182
+ // Emit formComplete with standardised payload before completing.
183
+ if (currentKey.value) emit('formComplete', buildPayload(currentKey.value))
182
184
  emit('complete', { ...formData.value })
183
185
  // Redirect last: leaves the page after analytics + host handling.
184
186
  const url = step?.redirectUrl?.trim()
@@ -31,13 +31,6 @@ export interface FormStep {
31
31
  * (final step or an early-termination leaf). Empty => no redirect.
32
32
  */
33
33
  redirectUrl?: string | null
34
- /** dataLayer payload pushed when the user *enters* this step. */
35
- enterEvent?: Record<string, any> | null
36
- /**
37
- * dataLayer payload pushed when the form is *submitted* from this step
38
- * (i.e. this step is terminal), before the redirect.
39
- */
40
- submitEvent?: Record<string, any> | null
41
34
  /** Canvas position (designer-only; ignored by the server). */
42
35
  x?: number
43
36
  y?: number
@@ -60,6 +53,18 @@ export interface FormStructure {
60
53
  transitions: StepEdge[]
61
54
  }
62
55
 
56
+ /** Standardised payload emitted for both `stepEnter` and `formComplete`. */
57
+ export interface FormStepEventPayload {
58
+ formName: string
59
+ stepKey: string
60
+ stepTitle: string
61
+ /** 1-based position in visited path. */
62
+ stepIndex: number
63
+ /** Projected total along current branch (null if indeterminate). */
64
+ totalSteps: number | null
65
+ formData: Record<string, any>
66
+ }
67
+
63
68
  /** An empty structure (single-step / not-yet-built). */
64
69
  export function emptyStructure(): FormStructure {
65
70
  return { steps: [], transitions: [] }
@@ -333,11 +333,12 @@
333
333
  * fight the existing focus outline or the .frame/.bgl-outline variants, which
334
334
  * already draw their own outline. The focus state still wins because its rule
335
335
  * comes from inputs.css with its own box-shadow + outline-color. */
336
- .bgl-dark-mode .bagel-input input:not([type="radio"]):not([type="checkbox"]):not([type="color"]),
336
+ .bgl-dark-mode .bagel-input input:not([type="radio"]):not([type="checkbox"]):not([type="color"]):not(.national-number-input),
337
337
  .bgl-dark-mode .bagel-input textarea,
338
338
  .bgl-dark-mode .bagel-input select,
339
339
  .bgl-dark-mode .custom-select .input,
340
- .bgl-dark-mode .selectinput-btn {
340
+ .bgl-dark-mode .selectinput-btn,
341
+ .bgl-dark-mode .tel-input {
341
342
  box-shadow: inset 0 0 0 1px var(--bgl-dm-border);
342
343
  }
343
344