@fogpipe/forma-react 0.17.1 → 0.18.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 (36) hide show
  1. package/README.md +82 -0
  2. package/dist/FormRenderer-D_ZVK44t.d.ts +558 -0
  3. package/dist/chunk-5K4QITFH.js +1276 -0
  4. package/dist/chunk-5K4QITFH.js.map +1 -0
  5. package/dist/defaults/index.d.ts +56 -0
  6. package/dist/defaults/index.js +895 -0
  7. package/dist/defaults/index.js.map +1 -0
  8. package/dist/defaults/styles/forma-defaults.css +696 -0
  9. package/dist/index.d.ts +7 -559
  10. package/dist/index.js +28 -1292
  11. package/dist/index.js.map +1 -1
  12. package/package.json +17 -3
  13. package/src/__tests__/defaults/components.test.tsx +818 -0
  14. package/src/__tests__/defaults/integration.test.tsx +494 -0
  15. package/src/__tests__/defaults/layout.test.tsx +298 -0
  16. package/src/defaults/DefaultFormRenderer.tsx +43 -0
  17. package/src/defaults/componentMap.ts +45 -0
  18. package/src/defaults/components/ArrayField.tsx +183 -0
  19. package/src/defaults/components/BooleanInput.tsx +32 -0
  20. package/src/defaults/components/ComputedDisplay.tsx +26 -0
  21. package/src/defaults/components/DateInput.tsx +59 -0
  22. package/src/defaults/components/DisplayField.tsx +15 -0
  23. package/src/defaults/components/FallbackField.tsx +35 -0
  24. package/src/defaults/components/MatrixField.tsx +98 -0
  25. package/src/defaults/components/MultiSelectInput.tsx +51 -0
  26. package/src/defaults/components/NumberInput.tsx +73 -0
  27. package/src/defaults/components/ObjectField.tsx +22 -0
  28. package/src/defaults/components/SelectInput.tsx +44 -0
  29. package/src/defaults/components/TextInput.tsx +48 -0
  30. package/src/defaults/components/TextareaInput.tsx +46 -0
  31. package/src/defaults/index.ts +33 -0
  32. package/src/defaults/layout/FieldWrapper.tsx +83 -0
  33. package/src/defaults/layout/FormLayout.tsx +34 -0
  34. package/src/defaults/layout/PageWrapper.tsx +18 -0
  35. package/src/defaults/layout/WizardLayout.tsx +130 -0
  36. package/src/defaults/styles/forma-defaults.css +696 -0
@@ -0,0 +1,130 @@
1
+ import React, { useCallback } from "react";
2
+ import type { LayoutProps } from "../../types.js";
3
+ import { useFormaContext } from "../../context.js";
4
+
5
+ export function WizardLayout({
6
+ children,
7
+ onSubmit,
8
+ isSubmitting,
9
+ }: LayoutProps) {
10
+ const { wizard } = useFormaContext();
11
+
12
+ const handleNext = useCallback(() => {
13
+ if (!wizard) return;
14
+ wizard.touchCurrentPageFields();
15
+ if (wizard.validateCurrentPage()) {
16
+ wizard.nextPage();
17
+ }
18
+ }, [wizard]);
19
+
20
+ const handleSubmit = useCallback(
21
+ (e: React.FormEvent<HTMLFormElement>) => {
22
+ e.preventDefault();
23
+
24
+ if (!wizard) {
25
+ onSubmit();
26
+ return;
27
+ }
28
+
29
+ const nativeEvent = e.nativeEvent as SubmitEvent;
30
+ const submitter = nativeEvent.submitter as HTMLButtonElement | null;
31
+
32
+ if (wizard.isLastPage && submitter?.dataset.action === "submit") {
33
+ onSubmit();
34
+ } else if (!wizard.isLastPage) {
35
+ handleNext();
36
+ }
37
+ },
38
+ [wizard, onSubmit, handleNext],
39
+ );
40
+
41
+ // Fallback to simple form layout if no wizard
42
+ if (!wizard) {
43
+ return (
44
+ <form
45
+ className="forma-form"
46
+ onSubmit={handleSubmit}
47
+ noValidate
48
+ >
49
+ {children}
50
+ <div className="forma-form__actions">
51
+ <button
52
+ type="submit"
53
+ className="forma-button forma-button--primary forma-submit"
54
+ disabled={isSubmitting}
55
+ aria-busy={isSubmitting || undefined}
56
+ >
57
+ {isSubmitting ? "Submitting..." : "Submit"}
58
+ </button>
59
+ </div>
60
+ </form>
61
+ );
62
+ }
63
+
64
+ return (
65
+ <form className="forma-wizard" onSubmit={handleSubmit} noValidate>
66
+ {/* Step indicator */}
67
+ <div className="forma-wizard__steps" role="navigation" aria-label="Form progress">
68
+ {wizard.pages.map((page, index) => {
69
+ const isCompleted = index < wizard.currentPageIndex;
70
+ const isCurrent = index === wizard.currentPageIndex;
71
+ const stepClass = [
72
+ "forma-step",
73
+ isCompleted && "forma-step--completed",
74
+ isCurrent && "forma-step--current",
75
+ !isCompleted && !isCurrent && "forma-step--upcoming",
76
+ ]
77
+ .filter(Boolean)
78
+ .join(" ");
79
+
80
+ return (
81
+ <div key={page.id} className={stepClass} aria-current={isCurrent ? "step" : undefined}>
82
+ <span className="forma-step__indicator">
83
+ {isCompleted ? "\u2713" : index + 1}
84
+ </span>
85
+ <span className="forma-step__label">{page.title}</span>
86
+ </div>
87
+ );
88
+ })}
89
+ </div>
90
+
91
+ {/* Page content */}
92
+ {children}
93
+
94
+ {/* Navigation */}
95
+ <div className="forma-wizard__nav">
96
+ {wizard.hasPreviousPage ? (
97
+ <button
98
+ type="button"
99
+ className="forma-button forma-button--secondary"
100
+ onClick={() => wizard.previousPage()}
101
+ >
102
+ Previous
103
+ </button>
104
+ ) : (
105
+ <div />
106
+ )}
107
+
108
+ {wizard.isLastPage ? (
109
+ <button
110
+ type="submit"
111
+ data-action="submit"
112
+ className={`forma-button forma-button--primary forma-submit${isSubmitting ? " forma-submit--loading" : ""}`}
113
+ disabled={isSubmitting}
114
+ aria-busy={isSubmitting || undefined}
115
+ >
116
+ {isSubmitting ? "Submitting..." : "Submit"}
117
+ </button>
118
+ ) : (
119
+ <button
120
+ type="button"
121
+ className="forma-button forma-button--primary"
122
+ onClick={handleNext}
123
+ >
124
+ Next
125
+ </button>
126
+ )}
127
+ </div>
128
+ </form>
129
+ );
130
+ }