@bacano/sdk 1.2.2 → 1.2.3
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/FLOWS.md +114 -0
- package/README.md +89 -18
- package/STOREFRONT_FORMS.md +50 -0
- package/STOREFRONT_PAYMENTS.md +231 -0
- package/client.d.ts +8 -1
- package/flows.d.ts +109 -0
- package/form-conditions.d.ts +6 -0
- package/index.cjs +84 -2
- package/index.d.ts +3 -0
- package/index.js +84 -2
- package/modules/checkout.d.ts +1 -1
- package/package.json +1 -1
- package/react/flow-form.d.ts +9 -0
- package/react/form-scale-control.d.ts +9 -0
- package/react/forms.cjs +260 -65
- package/react/forms.d.ts +1 -0
- package/react/forms.js +254 -59
- package/react.cjs +48 -1
- package/react.js +48 -1
- package/skills/bacano-web/SKILL.md +2 -0
- package/skills/bacano-web/references/storefront.md +2 -0
- package/transport/documents.d.ts +1 -1
- package/types.d.ts +14 -1
package/react/forms.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
useCallback as useCallback2,
|
|
4
4
|
useEffect as useEffect3,
|
|
5
|
-
useId,
|
|
5
|
+
useId as useId2,
|
|
6
6
|
useMemo as useMemo2,
|
|
7
7
|
useRef as useRef3,
|
|
8
|
-
useState as
|
|
8
|
+
useState as useState3
|
|
9
9
|
} from "react";
|
|
10
10
|
|
|
11
11
|
// libs/sdk/src/errors.ts
|
|
@@ -22,11 +22,124 @@ var WebsiteError = class extends Error {
|
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
// libs/sdk/src/
|
|
25
|
+
// libs/sdk/src/form-conditions.ts
|
|
26
|
+
function formRootFields(definition) {
|
|
27
|
+
return [
|
|
28
|
+
...definition.fields,
|
|
29
|
+
...definition.sections.flatMap((section) => section.fields),
|
|
30
|
+
...definition.steps.flatMap((step) => [
|
|
31
|
+
...step.fields,
|
|
32
|
+
...step.sections.flatMap((section) => section.fields)
|
|
33
|
+
])
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
function visibleFormFields(fields, values) {
|
|
37
|
+
return fields.flatMap((field) => [
|
|
38
|
+
field,
|
|
39
|
+
...visibleFormFields(
|
|
40
|
+
field.branches?.find((branch) => branch.value === values[field.key])?.fields ?? [],
|
|
41
|
+
values
|
|
42
|
+
)
|
|
43
|
+
]);
|
|
44
|
+
}
|
|
45
|
+
function allFormFields(fields) {
|
|
46
|
+
return fields.flatMap((field) => [
|
|
47
|
+
field,
|
|
48
|
+
...allFormFields((field.branches ?? []).flatMap((branch) => branch.fields))
|
|
49
|
+
]);
|
|
50
|
+
}
|
|
51
|
+
function activeFormValues(definition, values) {
|
|
52
|
+
const keys = new Set(
|
|
53
|
+
visibleFormFields(formRootFields(definition), values).map(
|
|
54
|
+
(field) => field.key
|
|
55
|
+
)
|
|
56
|
+
);
|
|
57
|
+
return Object.fromEntries(
|
|
58
|
+
Object.entries(values).filter(([key]) => keys.has(key))
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// libs/sdk/src/react/form-scale-control.tsx
|
|
26
63
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
64
|
+
function FormScaleControl({
|
|
65
|
+
field,
|
|
66
|
+
id,
|
|
67
|
+
value,
|
|
68
|
+
onChange,
|
|
69
|
+
className
|
|
70
|
+
}) {
|
|
71
|
+
const scale = field.scale;
|
|
72
|
+
if (!scale) return null;
|
|
73
|
+
const options = Array.from(
|
|
74
|
+
{ length: Math.max(0, Math.min(11, scale.max - scale.min + 1)) },
|
|
75
|
+
(_, index) => scale.min + index
|
|
76
|
+
);
|
|
77
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
78
|
+
/* @__PURE__ */ jsx(
|
|
79
|
+
"div",
|
|
80
|
+
{
|
|
81
|
+
role: "radiogroup",
|
|
82
|
+
"aria-labelledby": `${id}-label`,
|
|
83
|
+
style: { display: "flex", flexWrap: "wrap", gap: 12 },
|
|
84
|
+
children: options.map((number) => /* @__PURE__ */ jsxs(
|
|
85
|
+
"label",
|
|
86
|
+
{
|
|
87
|
+
style: { display: "inline-flex", alignItems: "center", gap: 4 },
|
|
88
|
+
children: [
|
|
89
|
+
/* @__PURE__ */ jsx(
|
|
90
|
+
"input",
|
|
91
|
+
{
|
|
92
|
+
className,
|
|
93
|
+
type: "radio",
|
|
94
|
+
name: id,
|
|
95
|
+
value: String(number),
|
|
96
|
+
checked: value === String(number),
|
|
97
|
+
required: field.required,
|
|
98
|
+
onChange: () => onChange(String(number)),
|
|
99
|
+
"aria-label": `${number} de ${scale.max}`
|
|
100
|
+
}
|
|
101
|
+
),
|
|
102
|
+
scale.display === "stars" ? /* @__PURE__ */ jsx(
|
|
103
|
+
"span",
|
|
104
|
+
{
|
|
105
|
+
"aria-hidden": "true",
|
|
106
|
+
style: {
|
|
107
|
+
fontSize: 24,
|
|
108
|
+
color: Number(value) >= number ? "var(--accent, #b45309)" : "var(--muted, #6b7280)"
|
|
109
|
+
},
|
|
110
|
+
children: "\u2605"
|
|
111
|
+
}
|
|
112
|
+
) : number
|
|
113
|
+
]
|
|
114
|
+
},
|
|
115
|
+
number
|
|
116
|
+
))
|
|
117
|
+
}
|
|
118
|
+
),
|
|
119
|
+
(scale.minLabel || scale.maxLabel) && /* @__PURE__ */ jsxs("p", { children: [
|
|
120
|
+
scale.minLabel,
|
|
121
|
+
" \u2014 ",
|
|
122
|
+
scale.maxLabel
|
|
123
|
+
] })
|
|
124
|
+
] });
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// libs/sdk/src/react/form-field-control.tsx
|
|
128
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
27
129
|
function BacanoFormFieldControl(props) {
|
|
28
130
|
const { field, className, value, onChange } = props;
|
|
29
131
|
const controlId = props.id ?? field.key;
|
|
132
|
+
if (field.type === "scale")
|
|
133
|
+
return /* @__PURE__ */ jsx2(
|
|
134
|
+
FormScaleControl,
|
|
135
|
+
{
|
|
136
|
+
field,
|
|
137
|
+
id: controlId,
|
|
138
|
+
value,
|
|
139
|
+
onChange,
|
|
140
|
+
className
|
|
141
|
+
}
|
|
142
|
+
);
|
|
30
143
|
const common = {
|
|
31
144
|
id: controlId,
|
|
32
145
|
name: field.key,
|
|
@@ -34,7 +147,7 @@ function BacanoFormFieldControl(props) {
|
|
|
34
147
|
className
|
|
35
148
|
};
|
|
36
149
|
if (field.type === "textarea") {
|
|
37
|
-
return /* @__PURE__ */
|
|
150
|
+
return /* @__PURE__ */ jsx2(
|
|
38
151
|
"textarea",
|
|
39
152
|
{
|
|
40
153
|
...common,
|
|
@@ -48,7 +161,7 @@ function BacanoFormFieldControl(props) {
|
|
|
48
161
|
}
|
|
49
162
|
if (field.type === "select" || field.type === "multi_select") {
|
|
50
163
|
const isMultiple = field.type === "multi_select";
|
|
51
|
-
return /* @__PURE__ */
|
|
164
|
+
return /* @__PURE__ */ jsxs2(
|
|
52
165
|
"select",
|
|
53
166
|
{
|
|
54
167
|
...common,
|
|
@@ -61,15 +174,15 @@ function BacanoFormFieldControl(props) {
|
|
|
61
174
|
) : event.target.value
|
|
62
175
|
),
|
|
63
176
|
children: [
|
|
64
|
-
!isMultiple ? /* @__PURE__ */
|
|
65
|
-
(field.options ?? []).map((option) => /* @__PURE__ */
|
|
177
|
+
!isMultiple ? /* @__PURE__ */ jsx2("option", { value: "", children: field.placeholder ?? "Selecciona una opci\xF3n" }) : null,
|
|
178
|
+
(field.options ?? []).map((option) => /* @__PURE__ */ jsx2("option", { value: option.value, children: option.label }, option.value))
|
|
66
179
|
]
|
|
67
180
|
}
|
|
68
181
|
);
|
|
69
182
|
}
|
|
70
183
|
if (field.type === "radio") {
|
|
71
|
-
return /* @__PURE__ */
|
|
72
|
-
/* @__PURE__ */
|
|
184
|
+
return /* @__PURE__ */ jsx2("div", { role: "radiogroup", "aria-labelledby": `${controlId}-label`, children: (field.options ?? []).map((option) => /* @__PURE__ */ jsxs2("label", { children: [
|
|
185
|
+
/* @__PURE__ */ jsx2(
|
|
73
186
|
"input",
|
|
74
187
|
{
|
|
75
188
|
type: "radio",
|
|
@@ -84,7 +197,7 @@ function BacanoFormFieldControl(props) {
|
|
|
84
197
|
] }, option.value)) });
|
|
85
198
|
}
|
|
86
199
|
if (field.type === "checkbox") {
|
|
87
|
-
return /* @__PURE__ */
|
|
200
|
+
return /* @__PURE__ */ jsx2(
|
|
88
201
|
"input",
|
|
89
202
|
{
|
|
90
203
|
...common,
|
|
@@ -94,7 +207,7 @@ function BacanoFormFieldControl(props) {
|
|
|
94
207
|
}
|
|
95
208
|
);
|
|
96
209
|
}
|
|
97
|
-
return /* @__PURE__ */
|
|
210
|
+
return /* @__PURE__ */ jsx2(
|
|
98
211
|
"input",
|
|
99
212
|
{
|
|
100
213
|
...common,
|
|
@@ -111,13 +224,13 @@ function BacanoFormFieldControl(props) {
|
|
|
111
224
|
}
|
|
112
225
|
|
|
113
226
|
// libs/sdk/src/react/form-sections.tsx
|
|
114
|
-
import { jsx as
|
|
227
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
115
228
|
function FormFields(props) {
|
|
116
229
|
return props.fields.map((field) => {
|
|
117
230
|
const controlId = `${props.idPrefix}-${field.key}`;
|
|
118
231
|
const value = props.values[field.key] ?? (field.type === "checkbox" ? false : field.type === "multi_select" ? [] : "");
|
|
119
|
-
return /* @__PURE__ */
|
|
120
|
-
/* @__PURE__ */
|
|
232
|
+
return /* @__PURE__ */ jsxs3("div", { className: props.classNames?.field, children: [
|
|
233
|
+
/* @__PURE__ */ jsx3(
|
|
121
234
|
"label",
|
|
122
235
|
{
|
|
123
236
|
id: `${controlId}-label`,
|
|
@@ -126,7 +239,7 @@ function FormFields(props) {
|
|
|
126
239
|
children: field.label
|
|
127
240
|
}
|
|
128
241
|
),
|
|
129
|
-
/* @__PURE__ */
|
|
242
|
+
/* @__PURE__ */ jsx3(
|
|
130
243
|
BacanoFormFieldControl,
|
|
131
244
|
{
|
|
132
245
|
field,
|
|
@@ -136,15 +249,18 @@ function FormFields(props) {
|
|
|
136
249
|
onChange: (nextValue) => props.onChange(field.key, nextValue)
|
|
137
250
|
}
|
|
138
251
|
),
|
|
139
|
-
field.helpText ? /* @__PURE__ */
|
|
252
|
+
field.helpText ? /* @__PURE__ */ jsx3("p", { className: props.classNames?.helpText, children: field.helpText }) : null,
|
|
253
|
+
field.branches?.map(
|
|
254
|
+
(branch) => branch.value === props.values[field.key] ? /* @__PURE__ */ jsx3("div", { "data-bacano-form-branch": branch.value, children: /* @__PURE__ */ jsx3(FormFields, { ...props, fields: branch.fields }) }, branch.value) : null
|
|
255
|
+
)
|
|
140
256
|
] }, field.key);
|
|
141
257
|
});
|
|
142
258
|
}
|
|
143
259
|
function FormSections(props) {
|
|
144
|
-
return props.sections.map((section) => /* @__PURE__ */
|
|
145
|
-
/* @__PURE__ */
|
|
146
|
-
section.description ? /* @__PURE__ */
|
|
147
|
-
/* @__PURE__ */
|
|
260
|
+
return props.sections.map((section) => /* @__PURE__ */ jsxs3("section", { className: props.classNames?.section, children: [
|
|
261
|
+
/* @__PURE__ */ jsx3("h3", { className: props.classNames?.sectionTitle, children: section.title }),
|
|
262
|
+
section.description ? /* @__PURE__ */ jsx3("p", { className: props.classNames?.sectionDescription, children: section.description }) : null,
|
|
263
|
+
/* @__PURE__ */ jsx3(
|
|
148
264
|
FormFields,
|
|
149
265
|
{
|
|
150
266
|
fields: section.fields,
|
|
@@ -284,8 +400,82 @@ function useBacanoState() {
|
|
|
284
400
|
return useContext2(BacanoReactContext);
|
|
285
401
|
}
|
|
286
402
|
|
|
403
|
+
// libs/sdk/src/react/flow-form.tsx
|
|
404
|
+
import { useId, useState as useState2 } from "react";
|
|
405
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
406
|
+
function BacanoFlowForm({
|
|
407
|
+
form,
|
|
408
|
+
onSubmit,
|
|
409
|
+
onRefresh,
|
|
410
|
+
classNames
|
|
411
|
+
}) {
|
|
412
|
+
const id = useId();
|
|
413
|
+
const [values, setValues] = useState2(
|
|
414
|
+
() => activeFormValues(form.definition, form.initialValues ?? {})
|
|
415
|
+
);
|
|
416
|
+
const [error, setError] = useState2("");
|
|
417
|
+
const [busy, setBusy] = useState2(false);
|
|
418
|
+
const common = {
|
|
419
|
+
idPrefix: id,
|
|
420
|
+
values,
|
|
421
|
+
classNames,
|
|
422
|
+
onChange: (key, value) => setValues(
|
|
423
|
+
(current) => activeFormValues(form.definition, { ...current, [key]: value })
|
|
424
|
+
)
|
|
425
|
+
};
|
|
426
|
+
return /* @__PURE__ */ jsxs4(
|
|
427
|
+
"form",
|
|
428
|
+
{
|
|
429
|
+
className: classNames?.root,
|
|
430
|
+
onSubmit: async (event) => {
|
|
431
|
+
event.preventDefault();
|
|
432
|
+
if (busy) return;
|
|
433
|
+
setBusy(true);
|
|
434
|
+
setError("");
|
|
435
|
+
try {
|
|
436
|
+
await onSubmit(activeFormValues(form.definition, values), form);
|
|
437
|
+
} catch (reason) {
|
|
438
|
+
setError(
|
|
439
|
+
reason instanceof Error ? reason.message : "No fue posible enviar la respuesta."
|
|
440
|
+
);
|
|
441
|
+
} finally {
|
|
442
|
+
setBusy(false);
|
|
443
|
+
}
|
|
444
|
+
},
|
|
445
|
+
children: [
|
|
446
|
+
form.correction && /* @__PURE__ */ jsxs4("p", { role: "status", children: [
|
|
447
|
+
"Cargamos tus respuestas anteriores para que puedas corregirlas.",
|
|
448
|
+
form.correction.formChanged && " Las preguntas cambiaron; revisa los campos antes de enviar."
|
|
449
|
+
] }),
|
|
450
|
+
/* @__PURE__ */ jsx4(FormFields, { ...common, fields: form.definition.fields }),
|
|
451
|
+
/* @__PURE__ */ jsx4(FormSections, { ...common, sections: form.definition.sections }),
|
|
452
|
+
form.definition.steps.map((step) => /* @__PURE__ */ jsxs4("section", { className: classNames?.section, children: [
|
|
453
|
+
/* @__PURE__ */ jsx4("h3", { className: classNames?.sectionTitle, children: step.title }),
|
|
454
|
+
/* @__PURE__ */ jsx4("p", { children: step.description }),
|
|
455
|
+
/* @__PURE__ */ jsx4(FormFields, { ...common, fields: step.fields }),
|
|
456
|
+
/* @__PURE__ */ jsx4(FormSections, { ...common, sections: step.sections })
|
|
457
|
+
] }, step.key)),
|
|
458
|
+
error && /* @__PURE__ */ jsxs4("div", { role: "alert", children: [
|
|
459
|
+
/* @__PURE__ */ jsx4("p", { children: error === "FLOW_FORM_CHANGED" ? "El formulario cambi\xF3. Actualiza las preguntas y revisa tus respuestas antes de enviarlas." : error }),
|
|
460
|
+
/* @__PURE__ */ jsx4(
|
|
461
|
+
"button",
|
|
462
|
+
{
|
|
463
|
+
type: "button",
|
|
464
|
+
onClick: () => void onRefresh().catch(
|
|
465
|
+
() => setError("No se pudo actualizar el formulario.")
|
|
466
|
+
),
|
|
467
|
+
children: "Actualizar preguntas sin borrar mis respuestas"
|
|
468
|
+
}
|
|
469
|
+
)
|
|
470
|
+
] }),
|
|
471
|
+
/* @__PURE__ */ jsx4("button", { type: "submit", disabled: busy, className: classNames?.button, children: busy ? "Guardando\u2026" : form.definition.submitLabel })
|
|
472
|
+
]
|
|
473
|
+
}
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
|
|
287
477
|
// libs/sdk/src/react/forms.tsx
|
|
288
|
-
import { Fragment, jsx as
|
|
478
|
+
import { Fragment, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
289
479
|
var EMPTY_FORM_FIELDS = [];
|
|
290
480
|
var EMPTY_FORM_SECTIONS = [];
|
|
291
481
|
var EMPTY_FORM_STEPS = [];
|
|
@@ -297,11 +487,11 @@ function useBacanoForm(formKey, options) {
|
|
|
297
487
|
} = useBacanoState();
|
|
298
488
|
const enabled = options?.enabled ?? true;
|
|
299
489
|
const initialForm = options?.initialForm?.key === formKey ? options.initialForm : null;
|
|
300
|
-
const [form, setForm] =
|
|
490
|
+
const [form, setForm] = useState3(initialForm);
|
|
301
491
|
const formRef = useRef3(initialForm);
|
|
302
492
|
const requestVersion = useRef3(0);
|
|
303
|
-
const [loading, setLoading] =
|
|
304
|
-
const [error, setError] =
|
|
493
|
+
const [loading, setLoading] = useState3(enabled && !initialForm);
|
|
494
|
+
const [error, setError] = useState3(null);
|
|
305
495
|
const load = useCallback2(
|
|
306
496
|
async (force = false) => {
|
|
307
497
|
if (!enabled || !client) return;
|
|
@@ -346,18 +536,18 @@ function useBacanoForm(formKey, options) {
|
|
|
346
536
|
};
|
|
347
537
|
}
|
|
348
538
|
function BacanoFormInstance(props) {
|
|
349
|
-
const reactId =
|
|
539
|
+
const reactId = useId2();
|
|
350
540
|
const idPrefix = `${props.formKey}-${reactId.replace(/:/g, "")}`;
|
|
351
541
|
const { client } = useBacanoState();
|
|
352
542
|
const { form, loading, error } = useBacanoForm(props.formKey, {
|
|
353
543
|
initialForm: props.initialForm
|
|
354
544
|
});
|
|
355
|
-
const [internalValues, setValues] =
|
|
356
|
-
const [step, setStep] =
|
|
357
|
-
const [submitting, setSubmitting] =
|
|
358
|
-
const [submitted, setSubmitted] =
|
|
359
|
-
const [submissionError, setSubmissionError] =
|
|
360
|
-
const [honeypot, setHoneypot] =
|
|
545
|
+
const [internalValues, setValues] = useState3({});
|
|
546
|
+
const [step, setStep] = useState3(0);
|
|
547
|
+
const [submitting, setSubmitting] = useState3(false);
|
|
548
|
+
const [submitted, setSubmitted] = useState3(false);
|
|
549
|
+
const [submissionError, setSubmissionError] = useState3(null);
|
|
550
|
+
const [honeypot, setHoneypot] = useState3("");
|
|
361
551
|
const tracking = useBacanoFormTracking(props.formKey, {
|
|
362
552
|
visible: (props.visible ?? true) && !loading && form?.status === "ACTIVE" && !submitted
|
|
363
553
|
});
|
|
@@ -367,22 +557,23 @@ function BacanoFormInstance(props) {
|
|
|
367
557
|
const steps = form?.definition.steps ?? EMPTY_FORM_STEPS;
|
|
368
558
|
const fieldKeys = useMemo2(
|
|
369
559
|
() => new Set(
|
|
370
|
-
[
|
|
560
|
+
allFormFields([
|
|
371
561
|
...fields,
|
|
372
562
|
...sections.flatMap((section) => section.fields),
|
|
373
563
|
...steps.flatMap((formStep) => [
|
|
374
564
|
...formStep.fields,
|
|
375
565
|
...formStep.sections.flatMap((section) => section.fields)
|
|
376
566
|
])
|
|
377
|
-
].map((field) => field.key)
|
|
567
|
+
]).map((field) => field.key)
|
|
378
568
|
),
|
|
379
569
|
[fields, sections, steps]
|
|
380
570
|
);
|
|
381
|
-
const
|
|
571
|
+
const rawValues = Object.fromEntries(
|
|
382
572
|
Object.entries(props.values ?? internalValues).filter(
|
|
383
573
|
([key]) => fieldKeys.has(key)
|
|
384
574
|
)
|
|
385
575
|
);
|
|
576
|
+
const values = form ? activeFormValues(form.definition, props.values ?? internalValues) : rawValues;
|
|
386
577
|
useEffect3(() => {
|
|
387
578
|
setStep(0);
|
|
388
579
|
setValues(
|
|
@@ -395,15 +586,15 @@ function BacanoFormInstance(props) {
|
|
|
395
586
|
setHoneypot("");
|
|
396
587
|
idempotencyKey.current = crypto.randomUUID();
|
|
397
588
|
}, [fieldKeys, form?.version]);
|
|
398
|
-
if (loading) return /* @__PURE__ */
|
|
589
|
+
if (loading) return /* @__PURE__ */ jsx5(Fragment, { children: props.loadingFallback ?? null });
|
|
399
590
|
if (error && !form)
|
|
400
|
-
return /* @__PURE__ */
|
|
401
|
-
if (!form) return /* @__PURE__ */
|
|
591
|
+
return /* @__PURE__ */ jsx5(Fragment, { children: props.errorFallback?.(error) ?? props.unavailableFallback ?? null });
|
|
592
|
+
if (!form) return /* @__PURE__ */ jsx5(Fragment, { children: props.unavailableFallback ?? null });
|
|
402
593
|
if (form.status === "PAUSED") {
|
|
403
|
-
return /* @__PURE__ */
|
|
594
|
+
return /* @__PURE__ */ jsx5("div", { className: props.classNames?.message, "data-bacano-form-unavailable": true, children: props.unavailableFallback ?? form.definition.unavailableMessage });
|
|
404
595
|
}
|
|
405
596
|
if (submitted) {
|
|
406
|
-
return /* @__PURE__ */
|
|
597
|
+
return /* @__PURE__ */ jsx5("div", { className: props.classNames?.message, "data-bacano-form-success": true, children: form.definition.successMessage });
|
|
407
598
|
}
|
|
408
599
|
const isMultiStep = steps.length > 0;
|
|
409
600
|
const activeStep = isMultiStep ? steps[step] : null;
|
|
@@ -411,7 +602,10 @@ function BacanoFormInstance(props) {
|
|
|
411
602
|
const setFieldValue = (key, value) => {
|
|
412
603
|
if (value !== "" && value !== false && (!Array.isArray(value) || value.length > 0))
|
|
413
604
|
tracking.start();
|
|
414
|
-
const nextValues =
|
|
605
|
+
const nextValues = activeFormValues(form.definition, {
|
|
606
|
+
...values,
|
|
607
|
+
[key]: value
|
|
608
|
+
});
|
|
415
609
|
setValues(nextValues);
|
|
416
610
|
props.onValuesChange?.(nextValues);
|
|
417
611
|
};
|
|
@@ -467,7 +661,7 @@ function BacanoFormInstance(props) {
|
|
|
467
661
|
setSubmitting(false);
|
|
468
662
|
}
|
|
469
663
|
};
|
|
470
|
-
return /* @__PURE__ */
|
|
664
|
+
return /* @__PURE__ */ jsxs5(
|
|
471
665
|
"form",
|
|
472
666
|
{
|
|
473
667
|
noValidate: true,
|
|
@@ -476,7 +670,7 @@ function BacanoFormInstance(props) {
|
|
|
476
670
|
"data-bacano-form-version": form.version,
|
|
477
671
|
onSubmit: (event) => void submit(event),
|
|
478
672
|
children: [
|
|
479
|
-
/* @__PURE__ */
|
|
673
|
+
/* @__PURE__ */ jsxs5(
|
|
480
674
|
"div",
|
|
481
675
|
{
|
|
482
676
|
"aria-hidden": "true",
|
|
@@ -488,8 +682,8 @@ function BacanoFormInstance(props) {
|
|
|
488
682
|
clip: "rect(0 0 0 0)"
|
|
489
683
|
},
|
|
490
684
|
children: [
|
|
491
|
-
/* @__PURE__ */
|
|
492
|
-
/* @__PURE__ */
|
|
685
|
+
/* @__PURE__ */ jsx5("label", { htmlFor: `${form.key}-company-website`, children: "Empresa" }),
|
|
686
|
+
/* @__PURE__ */ jsx5(
|
|
493
687
|
"input",
|
|
494
688
|
{
|
|
495
689
|
id: `${form.key}-company-website`,
|
|
@@ -503,12 +697,12 @@ function BacanoFormInstance(props) {
|
|
|
503
697
|
]
|
|
504
698
|
}
|
|
505
699
|
),
|
|
506
|
-
/* @__PURE__ */
|
|
507
|
-
form.description ? /* @__PURE__ */
|
|
508
|
-
activeStep ? /* @__PURE__ */
|
|
509
|
-
/* @__PURE__ */
|
|
510
|
-
activeStep.description ? /* @__PURE__ */
|
|
511
|
-
/* @__PURE__ */
|
|
700
|
+
/* @__PURE__ */ jsx5("h2", { className: props.classNames?.title, children: form.name }),
|
|
701
|
+
form.description ? /* @__PURE__ */ jsx5("p", { className: props.classNames?.description, children: form.description }) : null,
|
|
702
|
+
activeStep ? /* @__PURE__ */ jsxs5("section", { className: props.classNames?.step, "data-bacano-form-step": true, children: [
|
|
703
|
+
/* @__PURE__ */ jsx5("h3", { className: props.classNames?.stepTitle, children: activeStep.title }),
|
|
704
|
+
activeStep.description ? /* @__PURE__ */ jsx5("p", { className: props.classNames?.stepDescription, children: activeStep.description }) : null,
|
|
705
|
+
/* @__PURE__ */ jsx5(
|
|
512
706
|
FormFields,
|
|
513
707
|
{
|
|
514
708
|
fields: activeStep.fields,
|
|
@@ -518,7 +712,7 @@ function BacanoFormInstance(props) {
|
|
|
518
712
|
onChange: setFieldValue
|
|
519
713
|
}
|
|
520
714
|
),
|
|
521
|
-
/* @__PURE__ */
|
|
715
|
+
/* @__PURE__ */ jsx5(
|
|
522
716
|
FormSections,
|
|
523
717
|
{
|
|
524
718
|
sections: activeStep.sections,
|
|
@@ -528,8 +722,8 @@ function BacanoFormInstance(props) {
|
|
|
528
722
|
onChange: setFieldValue
|
|
529
723
|
}
|
|
530
724
|
)
|
|
531
|
-
] }) : /* @__PURE__ */
|
|
532
|
-
/* @__PURE__ */
|
|
725
|
+
] }) : /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
726
|
+
/* @__PURE__ */ jsx5(
|
|
533
727
|
FormFields,
|
|
534
728
|
{
|
|
535
729
|
fields,
|
|
@@ -539,7 +733,7 @@ function BacanoFormInstance(props) {
|
|
|
539
733
|
onChange: setFieldValue
|
|
540
734
|
}
|
|
541
735
|
),
|
|
542
|
-
/* @__PURE__ */
|
|
736
|
+
/* @__PURE__ */ jsx5(
|
|
543
737
|
FormSections,
|
|
544
738
|
{
|
|
545
739
|
sections,
|
|
@@ -550,8 +744,8 @@ function BacanoFormInstance(props) {
|
|
|
550
744
|
}
|
|
551
745
|
)
|
|
552
746
|
] }),
|
|
553
|
-
/* @__PURE__ */
|
|
554
|
-
isMultiStep && step > 0 ? /* @__PURE__ */
|
|
747
|
+
/* @__PURE__ */ jsxs5("div", { className: props.classNames?.actions, children: [
|
|
748
|
+
isMultiStep && step > 0 ? /* @__PURE__ */ jsx5(
|
|
555
749
|
"button",
|
|
556
750
|
{
|
|
557
751
|
type: "button",
|
|
@@ -559,7 +753,7 @@ function BacanoFormInstance(props) {
|
|
|
559
753
|
children: "Anterior"
|
|
560
754
|
}
|
|
561
755
|
) : null,
|
|
562
|
-
/* @__PURE__ */
|
|
756
|
+
/* @__PURE__ */ jsx5(
|
|
563
757
|
"button",
|
|
564
758
|
{
|
|
565
759
|
type: "submit",
|
|
@@ -569,7 +763,7 @@ function BacanoFormInstance(props) {
|
|
|
569
763
|
}
|
|
570
764
|
)
|
|
571
765
|
] }),
|
|
572
|
-
submissionError ? /* @__PURE__ */
|
|
766
|
+
submissionError ? /* @__PURE__ */ jsx5(
|
|
573
767
|
"div",
|
|
574
768
|
{
|
|
575
769
|
role: "alert",
|
|
@@ -583,9 +777,10 @@ function BacanoFormInstance(props) {
|
|
|
583
777
|
);
|
|
584
778
|
}
|
|
585
779
|
function BacanoForm(props) {
|
|
586
|
-
return /* @__PURE__ */
|
|
780
|
+
return /* @__PURE__ */ jsx5(BacanoFormInstance, { ...props }, props.formKey);
|
|
587
781
|
}
|
|
588
782
|
export {
|
|
783
|
+
BacanoFlowForm,
|
|
589
784
|
BacanoForm,
|
|
590
785
|
useBacanoForm,
|
|
591
786
|
useBacanoFormTracking
|
package/react.cjs
CHANGED
|
@@ -1998,7 +1998,7 @@ var RECONCILE_PAYMENT_SESSION = (
|
|
|
1998
1998
|
$orderId: uuid!
|
|
1999
1999
|
$publicOrderToken: String!
|
|
2000
2000
|
$paymentSessionId: uuid!
|
|
2001
|
-
$gatewayTransactionId: String
|
|
2001
|
+
$gatewayTransactionId: String
|
|
2002
2002
|
) {
|
|
2003
2003
|
websiteReconcilePaymentSession(
|
|
2004
2004
|
order_id: $orderId
|
|
@@ -5458,6 +5458,52 @@ function BacanoMarketingProvider({
|
|
|
5458
5458
|
// libs/sdk/src/react/provider.tsx
|
|
5459
5459
|
var import_react6 = require("react");
|
|
5460
5460
|
|
|
5461
|
+
// libs/sdk/src/flows.ts
|
|
5462
|
+
function createFlowsClient(config) {
|
|
5463
|
+
const base = config.apiUrl.replace(/\/+$/, "") + "/api/v1/website/flows";
|
|
5464
|
+
async function request(path, body, binary = false) {
|
|
5465
|
+
const token = await config.getAccessToken?.();
|
|
5466
|
+
const response = await fetch(base + path, {
|
|
5467
|
+
method: body === void 0 ? "GET" : "POST",
|
|
5468
|
+
cache: "no-store",
|
|
5469
|
+
headers: {
|
|
5470
|
+
...token ? { Authorization: `Bearer ${token}` } : {},
|
|
5471
|
+
...body !== void 0 ? { "Content-Type": "application/json" } : {},
|
|
5472
|
+
...config.websiteSlug ? { "x-bacano-website-slug": config.websiteSlug } : {}
|
|
5473
|
+
},
|
|
5474
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
5475
|
+
});
|
|
5476
|
+
if (!response.ok) {
|
|
5477
|
+
const result = await response.json().catch(() => ({ error: "FLOW_REQUEST_FAILED" }));
|
|
5478
|
+
throw new WebsiteError(
|
|
5479
|
+
result.error ?? "FLOW_REQUEST_FAILED",
|
|
5480
|
+
result.error ?? "FLOW_REQUEST_FAILED"
|
|
5481
|
+
);
|
|
5482
|
+
}
|
|
5483
|
+
return binary ? await response.blob() : await response.json();
|
|
5484
|
+
}
|
|
5485
|
+
const stepPath = (caseId, stepId) => `/cases/${encodeURIComponent(caseId)}/steps/${encodeURIComponent(stepId)}`;
|
|
5486
|
+
return {
|
|
5487
|
+
/** Only the explicitly enabled local demo gateway accepts these credentials. */
|
|
5488
|
+
localDemoLogin: (email, password) => request("/local-session", { email, password }),
|
|
5489
|
+
logout: () => request("/logout", {}),
|
|
5490
|
+
listCases: () => request("/cases"),
|
|
5491
|
+
getJourney: (caseId) => request(`/cases/${encodeURIComponent(caseId)}`),
|
|
5492
|
+
getContent: (caseId, stepId) => request(stepPath(caseId, stepId) + "/content"),
|
|
5493
|
+
getForm: (caseId, stepId) => request(stepPath(caseId, stepId) + "/form"),
|
|
5494
|
+
getResponse: (caseId, stepId) => request(stepPath(caseId, stepId) + "/response"),
|
|
5495
|
+
getFile: (caseId, stepId, fileId) => request(
|
|
5496
|
+
stepPath(caseId, stepId) + `/files/${encodeURIComponent(fileId)}`,
|
|
5497
|
+
void 0,
|
|
5498
|
+
true
|
|
5499
|
+
),
|
|
5500
|
+
act: (caseId, command) => request(
|
|
5501
|
+
`/cases/${encodeURIComponent(caseId)}/actions`,
|
|
5502
|
+
command
|
|
5503
|
+
)
|
|
5504
|
+
};
|
|
5505
|
+
}
|
|
5506
|
+
|
|
5461
5507
|
// libs/sdk/src/modules/auth.ts
|
|
5462
5508
|
function createAuthHeaders(accessToken) {
|
|
5463
5509
|
return accessToken ? { Authorization: `Bearer ${accessToken}` } : {};
|
|
@@ -7482,6 +7528,7 @@ function createBacanoClient(config) {
|
|
|
7482
7528
|
await initialization;
|
|
7483
7529
|
},
|
|
7484
7530
|
getContext,
|
|
7531
|
+
flows: createFlowsClient(config),
|
|
7485
7532
|
auth: {
|
|
7486
7533
|
async getAccessToken() {
|
|
7487
7534
|
return config.getAccessToken ? await config.getAccessToken() : null;
|
package/react.js
CHANGED
|
@@ -1941,7 +1941,7 @@ var RECONCILE_PAYMENT_SESSION = (
|
|
|
1941
1941
|
$orderId: uuid!
|
|
1942
1942
|
$publicOrderToken: String!
|
|
1943
1943
|
$paymentSessionId: uuid!
|
|
1944
|
-
$gatewayTransactionId: String
|
|
1944
|
+
$gatewayTransactionId: String
|
|
1945
1945
|
) {
|
|
1946
1946
|
websiteReconcilePaymentSession(
|
|
1947
1947
|
order_id: $orderId
|
|
@@ -5405,6 +5405,52 @@ function BacanoMarketingProvider({
|
|
|
5405
5405
|
// libs/sdk/src/react/provider.tsx
|
|
5406
5406
|
import { useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
|
|
5407
5407
|
|
|
5408
|
+
// libs/sdk/src/flows.ts
|
|
5409
|
+
function createFlowsClient(config) {
|
|
5410
|
+
const base = config.apiUrl.replace(/\/+$/, "") + "/api/v1/website/flows";
|
|
5411
|
+
async function request(path, body, binary = false) {
|
|
5412
|
+
const token = await config.getAccessToken?.();
|
|
5413
|
+
const response = await fetch(base + path, {
|
|
5414
|
+
method: body === void 0 ? "GET" : "POST",
|
|
5415
|
+
cache: "no-store",
|
|
5416
|
+
headers: {
|
|
5417
|
+
...token ? { Authorization: `Bearer ${token}` } : {},
|
|
5418
|
+
...body !== void 0 ? { "Content-Type": "application/json" } : {},
|
|
5419
|
+
...config.websiteSlug ? { "x-bacano-website-slug": config.websiteSlug } : {}
|
|
5420
|
+
},
|
|
5421
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
5422
|
+
});
|
|
5423
|
+
if (!response.ok) {
|
|
5424
|
+
const result = await response.json().catch(() => ({ error: "FLOW_REQUEST_FAILED" }));
|
|
5425
|
+
throw new WebsiteError(
|
|
5426
|
+
result.error ?? "FLOW_REQUEST_FAILED",
|
|
5427
|
+
result.error ?? "FLOW_REQUEST_FAILED"
|
|
5428
|
+
);
|
|
5429
|
+
}
|
|
5430
|
+
return binary ? await response.blob() : await response.json();
|
|
5431
|
+
}
|
|
5432
|
+
const stepPath = (caseId, stepId) => `/cases/${encodeURIComponent(caseId)}/steps/${encodeURIComponent(stepId)}`;
|
|
5433
|
+
return {
|
|
5434
|
+
/** Only the explicitly enabled local demo gateway accepts these credentials. */
|
|
5435
|
+
localDemoLogin: (email, password) => request("/local-session", { email, password }),
|
|
5436
|
+
logout: () => request("/logout", {}),
|
|
5437
|
+
listCases: () => request("/cases"),
|
|
5438
|
+
getJourney: (caseId) => request(`/cases/${encodeURIComponent(caseId)}`),
|
|
5439
|
+
getContent: (caseId, stepId) => request(stepPath(caseId, stepId) + "/content"),
|
|
5440
|
+
getForm: (caseId, stepId) => request(stepPath(caseId, stepId) + "/form"),
|
|
5441
|
+
getResponse: (caseId, stepId) => request(stepPath(caseId, stepId) + "/response"),
|
|
5442
|
+
getFile: (caseId, stepId, fileId) => request(
|
|
5443
|
+
stepPath(caseId, stepId) + `/files/${encodeURIComponent(fileId)}`,
|
|
5444
|
+
void 0,
|
|
5445
|
+
true
|
|
5446
|
+
),
|
|
5447
|
+
act: (caseId, command) => request(
|
|
5448
|
+
`/cases/${encodeURIComponent(caseId)}/actions`,
|
|
5449
|
+
command
|
|
5450
|
+
)
|
|
5451
|
+
};
|
|
5452
|
+
}
|
|
5453
|
+
|
|
5408
5454
|
// libs/sdk/src/modules/auth.ts
|
|
5409
5455
|
function createAuthHeaders(accessToken) {
|
|
5410
5456
|
return accessToken ? { Authorization: `Bearer ${accessToken}` } : {};
|
|
@@ -7429,6 +7475,7 @@ function createBacanoClient(config) {
|
|
|
7429
7475
|
await initialization;
|
|
7430
7476
|
},
|
|
7431
7477
|
getContext,
|
|
7478
|
+
flows: createFlowsClient(config),
|
|
7432
7479
|
auth: {
|
|
7433
7480
|
async getAccessToken() {
|
|
7434
7481
|
return config.getAccessToken ? await config.getAccessToken() : null;
|