@elevasis/ui 1.0.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.
Files changed (97) hide show
  1. package/dist/api/index.d.ts +87 -0
  2. package/dist/api/index.js +3 -0
  3. package/dist/auth/context.d.ts +19 -0
  4. package/dist/auth/context.js +1 -0
  5. package/dist/auth/index.d.ts +85 -0
  6. package/dist/auth/index.js +3 -0
  7. package/dist/chunk-3KMDHCAR.js +52 -0
  8. package/dist/chunk-5UWFGBFM.js +129 -0
  9. package/dist/chunk-6BJOYF6E.js +8 -0
  10. package/dist/chunk-6M6OLGQY.js +36 -0
  11. package/dist/chunk-7AI5ZYJ4.js +202 -0
  12. package/dist/chunk-7PLEQFHO.js +18 -0
  13. package/dist/chunk-GDV44UWF.js +138 -0
  14. package/dist/chunk-GEFB5YIR.js +338 -0
  15. package/dist/chunk-HBRMWW6V.js +43 -0
  16. package/dist/chunk-HUWJXLLF.js +681 -0
  17. package/dist/chunk-J3FALDQE.js +176 -0
  18. package/dist/chunk-JKERRYVS.js +109 -0
  19. package/dist/chunk-KA7LO7U5.js +28 -0
  20. package/dist/chunk-LHQTTUL2.js +27 -0
  21. package/dist/chunk-MAAS6CGR.js +1299 -0
  22. package/dist/chunk-NE36BUGQ.js +146 -0
  23. package/dist/chunk-NGXCFBCS.js +398 -0
  24. package/dist/chunk-OEYU5O27.js +235 -0
  25. package/dist/chunk-OUHGHTE7.js +748 -0
  26. package/dist/chunk-OXVOHOP3.js +661 -0
  27. package/dist/chunk-PSLKGOBZ.js +58 -0
  28. package/dist/chunk-PYL4XW6H.js +107 -0
  29. package/dist/chunk-Q47SPRY7.js +1 -0
  30. package/dist/chunk-Q7DJKLEN.js +18 -0
  31. package/dist/chunk-RJCA5672.js +1664 -0
  32. package/dist/chunk-S66I2PYB.js +748 -0
  33. package/dist/chunk-W7ZBF5AA.js +1 -0
  34. package/dist/chunk-WNWKOCGJ.js +1067 -0
  35. package/dist/chunk-XCYKC6OZ.js +1 -0
  36. package/dist/chunk-YULUKCS6.js +56 -0
  37. package/dist/chunk-YZ6GTZXL.js +48 -0
  38. package/dist/chunk-ZGHDPDTF.js +379 -0
  39. package/dist/components/command-queue/index.css +53 -0
  40. package/dist/components/command-queue/index.d.ts +204 -0
  41. package/dist/components/command-queue/index.js +10 -0
  42. package/dist/components/forms/index.d.ts +56 -0
  43. package/dist/components/forms/index.js +2 -0
  44. package/dist/components/index.css +443 -0
  45. package/dist/components/index.d.ts +1354 -0
  46. package/dist/components/index.js +18 -0
  47. package/dist/components/monitoring/index.d.ts +66 -0
  48. package/dist/components/monitoring/index.js +2 -0
  49. package/dist/components/navigation/index.d.ts +54 -0
  50. package/dist/components/navigation/index.js +91 -0
  51. package/dist/components/notifications/index.d.ts +52 -0
  52. package/dist/components/notifications/index.js +4 -0
  53. package/dist/components/resource-definition/index.css +388 -0
  54. package/dist/components/resource-definition/index.d.ts +301 -0
  55. package/dist/components/resource-definition/index.js +3 -0
  56. package/dist/display/index.css +53 -0
  57. package/dist/display/index.d.ts +606 -0
  58. package/dist/display/index.js +6 -0
  59. package/dist/execution/index.css +388 -0
  60. package/dist/execution/index.d.ts +1090 -0
  61. package/dist/execution/index.js +4 -0
  62. package/dist/graph/index.css +388 -0
  63. package/dist/graph/index.d.ts +429 -0
  64. package/dist/graph/index.js +1 -0
  65. package/dist/hooks/index.d.ts +1927 -0
  66. package/dist/hooks/index.js +6 -0
  67. package/dist/hooks/published.d.ts +1653 -0
  68. package/dist/hooks/published.js +4 -0
  69. package/dist/index.css +505 -0
  70. package/dist/index.d.ts +7284 -0
  71. package/dist/index.js +31 -0
  72. package/dist/initialization/index.d.ts +2325 -0
  73. package/dist/initialization/index.js +4 -0
  74. package/dist/organization/index.d.ts +225 -0
  75. package/dist/organization/index.js +4 -0
  76. package/dist/profile/index.d.ts +2265 -0
  77. package/dist/profile/index.js +3 -0
  78. package/dist/provider/index.css +61 -0
  79. package/dist/provider/index.d.ts +291 -0
  80. package/dist/provider/index.js +7 -0
  81. package/dist/provider/published.d.ts +198 -0
  82. package/dist/provider/published.js +6 -0
  83. package/dist/router/context.d.ts +19 -0
  84. package/dist/router/context.js +1 -0
  85. package/dist/router/index.d.ts +31 -0
  86. package/dist/router/index.js +2 -0
  87. package/dist/sse/index.d.ts +83 -0
  88. package/dist/sse/index.js +185 -0
  89. package/dist/supabase/index.d.ts +4289 -0
  90. package/dist/supabase/index.js +47 -0
  91. package/dist/typeform/index.d.ts +458 -0
  92. package/dist/typeform/index.js +1976 -0
  93. package/dist/typeform/schemas.d.ts +67 -0
  94. package/dist/typeform/schemas.js +1 -0
  95. package/dist/utils/index.d.ts +177 -0
  96. package/dist/utils/index.js +1 -0
  97. package/package.json +88 -0
@@ -0,0 +1,1976 @@
1
+ export { answerValueSchema, checkboxWithOtherSchema, multiAnswerValueSchema, radioWithOtherSchema } from '../chunk-6M6OLGQY.js';
2
+ import { createContext, useMemo, useState, useCallback, useEffect, useContext, useRef } from 'react';
3
+ import { Box, Progress, Text, Group, Button, Kbd, Modal, Stack, Transition, Title, UnstyledButton, TextInput, Textarea, Center, Alert, Card, ActionIcon, Paper } from '@mantine/core';
4
+ import { IconArrowLeft, IconCheck, IconArrowRight, IconPlus, IconPencil, IconTrash, IconX } from '@tabler/icons-react';
5
+ import { createPortal } from 'react-dom';
6
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
+
8
+ function normalizeToPages(config) {
9
+ if (config.pages && config.pages.length > 0) {
10
+ return config.pages;
11
+ }
12
+ if (config.questions && config.questions.length > 0) {
13
+ return config.questions.map((q) => ({
14
+ id: `page-${q.id}`,
15
+ questions: [q]
16
+ }));
17
+ }
18
+ return [];
19
+ }
20
+ function validateArrayQuestion(question, value, fieldErrors) {
21
+ const items = value || [];
22
+ const completedItems = items.filter((item) => item._status === "completed");
23
+ const editingItems = items.filter((item) => item._status === "editing");
24
+ if (editingItems.length > 0) {
25
+ return "Complete or remove all pending items before continuing";
26
+ }
27
+ if (question.minItems && completedItems.length < question.minItems) {
28
+ return `At least ${question.minItems} item(s) required`;
29
+ }
30
+ if (question.maxItems && items.length > question.maxItems) {
31
+ return `Maximum ${question.maxItems} item(s) allowed`;
32
+ }
33
+ let hasNestedError = false;
34
+ for (let i = 0; i < items.length; i++) {
35
+ const item = items[i];
36
+ if (item._status !== "completed") continue;
37
+ for (const field of question.itemTemplate.fields) {
38
+ if (field.type === "content") continue;
39
+ if (field.required) {
40
+ const fieldValue = item[field.id];
41
+ const isEmpty = !fieldValue || typeof fieldValue === "string" && !fieldValue.trim() || Array.isArray(fieldValue) && fieldValue.length === 0;
42
+ if (isEmpty) {
43
+ const errorKey = `${question.id}[${i}].${field.id}`;
44
+ fieldErrors[errorKey] = `${field.question || field.id} is required`;
45
+ hasNestedError = true;
46
+ }
47
+ }
48
+ }
49
+ }
50
+ if (hasNestedError) {
51
+ return "Please complete all required fields in each item";
52
+ }
53
+ return null;
54
+ }
55
+ function evaluateCondition(condition, answers) {
56
+ if (!condition) return true;
57
+ if (typeof condition === "function") return condition(answers);
58
+ const rawValue = answers[condition.field];
59
+ let value;
60
+ if (rawValue && typeof rawValue === "object" && "type" in rawValue) {
61
+ value = rawValue.value;
62
+ } else if (Array.isArray(rawValue) && rawValue.length > 0 && typeof rawValue[0] === "object" && "type" in rawValue[0]) {
63
+ value = rawValue.map((v) => v.value);
64
+ } else {
65
+ value = rawValue;
66
+ }
67
+ switch (condition.operator) {
68
+ case "equals":
69
+ return value === condition.value;
70
+ case "notEquals":
71
+ return value !== condition.value;
72
+ case "includes":
73
+ return Array.isArray(value) ? value.includes(condition.value) : String(value ?? "").includes(condition.value);
74
+ case "notIncludes":
75
+ return Array.isArray(value) ? !value.includes(condition.value) : !String(value ?? "").includes(condition.value);
76
+ case "isEmpty":
77
+ return !value || Array.isArray(value) && value.length === 0 || value === "";
78
+ case "isNotEmpty":
79
+ return !!value && (!Array.isArray(value) || value.length > 0) && value !== "";
80
+ default:
81
+ return true;
82
+ }
83
+ }
84
+ function useTypeform(config) {
85
+ const { schema, onSubmit, onStepChange, onPageChange, initialValues } = config;
86
+ const pages = useMemo(() => normalizeToPages(config), [config]);
87
+ const [currentPageIndex, setCurrentPageIndex] = useState(0);
88
+ const [answers, setAnswers] = useState(() => {
89
+ if (initialValues) {
90
+ return initialValues;
91
+ }
92
+ return {};
93
+ });
94
+ const [errors, setErrors] = useState({});
95
+ const [isSubmitting, setIsSubmitting] = useState(false);
96
+ const [isComplete, setIsComplete] = useState(false);
97
+ const [direction, setDirection] = useState("forward");
98
+ const visiblePages = useMemo(
99
+ () => pages.filter((page) => evaluateCondition(page.condition, answers)),
100
+ [pages, answers]
101
+ );
102
+ const currentVisiblePageIndex = useMemo(() => {
103
+ if (currentPageIndex >= visiblePages.length) {
104
+ return Math.max(0, visiblePages.length - 1);
105
+ }
106
+ return currentPageIndex;
107
+ }, [currentPageIndex, visiblePages.length]);
108
+ const currentPage = visiblePages[currentVisiblePageIndex] ?? null;
109
+ const currentPageQuestions = currentPage?.questions ?? [];
110
+ const currentQuestion = currentPageQuestions[0] ?? null;
111
+ const allQuestions = useMemo(
112
+ () => visiblePages.flatMap((p) => p.questions).filter((q) => q.type !== "content"),
113
+ [visiblePages]
114
+ );
115
+ const progress = visiblePages.length > 0 ? (currentVisiblePageIndex + 1) / visiblePages.length * 100 : 0;
116
+ const isFirstPage = currentVisiblePageIndex === 0;
117
+ const isLastPage = currentVisiblePageIndex === visiblePages.length - 1;
118
+ const isFirstQuestion = isFirstPage;
119
+ const isLastQuestion = isLastPage;
120
+ const validateQuestion = useCallback(
121
+ (question, fieldErrors) => {
122
+ if (question.type === "content") {
123
+ return null;
124
+ }
125
+ const answer = answers[question.id];
126
+ if (question.type === "array") {
127
+ const arrayQ = question;
128
+ const arrayValue = answer;
129
+ const errorsCollector = fieldErrors || {};
130
+ return validateArrayQuestion(arrayQ, arrayValue, errorsCollector);
131
+ }
132
+ if (question.required) {
133
+ if (answer === void 0 || answer === "" || Array.isArray(answer) && answer.length === 0) {
134
+ return "This field is required";
135
+ }
136
+ }
137
+ if (question.type === "email" || question.type === "text" && question.inputType === "email") {
138
+ if (answer && typeof answer === "string") {
139
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
140
+ if (!emailRegex.test(answer)) {
141
+ return "Please enter a valid email address";
142
+ }
143
+ }
144
+ }
145
+ if (question.type === "checkbox") {
146
+ const checkboxQ = question;
147
+ const selectedCount = Array.isArray(answer) ? answer.length : 0;
148
+ if (checkboxQ.minSelect && selectedCount < checkboxQ.minSelect) {
149
+ return `Please select at least ${checkboxQ.minSelect} option(s)`;
150
+ }
151
+ if (checkboxQ.maxSelect && selectedCount > checkboxQ.maxSelect) {
152
+ return `Please select at most ${checkboxQ.maxSelect} option(s)`;
153
+ }
154
+ }
155
+ return null;
156
+ },
157
+ [answers]
158
+ );
159
+ const validateCurrentPage = useCallback(() => {
160
+ const pageErrors = {};
161
+ for (const question of currentPageQuestions) {
162
+ if (question.type === "content") continue;
163
+ const error = validateQuestion(question, pageErrors);
164
+ if (error) {
165
+ pageErrors[question.id] = error;
166
+ }
167
+ }
168
+ return pageErrors;
169
+ }, [currentPageQuestions, validateQuestion]);
170
+ const canProceed = useMemo(() => {
171
+ if (!currentPage) return false;
172
+ for (const question of currentPageQuestions) {
173
+ if (question.type === "content") continue;
174
+ if (validateQuestion(question) !== null) {
175
+ return false;
176
+ }
177
+ }
178
+ return true;
179
+ }, [currentPage, currentPageQuestions, validateQuestion]);
180
+ const setAnswer = useCallback(
181
+ (questionId, value) => {
182
+ setAnswers((prev) => ({ ...prev, [questionId]: value }));
183
+ setErrors((prev) => {
184
+ const next2 = { ...prev };
185
+ delete next2[questionId];
186
+ return next2;
187
+ });
188
+ },
189
+ []
190
+ );
191
+ const setArrayItemAnswer = useCallback(
192
+ (questionId, itemIndex, fieldId, value) => {
193
+ setAnswers((prev) => {
194
+ const currentArray = prev[questionId] || [];
195
+ const newArray = [...currentArray];
196
+ if (!newArray[itemIndex]) {
197
+ newArray[itemIndex] = { _status: "editing" };
198
+ }
199
+ newArray[itemIndex] = { ...newArray[itemIndex], [fieldId]: value };
200
+ return { ...prev, [questionId]: newArray };
201
+ });
202
+ setErrors((prev) => {
203
+ const next2 = { ...prev };
204
+ const errorKey = `${questionId}[${itemIndex}].${fieldId}`;
205
+ delete next2[errorKey];
206
+ return next2;
207
+ });
208
+ },
209
+ []
210
+ );
211
+ const next = useCallback(() => {
212
+ if (!currentPage) return;
213
+ const pageErrors = validateCurrentPage();
214
+ if (Object.keys(pageErrors).length > 0) {
215
+ setErrors((prev) => ({ ...prev, ...pageErrors }));
216
+ return;
217
+ }
218
+ if (currentVisiblePageIndex < visiblePages.length - 1) {
219
+ const nextIndex = currentVisiblePageIndex + 1;
220
+ setDirection("forward");
221
+ setCurrentPageIndex(nextIndex);
222
+ const nextPage = visiblePages[nextIndex];
223
+ onPageChange?.(nextIndex, nextPage);
224
+ if (nextPage.questions[0]) {
225
+ onStepChange?.(nextIndex, nextPage.questions[0]);
226
+ }
227
+ }
228
+ }, [currentVisiblePageIndex, currentPage, visiblePages, validateCurrentPage, onPageChange, onStepChange]);
229
+ const back = useCallback(() => {
230
+ if (currentVisiblePageIndex > 0) {
231
+ const prevIndex = currentVisiblePageIndex - 1;
232
+ setDirection("backward");
233
+ setCurrentPageIndex(prevIndex);
234
+ const prevPage = visiblePages[prevIndex];
235
+ onPageChange?.(prevIndex, prevPage);
236
+ if (prevPage.questions[0]) {
237
+ onStepChange?.(prevIndex, prevPage.questions[0]);
238
+ }
239
+ }
240
+ }, [currentVisiblePageIndex, visiblePages, onPageChange, onStepChange]);
241
+ const goTo = useCallback(
242
+ (index) => {
243
+ if (index >= 0 && index < visiblePages.length) {
244
+ setCurrentPageIndex(index);
245
+ const page = visiblePages[index];
246
+ onPageChange?.(index, page);
247
+ if (page.questions[0]) {
248
+ onStepChange?.(index, page.questions[0]);
249
+ }
250
+ }
251
+ },
252
+ [visiblePages, onPageChange, onStepChange]
253
+ );
254
+ const submit = useCallback(async () => {
255
+ const allErrors = {};
256
+ for (const question of allQuestions) {
257
+ const error = validateQuestion(question);
258
+ if (error) {
259
+ allErrors[question.id] = error;
260
+ }
261
+ }
262
+ if (Object.keys(allErrors).length > 0) {
263
+ setErrors(allErrors);
264
+ for (let i = 0; i < visiblePages.length; i++) {
265
+ const page = visiblePages[i];
266
+ if (page.questions.some((q) => allErrors[q.id])) {
267
+ setCurrentPageIndex(i);
268
+ break;
269
+ }
270
+ }
271
+ return;
272
+ }
273
+ if (schema) {
274
+ const result = schema.safeParse(answers);
275
+ if (!result.success) {
276
+ const zodErrors = {};
277
+ for (const issue of result.error.issues) {
278
+ const pathStr = issue.path.join(".");
279
+ const topLevelField = issue.path[0];
280
+ if (typeof topLevelField === "string") {
281
+ if (zodErrors[topLevelField]) {
282
+ zodErrors[topLevelField] += `; ${issue.message}`;
283
+ } else {
284
+ zodErrors[topLevelField] = issue.message;
285
+ }
286
+ }
287
+ if (pathStr && pathStr !== String(topLevelField)) {
288
+ zodErrors[pathStr] = issue.message;
289
+ }
290
+ }
291
+ setErrors(zodErrors);
292
+ for (let i = 0; i < visiblePages.length; i++) {
293
+ const page = visiblePages[i];
294
+ const pageQuestionIds = page.questions.map((q) => q.id);
295
+ if (pageQuestionIds.some((qId) => zodErrors[qId])) {
296
+ setCurrentPageIndex(i);
297
+ break;
298
+ }
299
+ }
300
+ return;
301
+ }
302
+ }
303
+ setIsSubmitting(true);
304
+ try {
305
+ await onSubmit(answers);
306
+ setIsComplete(true);
307
+ } catch (error) {
308
+ console.error("[Typeform] Form submission error:", error);
309
+ setErrors({ _form: error instanceof Error ? error.message : "Submission failed. Please try again." });
310
+ } finally {
311
+ setIsSubmitting(false);
312
+ }
313
+ }, [answers, allQuestions, visiblePages, schema, onSubmit, validateQuestion]);
314
+ const reset = useCallback(() => {
315
+ setCurrentPageIndex(0);
316
+ setAnswers(initialValues ? initialValues : {});
317
+ setErrors({});
318
+ setIsSubmitting(false);
319
+ setIsComplete(false);
320
+ }, [initialValues]);
321
+ const terminateAndSubmit = useCallback(
322
+ async (reason) => {
323
+ if (!config.terminationAction?.onTerminate) {
324
+ console.warn("terminateAndSubmit called but no terminationAction.onTerminate configured");
325
+ return;
326
+ }
327
+ try {
328
+ setIsSubmitting(true);
329
+ const partialData = answers;
330
+ const currentPage2 = visiblePages[currentVisiblePageIndex];
331
+ const lastPageIndex = pages.findIndex((p) => p.id === currentPage2?.id);
332
+ await config.terminationAction.onTerminate({
333
+ partialData,
334
+ lastPageIndex: lastPageIndex >= 0 ? lastPageIndex : currentVisiblePageIndex,
335
+ reason
336
+ });
337
+ setIsComplete(true);
338
+ } catch (error) {
339
+ console.error("Termination failed:", error);
340
+ throw error;
341
+ } finally {
342
+ setIsSubmitting(false);
343
+ }
344
+ },
345
+ [answers, config, currentVisiblePageIndex, visiblePages, pages]
346
+ );
347
+ return {
348
+ // State
349
+ currentIndex: currentVisiblePageIndex,
350
+ // backwards compatibility
351
+ answers,
352
+ errors,
353
+ isSubmitting,
354
+ isComplete,
355
+ direction,
356
+ // Computed
357
+ currentQuestion,
358
+ currentPage,
359
+ currentPageIndex: currentVisiblePageIndex,
360
+ pages: visiblePages,
361
+ // Return visible pages for progress bar
362
+ progress,
363
+ isFirstQuestion,
364
+ isLastQuestion,
365
+ isFirstPage,
366
+ isLastPage,
367
+ canProceed,
368
+ // Actions
369
+ next,
370
+ back,
371
+ goTo,
372
+ setAnswer,
373
+ setArrayItemAnswer,
374
+ submit,
375
+ reset,
376
+ terminateAndSubmit
377
+ };
378
+ }
379
+
380
+ // src/components/typeform/theme.ts
381
+ var defaultTheme = {
382
+ colors: {
383
+ primary: "var(--mantine-color-blue-6)",
384
+ background: "var(--color-background)",
385
+ card: "var(--mantine-color-blue-9)",
386
+ cardBorder: "var(--mantine-color-dark-5)",
387
+ text: "var(--color-text)",
388
+ textMuted: "var(--color-text-dimmed)"
389
+ },
390
+ spacing: {
391
+ questionGap: 12,
392
+ contentMaxWidth: 800,
393
+ // Wider default for better multi-question support
394
+ pageGap: 32
395
+ // Gap between questions on same page
396
+ },
397
+ animation: {
398
+ duration: 300,
399
+ easing: "ease"
400
+ },
401
+ options: {
402
+ autoAdvance: false,
403
+ compact: false
404
+ // Compact mode for multi-question pages
405
+ }
406
+ };
407
+ function mergeTheme(theme) {
408
+ return {
409
+ colors: { ...defaultTheme.colors, ...theme?.colors },
410
+ spacing: { ...defaultTheme.spacing, ...theme?.spacing },
411
+ animation: { ...defaultTheme.animation, ...theme?.animation },
412
+ options: { ...defaultTheme.options, ...theme?.options }
413
+ };
414
+ }
415
+ function TypeformProgress({
416
+ current,
417
+ total,
418
+ showPercentage = false,
419
+ usePortal = false
420
+ }) {
421
+ const { styles } = useTypeformContext();
422
+ const percentage = total > 0 ? Math.round(current / total * 100) : 0;
423
+ const [mounted, setMounted] = useState(false);
424
+ useEffect(() => {
425
+ setMounted(true);
426
+ }, []);
427
+ const content = /* @__PURE__ */ jsxs(
428
+ Box,
429
+ {
430
+ style: {
431
+ position: "fixed",
432
+ top: 0,
433
+ left: 0,
434
+ right: 0,
435
+ zIndex: 1e3,
436
+ ...styles?.progress
437
+ },
438
+ children: [
439
+ /* @__PURE__ */ jsx(
440
+ Progress,
441
+ {
442
+ value: percentage,
443
+ size: 4,
444
+ radius: 0,
445
+ transitionDuration: 300,
446
+ style: styles?.progressBar,
447
+ styles: {
448
+ root: {
449
+ background: "var(--mantine-color-dark-6)"
450
+ }
451
+ }
452
+ }
453
+ ),
454
+ showPercentage && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", ta: "right", pr: "md", pt: 4, style: styles?.progressText, children: [
455
+ percentage,
456
+ "%"
457
+ ] })
458
+ ]
459
+ }
460
+ );
461
+ if (usePortal && mounted && typeof document !== "undefined") {
462
+ return createPortal(content, document.body);
463
+ }
464
+ return content;
465
+ }
466
+ function TypeformNavigation({
467
+ onBack,
468
+ onNext,
469
+ onSubmit,
470
+ canGoBack,
471
+ canGoNext,
472
+ isLastQuestion,
473
+ isSubmitting,
474
+ terminationAction,
475
+ onTerminate
476
+ }) {
477
+ const { styles } = useTypeformContext();
478
+ const [showTerminationModal, setShowTerminationModal] = useState(false);
479
+ return /* @__PURE__ */ jsxs(
480
+ Box,
481
+ {
482
+ style: {
483
+ position: "sticky",
484
+ bottom: 0,
485
+ padding: "var(--mantine-spacing-md)",
486
+ background: "var(--color-background)",
487
+ borderTop: "1px solid var(--color-border)",
488
+ borderRadius: "var(--mantine-radius-default)",
489
+ ...styles?.navigation
490
+ },
491
+ children: [
492
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", maw: 600, mx: "auto", children: [
493
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
494
+ terminationAction && onTerminate && !canGoBack && /* @__PURE__ */ jsx(
495
+ Button,
496
+ {
497
+ variant: terminationAction.variant || "subtle",
498
+ color: terminationAction.color || "red",
499
+ onClick: () => {
500
+ if (terminationAction.confirmText) {
501
+ setShowTerminationModal(true);
502
+ } else {
503
+ onTerminate();
504
+ }
505
+ },
506
+ style: styles?.buttonTerminate,
507
+ children: terminationAction.label
508
+ }
509
+ ),
510
+ /* @__PURE__ */ jsx(
511
+ Button,
512
+ {
513
+ variant: "subtle",
514
+ color: "gray",
515
+ leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
516
+ onClick: onBack,
517
+ disabled: !canGoBack,
518
+ style: styles?.buttonBack,
519
+ styles: {
520
+ root: {
521
+ visibility: canGoBack ? "visible" : "hidden"
522
+ }
523
+ },
524
+ children: "Back"
525
+ }
526
+ )
527
+ ] }),
528
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
529
+ /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
530
+ "Press ",
531
+ /* @__PURE__ */ jsx(Kbd, { size: "xs", children: "Enter" })
532
+ ] }),
533
+ isLastQuestion ? /* @__PURE__ */ jsx(
534
+ Button,
535
+ {
536
+ rightSection: /* @__PURE__ */ jsx(IconCheck, { size: 16 }),
537
+ onClick: onSubmit,
538
+ loading: isSubmitting,
539
+ disabled: !canGoNext,
540
+ style: {
541
+ background: "var(--color-primary)",
542
+ color: "white",
543
+ transition: "all 150ms ease",
544
+ ...styles?.buttonSubmit
545
+ },
546
+ children: "Submit"
547
+ }
548
+ ) : /* @__PURE__ */ jsx(
549
+ Button,
550
+ {
551
+ rightSection: /* @__PURE__ */ jsx(IconArrowRight, { size: 16 }),
552
+ onClick: onNext,
553
+ disabled: !canGoNext,
554
+ style: {
555
+ background: "var(--color-primary)",
556
+ color: "white",
557
+ transition: "all 150ms ease",
558
+ ...styles?.buttonNext
559
+ },
560
+ children: "Continue"
561
+ }
562
+ )
563
+ ] })
564
+ ] }),
565
+ terminationAction && onTerminate && /* @__PURE__ */ jsx(
566
+ Modal,
567
+ {
568
+ opened: showTerminationModal,
569
+ onClose: () => setShowTerminationModal(false),
570
+ title: terminationAction.label,
571
+ centered: true,
572
+ children: /* @__PURE__ */ jsxs(Stack, { children: [
573
+ /* @__PURE__ */ jsx(Text, { children: terminationAction.confirmText }),
574
+ /* @__PURE__ */ jsxs(Group, { justify: "flex-end", children: [
575
+ /* @__PURE__ */ jsx(Button, { variant: "subtle", onClick: () => setShowTerminationModal(false), children: "Cancel" }),
576
+ /* @__PURE__ */ jsx(
577
+ Button,
578
+ {
579
+ color: terminationAction.color || "red",
580
+ onClick: async () => {
581
+ await onTerminate();
582
+ setShowTerminationModal(false);
583
+ },
584
+ children: "Confirm"
585
+ }
586
+ )
587
+ ] })
588
+ ] })
589
+ }
590
+ )
591
+ ]
592
+ }
593
+ );
594
+ }
595
+ var slideForward = {
596
+ in: { opacity: 1, transform: "translateY(0)" },
597
+ out: { opacity: 0, transform: "translateY(-40px)" },
598
+ transitionProperty: "opacity, transform"
599
+ };
600
+ var slideBackward = {
601
+ in: { opacity: 1, transform: "translateY(0)" },
602
+ out: { opacity: 0, transform: "translateY(40px)" },
603
+ transitionProperty: "opacity, transform"
604
+ };
605
+ function TypeformQuestionWrapper({
606
+ question,
607
+ description,
608
+ questionNumber,
609
+ isActive,
610
+ children,
611
+ error,
612
+ direction = "forward",
613
+ theme,
614
+ compact = false,
615
+ styles: customStyles
616
+ }) {
617
+ const maxWidth = theme?.spacing?.contentMaxWidth ?? 800;
618
+ return /* @__PURE__ */ jsx(
619
+ Transition,
620
+ {
621
+ mounted: isActive,
622
+ transition: direction === "backward" ? slideBackward : slideForward,
623
+ duration: theme?.animation?.duration ?? 300,
624
+ timingFunction: theme?.animation?.easing ?? "ease",
625
+ children: (transitionStyles) => /* @__PURE__ */ jsx(
626
+ Box,
627
+ {
628
+ style: {
629
+ ...transitionStyles,
630
+ display: "flex",
631
+ flexDirection: "column",
632
+ alignItems: "center",
633
+ justifyContent: "flex-start",
634
+ minHeight: "100vh",
635
+ padding: "var(--mantine-spacing-xl)",
636
+ paddingTop: "min(15vh, 80px)",
637
+ paddingBottom: 100,
638
+ // Space for navigation
639
+ overflow: "auto",
640
+ ...customStyles?.question
641
+ },
642
+ children: /* @__PURE__ */ jsxs(Box, { maw: maxWidth, w: "100%", children: [
643
+ /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", mb: "xs", style: customStyles?.questionNumber, children: [
644
+ questionNumber,
645
+ " \u2192"
646
+ ] }),
647
+ /* @__PURE__ */ jsx(
648
+ Title,
649
+ {
650
+ order: 2,
651
+ mb: "sm",
652
+ style: {
653
+ fontSize: compact ? "clamp(1.25rem, 3vw, 1.5rem)" : "clamp(1.5rem, 4vw, 2rem)",
654
+ fontWeight: 500,
655
+ lineHeight: 1.3,
656
+ ...customStyles?.questionTitle
657
+ },
658
+ children: question
659
+ }
660
+ ),
661
+ description && /* @__PURE__ */ jsx(Text, { size: compact ? "md" : "lg", c: "dimmed", mb: "xl", style: customStyles?.questionDescription, children: description }),
662
+ /* @__PURE__ */ jsx(Box, { mt: "xl", children }),
663
+ error && /* @__PURE__ */ jsx(Text, { size: "sm", c: "red", mt: "md", style: customStyles?.error, children: error })
664
+ ] })
665
+ }
666
+ )
667
+ }
668
+ );
669
+ }
670
+ function TypeformPageWrapper({
671
+ page,
672
+ pageNumber,
673
+ isActive,
674
+ direction = "forward",
675
+ theme,
676
+ compact = false,
677
+ styles: customStyles,
678
+ errors,
679
+ renderField
680
+ }) {
681
+ const maxWidth = theme?.spacing?.contentMaxWidth ?? 800;
682
+ const pageGap = theme?.spacing?.pageGap ?? 32;
683
+ const isMultiQuestion = page.questions.length > 1;
684
+ return /* @__PURE__ */ jsx(
685
+ Transition,
686
+ {
687
+ mounted: isActive,
688
+ transition: direction === "backward" ? slideBackward : slideForward,
689
+ duration: theme?.animation?.duration ?? 300,
690
+ timingFunction: theme?.animation?.easing ?? "ease",
691
+ children: (transitionStyles) => /* @__PURE__ */ jsx(
692
+ Box,
693
+ {
694
+ style: {
695
+ ...transitionStyles,
696
+ display: "flex",
697
+ flexDirection: "column",
698
+ alignItems: "center",
699
+ justifyContent: "flex-start",
700
+ minHeight: "100vh",
701
+ padding: "var(--mantine-spacing-xl)",
702
+ paddingTop: "min(15vh, 80px)",
703
+ paddingBottom: 100,
704
+ // Space for navigation
705
+ overflow: "auto",
706
+ ...customStyles?.question
707
+ },
708
+ children: /* @__PURE__ */ jsxs(Box, { maw: maxWidth, w: "100%", children: [
709
+ page.title && /* @__PURE__ */ jsxs(Fragment, { children: [
710
+ /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", mb: "xs", style: customStyles?.questionNumber, children: [
711
+ pageNumber,
712
+ " \u2192"
713
+ ] }),
714
+ /* @__PURE__ */ jsx(
715
+ Title,
716
+ {
717
+ order: 2,
718
+ mb: "sm",
719
+ style: {
720
+ fontSize: "clamp(1.5rem, 4vw, 2rem)",
721
+ fontWeight: 600,
722
+ lineHeight: 1.3,
723
+ ...customStyles?.questionTitle
724
+ },
725
+ children: page.title
726
+ }
727
+ ),
728
+ page.description && /* @__PURE__ */ jsx(Text, { size: "md", c: "dimmed", mb: "lg", style: customStyles?.questionDescription, children: page.description })
729
+ ] }),
730
+ /* @__PURE__ */ jsx(Stack, { gap: pageGap, children: page.questions.map((question) => {
731
+ const error = errors[question.id];
732
+ const showQuestionNumber = !page.title;
733
+ if (question.type === "content") {
734
+ return /* @__PURE__ */ jsx(Box, { mt: isMultiQuestion ? "sm" : "md", children: renderField(question) }, question.id);
735
+ }
736
+ return /* @__PURE__ */ jsxs(Box, { children: [
737
+ showQuestionNumber && !isMultiQuestion && /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", mb: "xs", style: customStyles?.questionNumber, children: [
738
+ pageNumber,
739
+ " \u2192"
740
+ ] }),
741
+ /* @__PURE__ */ jsxs(
742
+ Title,
743
+ {
744
+ order: isMultiQuestion ? 3 : 2,
745
+ mb: "xs",
746
+ style: {
747
+ fontSize: isMultiQuestion ? "clamp(1.125rem, 2.5vw, 1.25rem)" : compact ? "clamp(1.25rem, 3vw, 1.5rem)" : "clamp(1.5rem, 4vw, 2rem)",
748
+ fontWeight: 500,
749
+ lineHeight: 1.4
750
+ },
751
+ children: [
752
+ question.question,
753
+ question.required && /* @__PURE__ */ jsx(Text, { component: "span", c: "red", ml: 6, children: "*" })
754
+ ]
755
+ }
756
+ ),
757
+ question.description && /* @__PURE__ */ jsx(
758
+ Text,
759
+ {
760
+ size: isMultiQuestion ? "sm" : compact ? "md" : "lg",
761
+ c: "dimmed",
762
+ mb: "md",
763
+ style: customStyles?.questionDescription,
764
+ children: question.description
765
+ }
766
+ ),
767
+ /* @__PURE__ */ jsx(Box, { mt: isMultiQuestion ? "sm" : "xl", children: renderField(question) }),
768
+ error && /* @__PURE__ */ jsx(Text, { size: "sm", c: "red", mt: "md", style: customStyles?.error, children: error })
769
+ ] }, question.id);
770
+ }) })
771
+ ] })
772
+ }
773
+ )
774
+ }
775
+ );
776
+ }
777
+
778
+ // src/components/typeform/hooks.ts
779
+ function useCardStyle() {
780
+ const { config, styles } = useTypeformContext();
781
+ const theme = config.theme;
782
+ const getCardStyle = (isSelected, isHovered) => ({
783
+ display: "block",
784
+ width: "100%",
785
+ padding: "var(--mantine-spacing-sm) var(--mantine-spacing-md)",
786
+ borderRadius: "var(--mantine-radius-md)",
787
+ border: isSelected ? "var(--active-border)" : "1px solid var(--color-border)",
788
+ transition: "background-color 200ms ease, border-color 200ms ease",
789
+ ...styles?.card,
790
+ // Selection styling - must come after styles?.card to take precedence
791
+ backgroundColor: isSelected ? "var(--active-background)" : isHovered ? "var(--color-surface)" : "transparent"
792
+ });
793
+ const getKeyStyle = (isSelected, isHovered) => ({
794
+ minWidth: 24,
795
+ height: 24,
796
+ display: "inline-flex",
797
+ alignItems: "center",
798
+ justifyContent: "center",
799
+ fontSize: "var(--mantine-font-size-xs)",
800
+ backgroundColor: isSelected || isHovered ? "var(--color-primary)" : "var(--mantine-color-dark-5)",
801
+ border: "none",
802
+ transition: "background-color 200ms ease",
803
+ flexShrink: 0,
804
+ ...styles?.cardKey
805
+ });
806
+ return { getCardStyle, getKeyStyle, theme, styles };
807
+ }
808
+
809
+ // src/components/typeform/types.ts
810
+ function createPresetValue(value) {
811
+ return { type: "preset", value };
812
+ }
813
+ function createCustomValue(value) {
814
+ return { type: "custom", value };
815
+ }
816
+ function isCustomValue(answer) {
817
+ return answer.type === "custom";
818
+ }
819
+ function isPresetValue(answer) {
820
+ return answer.type === "preset";
821
+ }
822
+ function getAnswerString(answer) {
823
+ return answer?.value ?? "";
824
+ }
825
+ function getMultiAnswerStrings(answers) {
826
+ return answers.map((a) => a.value);
827
+ }
828
+ function hasCustomValue(answers) {
829
+ return answers.some((a) => a.type === "custom");
830
+ }
831
+ function getCustomValueText(answers) {
832
+ const custom = answers.find((a) => a.type === "custom");
833
+ return custom?.value;
834
+ }
835
+ function hasPresetValue(answers, value) {
836
+ return answers.some((a) => a.type === "preset" && a.value === value);
837
+ }
838
+ function extractAnswerValue(answer) {
839
+ return answer.value;
840
+ }
841
+ function extractMultiAnswerValues(answers) {
842
+ return answers.map((a) => a.value);
843
+ }
844
+ function createSurveyConfig(config) {
845
+ return config;
846
+ }
847
+ function TypeformRadioGroup({ question, value, onChange, error }) {
848
+ const { getCardStyle, getKeyStyle, styles } = useCardStyle();
849
+ const { options } = question;
850
+ const [hoveredIndex, setHoveredIndex] = useState(null);
851
+ const [otherText, setOtherText] = useState(() => {
852
+ if (value && isCustomValue(value)) {
853
+ return value.value;
854
+ }
855
+ return "";
856
+ });
857
+ useEffect(() => {
858
+ if (value && isCustomValue(value)) {
859
+ setOtherText(value.value);
860
+ } else if (!value || !isCustomValue(value)) {
861
+ setOtherText("");
862
+ }
863
+ }, [value]);
864
+ const isOtherSelected = value && isCustomValue(value);
865
+ const selectedPresetValue = value && !isCustomValue(value) ? value.value : null;
866
+ const handleOptionClick = (optionValue) => {
867
+ const isOther = optionValue.toLowerCase() === "other";
868
+ if (isOther) {
869
+ onChange(createCustomValue(otherText));
870
+ } else {
871
+ onChange(createPresetValue(optionValue));
872
+ setOtherText("");
873
+ }
874
+ };
875
+ const handleOtherTextChange = (text) => {
876
+ setOtherText(text);
877
+ onChange(createCustomValue(text));
878
+ };
879
+ return /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
880
+ options.map((option, index) => {
881
+ const isOther = option.value.toLowerCase() === "other";
882
+ const isSelected = isOther ? isOtherSelected : selectedPresetValue === option.value;
883
+ const letterKey = String.fromCharCode(65 + index);
884
+ return /* @__PURE__ */ jsx(
885
+ UnstyledButton,
886
+ {
887
+ onClick: () => handleOptionClick(option.value),
888
+ onMouseEnter: () => setHoveredIndex(index),
889
+ onMouseLeave: () => setHoveredIndex(null),
890
+ style: getCardStyle(!!isSelected, hoveredIndex === index),
891
+ children: /* @__PURE__ */ jsxs(Group, { gap: "sm", wrap: "nowrap", children: [
892
+ /* @__PURE__ */ jsx(Kbd, { size: "xs", style: getKeyStyle(!!isSelected, hoveredIndex === index), children: letterKey }),
893
+ /* @__PURE__ */ jsxs(Box, { style: { flex: 1 }, children: [
894
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, style: styles?.cardLabel, children: option.label }),
895
+ option.description && /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", mt: 2, style: styles?.cardDescription, children: option.description })
896
+ ] }),
897
+ isSelected && /* @__PURE__ */ jsx(IconCheck, { size: 16, style: { color: "var(--color-primary)", ...styles?.cardCheckmark } })
898
+ ] })
899
+ },
900
+ option.value
901
+ );
902
+ }),
903
+ isOtherSelected && /* @__PURE__ */ jsx(Box, { mt: "md", children: /* @__PURE__ */ jsx(
904
+ TextInput,
905
+ {
906
+ placeholder: "Please specify...",
907
+ value: otherText,
908
+ onChange: (e) => handleOtherTextChange(e.target.value),
909
+ styles: {
910
+ input: {
911
+ ...styles?.input,
912
+ fontSize: 16
913
+ }
914
+ }
915
+ }
916
+ ) }),
917
+ error && /* @__PURE__ */ jsx(Text, { size: "sm", c: "red", mt: "sm", style: styles?.error, children: error })
918
+ ] });
919
+ }
920
+ function TypeformCheckboxGroup({ question, value, onChange, error }) {
921
+ const { getCardStyle, getKeyStyle, styles } = useCardStyle();
922
+ const { options } = question;
923
+ const [hoveredIndex, setHoveredIndex] = useState(null);
924
+ const [otherText, setOtherText] = useState(() => getCustomValueText(value) ?? "");
925
+ useEffect(() => {
926
+ const customText = getCustomValueText(value);
927
+ if (customText !== void 0) {
928
+ setOtherText(customText);
929
+ } else if (!hasCustomValue(value)) {
930
+ setOtherText("");
931
+ }
932
+ }, [value]);
933
+ const isOtherSelected = hasCustomValue(value);
934
+ const handleToggle = (optionValue) => {
935
+ const isOther = optionValue.toLowerCase() === "other";
936
+ if (isOther) {
937
+ if (isOtherSelected) {
938
+ onChange(value.filter((v) => v.type !== "custom"));
939
+ setOtherText("");
940
+ } else {
941
+ onChange([...value, createCustomValue("")]);
942
+ }
943
+ } else {
944
+ const hasValue = hasPresetValue(value, optionValue);
945
+ if (hasValue) {
946
+ onChange(value.filter((v) => !(v.type === "preset" && v.value === optionValue)));
947
+ } else {
948
+ onChange([...value, createPresetValue(optionValue)]);
949
+ }
950
+ }
951
+ };
952
+ const handleOtherTextChange = (text) => {
953
+ setOtherText(text);
954
+ const withoutCustom = value.filter((v) => v.type !== "custom");
955
+ onChange([...withoutCustom, createCustomValue(text)]);
956
+ };
957
+ return /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
958
+ options.map((option, index) => {
959
+ const isOther = option.value.toLowerCase() === "other";
960
+ const isSelected = isOther ? isOtherSelected : hasPresetValue(value, option.value);
961
+ const letterKey = String.fromCharCode(65 + index);
962
+ return /* @__PURE__ */ jsx(
963
+ UnstyledButton,
964
+ {
965
+ onClick: () => handleToggle(option.value),
966
+ onMouseEnter: () => setHoveredIndex(index),
967
+ onMouseLeave: () => setHoveredIndex(null),
968
+ style: getCardStyle(isSelected, hoveredIndex === index),
969
+ children: /* @__PURE__ */ jsxs(Group, { gap: "sm", wrap: "nowrap", children: [
970
+ /* @__PURE__ */ jsx(Kbd, { size: "xs", style: getKeyStyle(isSelected, hoveredIndex === index), children: letterKey }),
971
+ /* @__PURE__ */ jsx(
972
+ Box,
973
+ {
974
+ style: {
975
+ width: 20,
976
+ height: 20,
977
+ borderRadius: 4,
978
+ border: `2px solid ${isSelected ? "var(--color-primary)" : "var(--mantine-color-dark-4)"}`,
979
+ backgroundColor: isSelected ? "var(--color-primary)" : "transparent",
980
+ display: "flex",
981
+ alignItems: "center",
982
+ justifyContent: "center",
983
+ transition: "all 150ms ease",
984
+ flexShrink: 0
985
+ },
986
+ children: isSelected && /* @__PURE__ */ jsx(IconCheck, { size: 14, style: { color: "white" } })
987
+ }
988
+ ),
989
+ /* @__PURE__ */ jsxs(Box, { style: { flex: 1 }, children: [
990
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, style: styles?.cardLabel, children: option.label }),
991
+ option.description && /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", mt: 2, style: styles?.cardDescription, children: option.description })
992
+ ] })
993
+ ] })
994
+ },
995
+ option.value
996
+ );
997
+ }),
998
+ isOtherSelected && /* @__PURE__ */ jsx(Box, { mt: "md", children: /* @__PURE__ */ jsx(
999
+ TextInput,
1000
+ {
1001
+ placeholder: "Please specify...",
1002
+ value: otherText,
1003
+ onChange: (e) => handleOtherTextChange(e.target.value),
1004
+ styles: {
1005
+ input: {
1006
+ ...styles?.input,
1007
+ fontSize: 16
1008
+ }
1009
+ }
1010
+ }
1011
+ ) }),
1012
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", mt: "xs", children: "Select all that apply" }),
1013
+ error && /* @__PURE__ */ jsx(Text, { size: "sm", c: "red", mt: "sm", style: styles?.error, children: error })
1014
+ ] });
1015
+ }
1016
+ function TypeformTextInput({ question, value, onChange, error, onSubmit }) {
1017
+ const { config, styles } = useTypeformContext();
1018
+ const theme = config.theme;
1019
+ const handleKeyDown = (e) => {
1020
+ if (e.key === "Enter" && !e.shiftKey && question.type !== "textarea") {
1021
+ e.preventDefault();
1022
+ onSubmit?.();
1023
+ }
1024
+ };
1025
+ const focusBorderColor = theme?.colors?.primary ?? "var(--mantine-color-blue-6)";
1026
+ const textColor = theme?.colors?.text ?? void 0;
1027
+ if (question.type === "textarea") {
1028
+ const textareaQuestion = question;
1029
+ return /* @__PURE__ */ jsx(
1030
+ Textarea,
1031
+ {
1032
+ value,
1033
+ onChange: (e) => onChange(e.target.value),
1034
+ placeholder: textareaQuestion.placeholder || "Type your answer here...",
1035
+ error,
1036
+ rows: textareaQuestion.rows || 4,
1037
+ autoFocus: true,
1038
+ styles: {
1039
+ input: {
1040
+ ...styles?.textarea,
1041
+ color: textColor,
1042
+ "&:focus": {
1043
+ borderColor: focusBorderColor
1044
+ }
1045
+ }
1046
+ }
1047
+ }
1048
+ );
1049
+ }
1050
+ const textQuestion = question;
1051
+ return /* @__PURE__ */ jsx(
1052
+ TextInput,
1053
+ {
1054
+ value,
1055
+ onChange: (e) => onChange(e.target.value),
1056
+ placeholder: textQuestion.placeholder || "Type your answer here...",
1057
+ type: textQuestion.inputType || "text",
1058
+ error,
1059
+ onKeyDown: handleKeyDown,
1060
+ autoFocus: true,
1061
+ styles: {
1062
+ input: {
1063
+ ...styles?.input,
1064
+ color: textColor,
1065
+ "&:focus": {
1066
+ borderBottomColor: focusBorderColor
1067
+ }
1068
+ }
1069
+ }
1070
+ }
1071
+ );
1072
+ }
1073
+ function TypeformArrayField({
1074
+ question,
1075
+ value = [],
1076
+ onChange,
1077
+ errors,
1078
+ renderField,
1079
+ theme: _theme
1080
+ }) {
1081
+ const {
1082
+ itemTemplate,
1083
+ minItems = 0,
1084
+ maxItems,
1085
+ addLabel = "Add item",
1086
+ removeLabel = "Remove",
1087
+ itemLabel,
1088
+ summaryFields
1089
+ } = question;
1090
+ const [localErrors, setLocalErrors] = useState({});
1091
+ const hasEditingItems = value.some((item) => item._status === "editing");
1092
+ const canAdd = (maxItems === void 0 || value.length < maxItems) && !hasEditingItems;
1093
+ const getCanRemove = (item) => {
1094
+ const completedCount = value.filter((i) => i._status === "completed").length;
1095
+ if (item._status === "editing") return true;
1096
+ return completedCount > minItems;
1097
+ };
1098
+ const handleAdd = () => {
1099
+ if (!canAdd) return;
1100
+ const newItem = { _status: "editing" };
1101
+ itemTemplate.fields.forEach((field) => {
1102
+ if (field.type !== "content") {
1103
+ if (field.type === "checkbox") {
1104
+ newItem[field.id] = [];
1105
+ } else {
1106
+ newItem[field.id] = "";
1107
+ }
1108
+ }
1109
+ });
1110
+ onChange([...value, newItem]);
1111
+ };
1112
+ const handleRemove = (index) => {
1113
+ const newValue = value.filter((_, i) => i !== index);
1114
+ onChange(newValue);
1115
+ const newLocalErrors = { ...localErrors };
1116
+ Object.keys(newLocalErrors).forEach((key) => {
1117
+ if (key.startsWith(`${question.id}[${index}]`)) {
1118
+ delete newLocalErrors[key];
1119
+ }
1120
+ });
1121
+ setLocalErrors(newLocalErrors);
1122
+ };
1123
+ const handleCancel = (index) => {
1124
+ handleRemove(index);
1125
+ };
1126
+ const handleItemChange = (index, fieldId, fieldValue) => {
1127
+ const newValue = [...value];
1128
+ newValue[index] = { ...newValue[index], [fieldId]: fieldValue };
1129
+ onChange(newValue);
1130
+ const errorKey = `${question.id}[${index}].${fieldId}`;
1131
+ if (localErrors[errorKey]) {
1132
+ const newLocalErrors = { ...localErrors };
1133
+ delete newLocalErrors[errorKey];
1134
+ setLocalErrors(newLocalErrors);
1135
+ }
1136
+ };
1137
+ const validateItem = (index) => {
1138
+ const item = value[index];
1139
+ if (!item) return false;
1140
+ const newErrors = {};
1141
+ let hasError = false;
1142
+ for (const field of itemTemplate.fields) {
1143
+ if (field.type === "content") continue;
1144
+ if (field.required) {
1145
+ const fieldValue = item[field.id];
1146
+ const isEmpty = !fieldValue || typeof fieldValue === "string" && !fieldValue.trim() || Array.isArray(fieldValue) && fieldValue.length === 0;
1147
+ if (isEmpty) {
1148
+ const errorKey = `${question.id}[${index}].${field.id}`;
1149
+ newErrors[errorKey] = `${field.question || field.id} is required`;
1150
+ hasError = true;
1151
+ }
1152
+ }
1153
+ }
1154
+ setLocalErrors((prev) => ({ ...prev, ...newErrors }));
1155
+ return !hasError;
1156
+ };
1157
+ const handleComplete = (index) => {
1158
+ if (validateItem(index)) {
1159
+ const newValue = [...value];
1160
+ newValue[index] = { ...newValue[index], _status: "completed" };
1161
+ onChange(newValue);
1162
+ }
1163
+ };
1164
+ const handleEdit = (index) => {
1165
+ const newValue = [...value];
1166
+ newValue[index] = { ...newValue[index], _status: "editing" };
1167
+ onChange(newValue);
1168
+ };
1169
+ const getItemLabel = (index) => {
1170
+ if (itemLabel) return itemLabel(index);
1171
+ return `Item ${index + 1}`;
1172
+ };
1173
+ const getFieldError = (index, fieldId) => {
1174
+ const errorKey = `${question.id}[${index}].${fieldId}`;
1175
+ return localErrors[errorKey] || errors?.[errorKey];
1176
+ };
1177
+ const getFieldValue = (item, field) => {
1178
+ if (field.type === "content") return "";
1179
+ const val = item[field.id];
1180
+ if (val === void 0) {
1181
+ if (field.type === "checkbox") return [];
1182
+ return "";
1183
+ }
1184
+ if (typeof val === "string" || Array.isArray(val)) return val;
1185
+ return "";
1186
+ };
1187
+ const getFieldLabel = (fieldId) => {
1188
+ const field = itemTemplate.fields.find((f) => f.id === fieldId);
1189
+ if (!field || field.type === "content") return fieldId;
1190
+ return field.question || fieldId;
1191
+ };
1192
+ const renderSummary = (item, index) => {
1193
+ const fieldsToShow = summaryFields || itemTemplate.fields.slice(0, 4).map((f) => f.id);
1194
+ const summaryLines = [];
1195
+ for (const fieldId of fieldsToShow) {
1196
+ if (fieldId === "_status") continue;
1197
+ const val = item[fieldId];
1198
+ if (!val) continue;
1199
+ const label = getFieldLabel(fieldId);
1200
+ let displayValue = "";
1201
+ if (typeof val === "string") {
1202
+ displayValue = val.length > 60 ? val.substring(0, 60) + "..." : val;
1203
+ } else if (Array.isArray(val)) {
1204
+ displayValue = val.join(", ");
1205
+ }
1206
+ if (displayValue) {
1207
+ summaryLines.push({ label, value: displayValue });
1208
+ }
1209
+ }
1210
+ return /* @__PURE__ */ jsxs(
1211
+ Card,
1212
+ {
1213
+ withBorder: true,
1214
+ padding: "md",
1215
+ style: {
1216
+ backgroundColor: "rgba(32, 32, 35, 0.45)",
1217
+ borderColor: "rgba(255, 255, 255, 0.12)",
1218
+ borderRadius: 12
1219
+ },
1220
+ children: [
1221
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "flex-start", mb: "xs", children: [
1222
+ /* @__PURE__ */ jsx(Text, { fw: 600, size: "sm", c: "dimmed", style: { fontFamily: "var(--mantine-font-family-headings)" }, children: getItemLabel(index) }),
1223
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1224
+ /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", color: "gray", onClick: () => handleEdit(index), "aria-label": "Edit", size: "sm", children: /* @__PURE__ */ jsx(IconPencil, { size: 14 }) }),
1225
+ getCanRemove(item) && /* @__PURE__ */ jsx(
1226
+ ActionIcon,
1227
+ {
1228
+ variant: "subtle",
1229
+ color: "red",
1230
+ onClick: () => handleRemove(index),
1231
+ "aria-label": removeLabel,
1232
+ size: "sm",
1233
+ children: /* @__PURE__ */ jsx(IconTrash, { size: 14 })
1234
+ }
1235
+ )
1236
+ ] })
1237
+ ] }),
1238
+ /* @__PURE__ */ jsx(
1239
+ Paper,
1240
+ {
1241
+ p: "sm",
1242
+ style: {
1243
+ backgroundColor: "rgba(255, 255, 255, 0.03)",
1244
+ borderRadius: 8
1245
+ },
1246
+ children: summaryLines.length > 0 ? /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
1247
+ summaryLines[0] && /* @__PURE__ */ jsx(Text, { size: "sm", style: { color: "#fff" }, children: summaryLines[0].value }),
1248
+ summaryLines.length > 1 && /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: summaryLines.slice(1).map((line) => line.value).join(" \xB7 ") })
1249
+ ] }) : /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", fs: "italic", children: "No data" })
1250
+ }
1251
+ )
1252
+ ]
1253
+ },
1254
+ index
1255
+ );
1256
+ };
1257
+ const renderEditingForm = (item, index) => {
1258
+ return /* @__PURE__ */ jsxs(
1259
+ Card,
1260
+ {
1261
+ withBorder: true,
1262
+ padding: "md",
1263
+ style: {
1264
+ backgroundColor: "rgba(32, 32, 35, 0.45)",
1265
+ borderColor: "rgba(0, 153, 255, 0.3)",
1266
+ borderRadius: 12
1267
+ },
1268
+ children: [
1269
+ /* @__PURE__ */ jsx(Text, { fw: 500, mb: "md", children: getItemLabel(index) }),
1270
+ /* @__PURE__ */ jsx(Stack, { gap: "sm", children: itemTemplate.fields.map((field) => /* @__PURE__ */ jsx(Box, { children: renderField(
1271
+ field,
1272
+ index,
1273
+ `${question.id}[${index}].${field.id}`,
1274
+ getFieldValue(item, field),
1275
+ (fieldValue) => handleItemChange(index, field.id, fieldValue),
1276
+ getFieldError(index, field.id)
1277
+ ) }, field.id)) }),
1278
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", mt: "lg", children: [
1279
+ /* @__PURE__ */ jsx(Button, { variant: "filled", leftSection: /* @__PURE__ */ jsx(IconCheck, { size: 16 }), onClick: () => handleComplete(index), children: "Complete" }),
1280
+ /* @__PURE__ */ jsx(Button, { variant: "subtle", color: "gray", leftSection: /* @__PURE__ */ jsx(IconX, { size: 16 }), onClick: () => handleCancel(index), children: "Cancel" })
1281
+ ] })
1282
+ ]
1283
+ },
1284
+ index
1285
+ );
1286
+ };
1287
+ return /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
1288
+ value.map(
1289
+ (item, index) => item._status === "completed" ? renderSummary(item, index) : renderEditingForm(item, index)
1290
+ ),
1291
+ canAdd && /* @__PURE__ */ jsx(Button, { variant: "light", leftSection: /* @__PURE__ */ jsx(IconPlus, { size: 16 }), onClick: handleAdd, children: addLabel })
1292
+ ] });
1293
+ }
1294
+ var TypeformContext = createContext(null);
1295
+ function useTypeformContext() {
1296
+ const context = useContext(TypeformContext);
1297
+ if (!context) {
1298
+ throw new Error("useTypeformContext must be used within a TypeformSurvey");
1299
+ }
1300
+ return context;
1301
+ }
1302
+ function TypeformSurvey({ config, className, styles, hideProgress }) {
1303
+ const typeform = useTypeform(config);
1304
+ const {
1305
+ currentPage,
1306
+ currentPageIndex,
1307
+ pages,
1308
+ answers,
1309
+ errors,
1310
+ isFirstPage,
1311
+ isLastPage,
1312
+ isSubmitting,
1313
+ isComplete,
1314
+ canProceed,
1315
+ direction,
1316
+ next,
1317
+ back,
1318
+ submit,
1319
+ setAnswer,
1320
+ terminateAndSubmit
1321
+ } = typeform;
1322
+ const nextRef = useRef(next);
1323
+ nextRef.current = next;
1324
+ const mergedTheme = mergeTheme(config.theme);
1325
+ const isCompact = mergedTheme.options?.compact ?? false;
1326
+ const isMultiQuestion = (currentPage?.questions.length ?? 0) > 1;
1327
+ const parseMarkdown = (text) => {
1328
+ const lines = text.split("\n");
1329
+ return lines.map((line, idx) => {
1330
+ const parts = line.split(/(\*\*.*?\*\*)/);
1331
+ const renderedLine = parts.map((part, partIdx) => {
1332
+ if (part.startsWith("**") && part.endsWith("**")) {
1333
+ return /* @__PURE__ */ jsx(
1334
+ Text,
1335
+ {
1336
+ component: "span",
1337
+ fw: 700,
1338
+ style: {
1339
+ color: "#fff"
1340
+ },
1341
+ children: part.slice(2, -2)
1342
+ },
1343
+ partIdx
1344
+ );
1345
+ }
1346
+ return part;
1347
+ });
1348
+ return /* @__PURE__ */ jsxs("span", { children: [
1349
+ renderedLine,
1350
+ idx < lines.length - 1 && /* @__PURE__ */ jsx("br", {})
1351
+ ] }, idx);
1352
+ });
1353
+ };
1354
+ const renderContent = (question) => {
1355
+ const { content, style = "default" } = question;
1356
+ switch (style) {
1357
+ case "callout":
1358
+ return /* @__PURE__ */ jsx(
1359
+ Paper,
1360
+ {
1361
+ p: "lg",
1362
+ style: {
1363
+ backgroundColor: "rgba(32, 32, 35, 0.45)",
1364
+ border: "1px solid rgba(255, 255, 255, 0.07)",
1365
+ borderRadius: 12,
1366
+ backdropFilter: "blur(24px)",
1367
+ WebkitBackdropFilter: "blur(24px)"
1368
+ },
1369
+ children: /* @__PURE__ */ jsx(Text, { size: "sm", style: { lineHeight: 1.6, color: "rgb(212, 212, 216)" }, children: parseMarkdown(content) })
1370
+ },
1371
+ question.id
1372
+ );
1373
+ case "script":
1374
+ return /* @__PURE__ */ jsx(
1375
+ Text,
1376
+ {
1377
+ fs: "italic",
1378
+ size: "sm",
1379
+ style: {
1380
+ color: "rgb(161, 161, 170)",
1381
+ padding: "8px 16px",
1382
+ borderLeft: "3px solid rgba(0, 153, 255, 0.3)"
1383
+ },
1384
+ children: parseMarkdown(content)
1385
+ },
1386
+ question.id
1387
+ );
1388
+ case "info":
1389
+ return /* @__PURE__ */ jsx(
1390
+ Paper,
1391
+ {
1392
+ p: "lg",
1393
+ style: {
1394
+ backgroundColor: "rgba(32, 32, 35, 0.45)",
1395
+ border: "1px solid rgba(255, 255, 255, 0.07)",
1396
+ borderRadius: 12,
1397
+ backdropFilter: "blur(24px)",
1398
+ WebkitBackdropFilter: "blur(24px)"
1399
+ },
1400
+ children: /* @__PURE__ */ jsx(Text, { size: "sm", style: { lineHeight: 1.6, color: "rgb(212, 212, 216)" }, children: parseMarkdown(content) })
1401
+ },
1402
+ question.id
1403
+ );
1404
+ case "warning":
1405
+ return /* @__PURE__ */ jsxs(
1406
+ Paper,
1407
+ {
1408
+ p: "md",
1409
+ style: {
1410
+ backgroundColor: "rgba(249, 115, 22, 0.1)",
1411
+ border: "1px solid rgba(249, 115, 22, 0.2)",
1412
+ borderRadius: 12
1413
+ },
1414
+ children: [
1415
+ /* @__PURE__ */ jsx(
1416
+ Text,
1417
+ {
1418
+ size: "sm",
1419
+ fw: 600,
1420
+ mb: "xs",
1421
+ style: { color: "rgb(251, 146, 60)", fontFamily: "var(--mantine-font-family-headings)" },
1422
+ children: "Note"
1423
+ }
1424
+ ),
1425
+ /* @__PURE__ */ jsx(Text, { size: "sm", style: { lineHeight: 1.6, color: "#fff" }, children: parseMarkdown(content) })
1426
+ ]
1427
+ },
1428
+ question.id
1429
+ );
1430
+ default:
1431
+ return /* @__PURE__ */ jsx(Text, { style: { color: "#fff" }, children: parseMarkdown(content) }, question.id);
1432
+ }
1433
+ };
1434
+ const renderField = (question) => {
1435
+ const questionId = question.id;
1436
+ const error = errors[questionId];
1437
+ switch (question.type) {
1438
+ case "content":
1439
+ return renderContent(question);
1440
+ case "radio": {
1441
+ const rawValue = answers[questionId];
1442
+ let answerValue;
1443
+ if (rawValue && typeof rawValue === "object" && "type" in rawValue) {
1444
+ answerValue = rawValue;
1445
+ } else if (typeof rawValue === "string" && rawValue) {
1446
+ answerValue = createPresetValue(rawValue);
1447
+ }
1448
+ const handleRadioChange = (value) => {
1449
+ setAnswer(questionId, value);
1450
+ if (mergedTheme.options?.autoAdvance && !isLastPage && !isMultiQuestion && !isCustomValue(value)) {
1451
+ setTimeout(() => {
1452
+ nextRef.current();
1453
+ }, 400);
1454
+ }
1455
+ };
1456
+ return /* @__PURE__ */ jsx(
1457
+ TypeformRadioGroup,
1458
+ {
1459
+ question,
1460
+ value: answerValue,
1461
+ onChange: handleRadioChange,
1462
+ error
1463
+ },
1464
+ questionId
1465
+ );
1466
+ }
1467
+ case "checkbox": {
1468
+ const rawValue = answers[questionId];
1469
+ let multiValue = [];
1470
+ if (Array.isArray(rawValue)) {
1471
+ if (rawValue.length > 0 && typeof rawValue[0] === "object" && "type" in rawValue[0]) {
1472
+ multiValue = rawValue;
1473
+ } else {
1474
+ multiValue = rawValue.map((v) => createPresetValue(v));
1475
+ }
1476
+ }
1477
+ return /* @__PURE__ */ jsx(
1478
+ TypeformCheckboxGroup,
1479
+ {
1480
+ question,
1481
+ value: multiValue,
1482
+ onChange: (value) => setAnswer(questionId, value),
1483
+ error
1484
+ },
1485
+ questionId
1486
+ );
1487
+ }
1488
+ case "text":
1489
+ case "email":
1490
+ case "textarea":
1491
+ return /* @__PURE__ */ jsx(
1492
+ TypeformTextInput,
1493
+ {
1494
+ question,
1495
+ value: answers[questionId] || "",
1496
+ onChange: (value) => setAnswer(questionId, value),
1497
+ error,
1498
+ onSubmit: () => {
1499
+ if (isLastPage) {
1500
+ submit();
1501
+ } else if (canProceed) {
1502
+ next();
1503
+ }
1504
+ }
1505
+ },
1506
+ questionId
1507
+ );
1508
+ case "array":
1509
+ return /* @__PURE__ */ jsx(
1510
+ TypeformArrayField,
1511
+ {
1512
+ question,
1513
+ value: answers[questionId] || [],
1514
+ onChange: (value) => setAnswer(questionId, value),
1515
+ errors,
1516
+ renderField: renderNestedField,
1517
+ theme: mergedTheme
1518
+ },
1519
+ questionId
1520
+ );
1521
+ default:
1522
+ return null;
1523
+ }
1524
+ };
1525
+ const renderNestedField = (field, _itemIndex, fieldId, value, onFieldChange, error) => {
1526
+ switch (field.type) {
1527
+ case "content":
1528
+ return renderContent(field);
1529
+ case "radio": {
1530
+ const answerValue = typeof value === "string" && value ? createPresetValue(value) : void 0;
1531
+ return /* @__PURE__ */ jsxs(Box, { mt: "md", children: [
1532
+ /* @__PURE__ */ jsxs(Text, { size: "sm", fw: 500, mb: 4, children: [
1533
+ field.question,
1534
+ field.required && /* @__PURE__ */ jsx(Text, { component: "span", c: "red", ml: 4, children: "*" })
1535
+ ] }),
1536
+ /* @__PURE__ */ jsx(
1537
+ TypeformRadioGroup,
1538
+ {
1539
+ question: field,
1540
+ value: answerValue,
1541
+ onChange: (newValue) => onFieldChange(newValue.value),
1542
+ error
1543
+ }
1544
+ )
1545
+ ] }, fieldId);
1546
+ }
1547
+ case "checkbox": {
1548
+ const multiValue = Array.isArray(value) ? value.map((v) => createPresetValue(v)) : [];
1549
+ return /* @__PURE__ */ jsxs(Box, { mt: "md", children: [
1550
+ /* @__PURE__ */ jsxs(Text, { size: "sm", fw: 500, mb: 4, children: [
1551
+ field.question,
1552
+ field.required && /* @__PURE__ */ jsx(Text, { component: "span", c: "red", ml: 4, children: "*" })
1553
+ ] }),
1554
+ /* @__PURE__ */ jsx(
1555
+ TypeformCheckboxGroup,
1556
+ {
1557
+ question: field,
1558
+ value: multiValue,
1559
+ onChange: (newValue) => onFieldChange(newValue.map((v) => v.value)),
1560
+ error
1561
+ }
1562
+ )
1563
+ ] }, fieldId);
1564
+ }
1565
+ case "text":
1566
+ case "email":
1567
+ case "textarea":
1568
+ return /* @__PURE__ */ jsxs(Box, { mt: "md", children: [
1569
+ /* @__PURE__ */ jsxs(Text, { size: "sm", fw: 500, mb: 4, children: [
1570
+ field.question,
1571
+ field.required && /* @__PURE__ */ jsx(Text, { component: "span", c: "red", ml: 4, children: "*" })
1572
+ ] }),
1573
+ /* @__PURE__ */ jsx(
1574
+ TypeformTextInput,
1575
+ {
1576
+ question: field,
1577
+ value: value || "",
1578
+ onChange: onFieldChange,
1579
+ error
1580
+ }
1581
+ )
1582
+ ] }, fieldId);
1583
+ default:
1584
+ return null;
1585
+ }
1586
+ };
1587
+ const handleKeyDown = useCallback(
1588
+ (e) => {
1589
+ if (isComplete) return;
1590
+ if (e.key === "Enter" && !e.shiftKey) {
1591
+ const activeElement = document.activeElement;
1592
+ if (activeElement?.tagName === "TEXTAREA") return;
1593
+ if (isMultiQuestion) return;
1594
+ if (isLastPage) {
1595
+ submit();
1596
+ } else if (canProceed) {
1597
+ next();
1598
+ }
1599
+ return;
1600
+ }
1601
+ if (!isMultiQuestion && currentPage?.questions[0]) {
1602
+ const question = currentPage.questions[0];
1603
+ if (question.type === "radio" || question.type === "checkbox") {
1604
+ const key = e.key.toUpperCase();
1605
+ const index = key.charCodeAt(0) - 65;
1606
+ const options = question.type === "radio" ? question.options : question.options;
1607
+ if (index >= 0 && index < options.length) {
1608
+ const option = options[index];
1609
+ if (question.type === "radio") {
1610
+ const newValue = createPresetValue(option.value);
1611
+ setAnswer(question.id, newValue);
1612
+ if (mergedTheme.options?.autoAdvance && !isLastPage && option.value.toLowerCase() !== "other") {
1613
+ setTimeout(() => nextRef.current(), 400);
1614
+ }
1615
+ } else {
1616
+ const rawValue = answers[question.id];
1617
+ let currentValue = [];
1618
+ if (Array.isArray(rawValue)) {
1619
+ if (rawValue.length > 0 && typeof rawValue[0] === "object" && "type" in rawValue[0]) {
1620
+ currentValue = rawValue;
1621
+ } else {
1622
+ currentValue = rawValue.map((v) => createPresetValue(v));
1623
+ }
1624
+ }
1625
+ const hasValue = currentValue.some((v) => v.type === "preset" && v.value === option.value);
1626
+ if (hasValue) {
1627
+ setAnswer(
1628
+ question.id,
1629
+ currentValue.filter((v) => !(v.type === "preset" && v.value === option.value))
1630
+ );
1631
+ } else {
1632
+ setAnswer(question.id, [...currentValue, createPresetValue(option.value)]);
1633
+ }
1634
+ }
1635
+ }
1636
+ }
1637
+ }
1638
+ },
1639
+ [currentPage, answers, isLastPage, isComplete, canProceed, isMultiQuestion, next, submit, setAnswer, mergedTheme]
1640
+ );
1641
+ useEffect(() => {
1642
+ window.addEventListener("keydown", handleKeyDown);
1643
+ return () => window.removeEventListener("keydown", handleKeyDown);
1644
+ }, [handleKeyDown]);
1645
+ if (isComplete) {
1646
+ return /* @__PURE__ */ jsx(Box, { className, style: styles?.container, children: /* @__PURE__ */ jsx(
1647
+ Center,
1648
+ {
1649
+ style: {
1650
+ // minHeight: '100vh',
1651
+ padding: "var(--mantine-spacing-xl)"
1652
+ // ...styles?.completion,
1653
+ },
1654
+ children: /* @__PURE__ */ jsxs(Stack, { align: "center", gap: "lg", children: [
1655
+ /* @__PURE__ */ jsx(
1656
+ Box,
1657
+ {
1658
+ style: {
1659
+ width: 80,
1660
+ height: 80,
1661
+ borderRadius: "50%",
1662
+ background: "var(--mantine-color-green-6)",
1663
+ display: "flex",
1664
+ alignItems: "center",
1665
+ justifyContent: "center",
1666
+ ...styles?.completionIcon
1667
+ },
1668
+ children: /* @__PURE__ */ jsx(IconCheck, { size: 40, color: "white" })
1669
+ }
1670
+ ),
1671
+ /* @__PURE__ */ jsx(Title, { order: 3, style: styles?.completionTitle, children: "Thank you!" }),
1672
+ /* @__PURE__ */ jsx(Text, { size: "lg", c: "dimmed", ta: "center", maw: 400, style: styles?.completionText, children: "Your response has been recorded." })
1673
+ ] })
1674
+ }
1675
+ ) });
1676
+ }
1677
+ const contextValue = {
1678
+ ...typeform,
1679
+ config,
1680
+ styles
1681
+ };
1682
+ return /* @__PURE__ */ jsx(TypeformContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
1683
+ Box,
1684
+ {
1685
+ className,
1686
+ style: {
1687
+ minHeight: "100vh",
1688
+ background: mergedTheme.colors?.background,
1689
+ ...styles?.container
1690
+ },
1691
+ children: [
1692
+ !hideProgress && /* @__PURE__ */ jsx(TypeformProgress, { current: currentPageIndex + 1, total: pages.length, usePortal: true }),
1693
+ errors._form && /* @__PURE__ */ jsx(Box, { px: "xl", pt: "md", children: /* @__PURE__ */ jsx(Alert, { color: "red", variant: "light", title: "Submission Error", children: errors._form }) }),
1694
+ currentPage && /* @__PURE__ */ jsx(
1695
+ TypeformPageWrapper,
1696
+ {
1697
+ page: currentPage,
1698
+ pageNumber: currentPageIndex + 1,
1699
+ isActive: true,
1700
+ direction,
1701
+ theme: mergedTheme,
1702
+ compact: isCompact,
1703
+ styles: {
1704
+ question: styles?.question,
1705
+ questionNumber: styles?.questionNumber,
1706
+ questionTitle: styles?.questionTitle,
1707
+ questionDescription: styles?.questionDescription,
1708
+ error: styles?.error
1709
+ },
1710
+ errors,
1711
+ renderField
1712
+ }
1713
+ ),
1714
+ /* @__PURE__ */ jsx(
1715
+ TypeformNavigation,
1716
+ {
1717
+ onBack: back,
1718
+ onNext: next,
1719
+ onSubmit: submit,
1720
+ canGoBack: !isFirstPage,
1721
+ canGoNext: canProceed,
1722
+ isLastQuestion: isLastPage,
1723
+ isSubmitting,
1724
+ terminationAction: config.terminationAction,
1725
+ onTerminate: terminateAndSubmit
1726
+ }
1727
+ )
1728
+ ]
1729
+ }
1730
+ ) });
1731
+ }
1732
+
1733
+ // src/components/typeform/presets/brochure-style.ts
1734
+ var brochureTheme = {
1735
+ colors: {
1736
+ primary: "#0099ff",
1737
+ background: "transparent",
1738
+ // Use parent container background
1739
+ card: "rgba(24, 24, 27, 0.4)",
1740
+ // zinc-900/40
1741
+ cardBorder: "rgba(255, 255, 255, 0.07)",
1742
+ text: "#ffffff",
1743
+ textMuted: "rgb(161, 161, 170)"
1744
+ // zinc-400
1745
+ },
1746
+ spacing: {
1747
+ questionGap: 14,
1748
+ contentMaxWidth: 900,
1749
+ // Wider for better multi-question support
1750
+ pageGap: 36
1751
+ // Gap between questions on same page
1752
+ },
1753
+ animation: {
1754
+ duration: 400,
1755
+ easing: "cubic-bezier(0.4, 0, 0.2, 1)"
1756
+ },
1757
+ options: {
1758
+ autoAdvance: false,
1759
+ compact: false
1760
+ // Can be enabled for multi-question pages
1761
+ }
1762
+ };
1763
+ var brochureStyles = {
1764
+ // Container - transparent, no min-height when inside glass card
1765
+ container: {
1766
+ backgroundColor: "transparent",
1767
+ minHeight: "auto"
1768
+ },
1769
+ // Question wrapper - centered content with generous padding
1770
+ question: {
1771
+ minHeight: "auto",
1772
+ padding: "56px 40px",
1773
+ paddingBottom: 120
1774
+ },
1775
+ // Question number - subtle badge style
1776
+ questionNumber: {
1777
+ fontSize: 13,
1778
+ fontWeight: 600,
1779
+ textTransform: "uppercase",
1780
+ letterSpacing: "0.15em",
1781
+ color: "#0099ff",
1782
+ marginBottom: 16
1783
+ },
1784
+ // Question title - cleaner, more modern sizing
1785
+ questionTitle: {
1786
+ fontSize: "clamp(1.5rem, 3.5vw, 1.875rem)",
1787
+ fontWeight: 600,
1788
+ letterSpacing: "-0.025em",
1789
+ lineHeight: 1.3,
1790
+ color: "#ffffff",
1791
+ marginBottom: 12
1792
+ },
1793
+ // Question description - muted text
1794
+ questionDescription: {
1795
+ fontSize: 16,
1796
+ lineHeight: 1.5,
1797
+ color: "rgb(161, 161, 170)"
1798
+ // zinc-400
1799
+ },
1800
+ // Option cards - glass morphism effect with comfortable padding
1801
+ card: {
1802
+ backgroundColor: "rgba(24, 24, 27, 0.4)",
1803
+ backdropFilter: "blur(24px)",
1804
+ WebkitBackdropFilter: "blur(24px)",
1805
+ border: "1px solid rgba(255, 255, 255, 0.07)",
1806
+ borderRadius: 12,
1807
+ padding: "16px 20px",
1808
+ boxShadow: "0 8px 32px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.03)",
1809
+ transition: "all 300ms cubic-bezier(0.4, 0, 0.2, 1)"
1810
+ },
1811
+ // Selected card - blue glow effect
1812
+ cardSelected: {
1813
+ backgroundColor: "rgba(0, 153, 255, 0.08)",
1814
+ border: "1px solid rgba(0, 153, 255, 0.3)",
1815
+ boxShadow: "0 8px 32px rgba(0, 0, 0, 0.3), 0 0 60px -15px rgba(0, 153, 255, 0.25), inset 0 1px 0 rgba(0, 153, 255, 0.1)"
1816
+ },
1817
+ // Hovered card - subtle lift
1818
+ cardHovered: {
1819
+ backgroundColor: "rgba(24, 24, 27, 0.6)",
1820
+ border: "1px solid rgba(255, 255, 255, 0.12)",
1821
+ transform: "translateY(-2px)"
1822
+ },
1823
+ // Card label text - more readable
1824
+ cardLabel: {
1825
+ fontSize: 15,
1826
+ fontWeight: 500,
1827
+ lineHeight: 1.4,
1828
+ color: "#ffffff"
1829
+ },
1830
+ // Card description text
1831
+ cardDescription: {
1832
+ fontSize: 14,
1833
+ lineHeight: 1.5,
1834
+ color: "rgb(113, 113, 122)"
1835
+ // zinc-500
1836
+ },
1837
+ // Keyboard hint badge
1838
+ cardKey: {
1839
+ backgroundColor: "rgba(255, 255, 255, 0.08)",
1840
+ border: "none",
1841
+ borderRadius: 6,
1842
+ fontSize: 12,
1843
+ fontWeight: 600
1844
+ },
1845
+ // Checkmark icon
1846
+ cardCheckmark: {
1847
+ color: "#0099ff"
1848
+ },
1849
+ // Text input styling - cleaner, modern sizing
1850
+ input: {
1851
+ backgroundColor: "transparent",
1852
+ border: "none",
1853
+ borderBottom: "2px solid rgba(255, 255, 255, 0.1)",
1854
+ borderRadius: 0,
1855
+ fontSize: 16,
1856
+ fontWeight: 400,
1857
+ color: "#ffffff",
1858
+ padding: "12px 0",
1859
+ transition: "border-color 200ms ease"
1860
+ },
1861
+ // Textarea styling
1862
+ textarea: {
1863
+ backgroundColor: "rgba(24, 24, 27, 0.4)",
1864
+ backdropFilter: "blur(24px)",
1865
+ WebkitBackdropFilter: "blur(24px)",
1866
+ border: "1px solid rgba(255, 255, 255, 0.07)",
1867
+ borderRadius: 12,
1868
+ fontSize: 16,
1869
+ lineHeight: 1.5,
1870
+ color: "#ffffff",
1871
+ padding: 16
1872
+ },
1873
+ // Progress bar container - fixed at top of viewport
1874
+ progress: {
1875
+ position: "fixed",
1876
+ top: 0,
1877
+ left: 0,
1878
+ right: 0,
1879
+ zIndex: 1e3,
1880
+ backgroundColor: "transparent"
1881
+ },
1882
+ // Progress bar itself
1883
+ progressBar: {
1884
+ height: 3
1885
+ },
1886
+ // Progress percentage text
1887
+ progressText: {
1888
+ color: "rgb(113, 113, 122)",
1889
+ // zinc-500
1890
+ fontSize: 11
1891
+ },
1892
+ // Navigation footer - relative positioning inside glass card
1893
+ navigation: {
1894
+ position: "relative",
1895
+ backgroundColor: "rgba(0, 0, 0, 0.4)",
1896
+ backdropFilter: "blur(24px)",
1897
+ WebkitBackdropFilter: "blur(24px)",
1898
+ borderTop: "1px solid rgba(255, 255, 255, 0.05)",
1899
+ borderRadius: "0 0 16px 16px",
1900
+ padding: "20px 40px"
1901
+ },
1902
+ // Back button
1903
+ buttonBack: {
1904
+ color: "rgb(161, 161, 170)",
1905
+ // zinc-400
1906
+ backgroundColor: "transparent",
1907
+ border: "none"
1908
+ },
1909
+ // Next/Continue button
1910
+ buttonNext: {
1911
+ backgroundColor: "#0099ff",
1912
+ color: "#ffffff",
1913
+ border: "none",
1914
+ borderRadius: 8,
1915
+ padding: "12px 24px",
1916
+ fontSize: 15,
1917
+ fontWeight: 600,
1918
+ boxShadow: "0 4px 20px rgba(0, 153, 255, 0.3)",
1919
+ transition: "all 200ms ease"
1920
+ },
1921
+ // Submit button (uses gradient, so keep background shorthand)
1922
+ buttonSubmit: {
1923
+ background: "linear-gradient(135deg, #0099ff 0%, #0066cc 100%)",
1924
+ color: "#ffffff",
1925
+ border: "none",
1926
+ borderRadius: 8,
1927
+ padding: "12px 28px",
1928
+ fontSize: 15,
1929
+ fontWeight: 600,
1930
+ boxShadow: "0 4px 20px rgba(0, 153, 255, 0.4)",
1931
+ transition: "all 200ms ease"
1932
+ },
1933
+ // Terminate button (No Show) - true red, not pink
1934
+ buttonTerminate: {
1935
+ backgroundColor: "#dc2626",
1936
+ color: "#ffffff",
1937
+ border: "none",
1938
+ borderRadius: 8,
1939
+ padding: "10px 20px",
1940
+ fontSize: 14,
1941
+ fontWeight: 600,
1942
+ transition: "all 200ms ease"
1943
+ },
1944
+ // Completion screen
1945
+ completion: {
1946
+ backgroundColor: "transparent"
1947
+ },
1948
+ // Completion icon (uses gradient, so keep background shorthand)
1949
+ completionIcon: {
1950
+ width: 100,
1951
+ height: 100,
1952
+ background: "linear-gradient(135deg, #0099ff 0%, #0066cc 100%)",
1953
+ boxShadow: "0 8px 40px rgba(0, 153, 255, 0.4)"
1954
+ },
1955
+ // Completion title
1956
+ completionTitle: {
1957
+ fontSize: 32,
1958
+ fontWeight: 600,
1959
+ color: "#ffffff"
1960
+ },
1961
+ // Completion text
1962
+ completionText: {
1963
+ fontSize: 18,
1964
+ color: "rgb(161, 161, 170)"
1965
+ // zinc-400
1966
+ },
1967
+ // Error message
1968
+ error: {
1969
+ color: "rgb(248, 113, 113)",
1970
+ // red-400
1971
+ fontSize: 14,
1972
+ marginTop: 12
1973
+ }
1974
+ };
1975
+
1976
+ export { TypeformArrayField, TypeformCheckboxGroup, TypeformNavigation, TypeformProgress, TypeformQuestionWrapper, TypeformRadioGroup, TypeformSurvey, TypeformTextInput, brochureStyles, brochureTheme, createCustomValue, createPresetValue, createSurveyConfig, defaultTheme, extractAnswerValue, extractMultiAnswerValues, getAnswerString, getCustomValueText, getMultiAnswerStrings, hasCustomValue, hasPresetValue, isCustomValue, isPresetValue, mergeTheme, useCardStyle, useTypeform, useTypeformContext };