@datum-cloud/datum-ui 0.5.0 → 0.6.0-alpha.a37bf9a

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 (175) hide show
  1. package/README.md +79 -40
  2. package/dist/adapter-context-rWveHhDd.mjs +25 -0
  3. package/dist/autocomplete/index.mjs +1 -1
  4. package/dist/{autocomplete-V5-qslzS.mjs → autocomplete-CkYJueBL.mjs} +2 -2
  5. package/dist/autosearch/index.mjs +199 -0
  6. package/dist/{calendar-date-picker-DWK94_DC.mjs → calendar-date-picker-CDT-8Ha8.mjs} +2 -1
  7. package/dist/combobox/index.mjs +2 -0
  8. package/dist/combobox-B-C9lJeD.mjs +97 -0
  9. package/dist/components/features/autocomplete/autocomplete.d.ts +1 -1
  10. package/dist/components/features/autocomplete/autocomplete.d.ts.map +1 -1
  11. package/dist/components/features/autocomplete/autocomplete.types.d.ts +2 -0
  12. package/dist/components/features/autocomplete/autocomplete.types.d.ts.map +1 -1
  13. package/dist/components/features/autosearch/autosearch.d.ts +35 -0
  14. package/dist/components/features/autosearch/autosearch.d.ts.map +1 -0
  15. package/dist/components/features/autosearch/autosearch.types.d.ts +51 -0
  16. package/dist/components/features/autosearch/autosearch.types.d.ts.map +1 -0
  17. package/dist/components/features/autosearch/index.d.ts +3 -0
  18. package/dist/components/features/autosearch/index.d.ts.map +1 -0
  19. package/dist/components/features/calendar-date-picker/calendar-date-picker.d.ts +2 -1
  20. package/dist/components/features/calendar-date-picker/calendar-date-picker.d.ts.map +1 -1
  21. package/dist/components/features/combobox/combobox.d.ts +27 -0
  22. package/dist/components/features/combobox/combobox.d.ts.map +1 -0
  23. package/dist/components/features/combobox/index.d.ts +3 -0
  24. package/dist/components/features/combobox/index.d.ts.map +1 -0
  25. package/dist/components/features/combobox/types.d.ts +84 -0
  26. package/dist/components/features/combobox/types.d.ts.map +1 -0
  27. package/dist/components/features/date-time-picker/date-time-picker.d.ts +9 -0
  28. package/dist/components/features/date-time-picker/date-time-picker.d.ts.map +1 -0
  29. package/dist/components/features/date-time-picker/index.d.ts +3 -0
  30. package/dist/components/features/date-time-picker/index.d.ts.map +1 -0
  31. package/dist/components/features/date-time-picker/types.d.ts +59 -0
  32. package/dist/components/features/date-time-picker/types.d.ts.map +1 -0
  33. package/dist/components/features/date-time-picker/utils/format.d.ts +13 -0
  34. package/dist/components/features/date-time-picker/utils/format.d.ts.map +1 -0
  35. package/dist/components/features/date-time-picker/utils/index.d.ts +3 -0
  36. package/dist/components/features/date-time-picker/utils/index.d.ts.map +1 -0
  37. package/dist/components/features/date-time-picker/utils/timezone.d.ts +23 -0
  38. package/dist/components/features/date-time-picker/utils/timezone.d.ts.map +1 -0
  39. package/dist/components/features/form/adapter-context.d.ts +17 -0
  40. package/dist/components/features/form/adapter-context.d.ts.map +1 -0
  41. package/dist/components/features/form/adapter-types.d.ts +126 -0
  42. package/dist/components/features/form/adapter-types.d.ts.map +1 -0
  43. package/dist/components/features/form/adapters/conform/conform-adapter.d.ts +9 -0
  44. package/dist/components/features/form/adapters/conform/conform-adapter.d.ts.map +1 -0
  45. package/dist/components/features/form/adapters/conform/conform-provider.d.ts +22 -0
  46. package/dist/components/features/form/adapters/conform/conform-provider.d.ts.map +1 -0
  47. package/dist/components/features/form/adapters/conform/index.d.ts +3 -0
  48. package/dist/components/features/form/adapters/conform/index.d.ts.map +1 -0
  49. package/dist/components/features/form/adapters/rhf/index.d.ts +3 -0
  50. package/dist/components/features/form/adapters/rhf/index.d.ts.map +1 -0
  51. package/dist/components/features/form/adapters/rhf/rhf-adapter.d.ts +10 -0
  52. package/dist/components/features/form/adapters/rhf/rhf-adapter.d.ts.map +1 -0
  53. package/dist/components/features/form/adapters/rhf/rhf-provider.d.ts +22 -0
  54. package/dist/components/features/form/adapters/rhf/rhf-provider.d.ts.map +1 -0
  55. package/dist/components/features/form/components/form-autocomplete.d.ts.map +1 -1
  56. package/dist/components/features/form/components/form-autosearch.d.ts +37 -0
  57. package/dist/components/features/form/components/form-autosearch.d.ts.map +1 -0
  58. package/dist/components/features/form/components/form-checkbox.d.ts.map +1 -1
  59. package/dist/components/features/form/components/form-combobox.d.ts +80 -0
  60. package/dist/components/features/form/components/form-combobox.d.ts.map +1 -0
  61. package/dist/components/features/form/components/form-copy-box.d.ts +3 -0
  62. package/dist/components/features/form/components/form-copy-box.d.ts.map +1 -1
  63. package/dist/components/features/form/components/form-custom.d.ts.map +1 -1
  64. package/dist/components/features/form/components/form-date-picker.d.ts +40 -0
  65. package/dist/components/features/form/components/form-date-picker.d.ts.map +1 -0
  66. package/dist/components/features/form/components/form-date-time-picker.d.ts +39 -0
  67. package/dist/components/features/form/components/form-date-time-picker.d.ts.map +1 -0
  68. package/dist/components/features/form/components/form-dialog.d.ts.map +1 -1
  69. package/dist/components/features/form/components/form-field-array.d.ts +5 -17
  70. package/dist/components/features/form/components/form-field-array.d.ts.map +1 -1
  71. package/dist/components/features/form/components/form-field.d.ts +7 -21
  72. package/dist/components/features/form/components/form-field.d.ts.map +1 -1
  73. package/dist/components/features/form/components/form-input-group.d.ts +4 -4
  74. package/dist/components/features/form/components/form-input-group.d.ts.map +1 -1
  75. package/dist/components/features/form/components/form-input.d.ts.map +1 -1
  76. package/dist/components/features/form/components/form-radio-group.d.ts.map +1 -1
  77. package/dist/components/features/form/components/form-root.d.ts +5 -25
  78. package/dist/components/features/form/components/form-root.d.ts.map +1 -1
  79. package/dist/components/features/form/components/form-select.d.ts.map +1 -1
  80. package/dist/components/features/form/components/form-switch.d.ts.map +1 -1
  81. package/dist/components/features/form/components/form-textarea.d.ts.map +1 -1
  82. package/dist/components/features/form/components/form-time-picker.d.ts +21 -0
  83. package/dist/components/features/form/components/form-time-picker.d.ts.map +1 -0
  84. package/dist/components/features/form/components/form-transfer.d.ts +37 -0
  85. package/dist/components/features/form/components/form-transfer.d.ts.map +1 -0
  86. package/dist/components/features/form/components/index.d.ts +7 -1
  87. package/dist/components/features/form/components/index.d.ts.map +1 -1
  88. package/dist/components/features/form/components/stepper/form-stepper.d.ts.map +1 -1
  89. package/dist/components/features/form/context/form-context.d.ts +2 -2
  90. package/dist/components/features/form/context/form-context.d.ts.map +1 -1
  91. package/dist/components/features/form/hooks/index.d.ts +1 -1
  92. package/dist/components/features/form/hooks/index.d.ts.map +1 -1
  93. package/dist/components/features/form/hooks/use-field.d.ts +12 -18
  94. package/dist/components/features/form/hooks/use-field.d.ts.map +1 -1
  95. package/dist/components/features/form/hooks/use-form-state.d.ts +36 -0
  96. package/dist/components/features/form/hooks/use-form-state.d.ts.map +1 -0
  97. package/dist/components/features/form/hooks/use-watch.d.ts +9 -20
  98. package/dist/components/features/form/hooks/use-watch.d.ts.map +1 -1
  99. package/dist/components/features/form/index.d.ts +69 -45
  100. package/dist/components/features/form/index.d.ts.map +1 -1
  101. package/dist/components/features/form/stepper/index.d.ts +17 -0
  102. package/dist/components/features/form/stepper/index.d.ts.map +1 -0
  103. package/dist/components/features/form/types/index.d.ts +78 -32
  104. package/dist/components/features/form/types/index.d.ts.map +1 -1
  105. package/dist/components/features/form/utils/get-field-constraints.d.ts +33 -0
  106. package/dist/components/features/form/utils/get-field-constraints.d.ts.map +1 -0
  107. package/dist/components/features/form/utils/get-schema-defaults.d.ts +24 -0
  108. package/dist/components/features/form/utils/get-schema-defaults.d.ts.map +1 -0
  109. package/dist/components/features/form/utils/zod-helpers.d.ts +12 -0
  110. package/dist/components/features/form/utils/zod-helpers.d.ts.map +1 -0
  111. package/dist/components/features/time-picker/index.d.ts +3 -0
  112. package/dist/components/features/time-picker/index.d.ts.map +1 -0
  113. package/dist/components/features/time-picker/time-picker.d.ts +22 -0
  114. package/dist/components/features/time-picker/time-picker.d.ts.map +1 -0
  115. package/dist/components/features/time-picker/types.d.ts +31 -0
  116. package/dist/components/features/time-picker/types.d.ts.map +1 -0
  117. package/dist/components/features/transfer/components/index.d.ts +9 -0
  118. package/dist/components/features/transfer/components/index.d.ts.map +1 -0
  119. package/dist/components/features/transfer/components/transfer-group.d.ts +7 -0
  120. package/dist/components/features/transfer/components/transfer-group.d.ts.map +1 -0
  121. package/dist/components/features/transfer/components/transfer-item.d.ts +10 -0
  122. package/dist/components/features/transfer/components/transfer-item.d.ts.map +1 -0
  123. package/dist/components/features/transfer/components/transfer-panel.d.ts +18 -0
  124. package/dist/components/features/transfer/components/transfer-panel.d.ts.map +1 -0
  125. package/dist/components/features/transfer/components/transfer-search.d.ts +9 -0
  126. package/dist/components/features/transfer/components/transfer-search.d.ts.map +1 -0
  127. package/dist/components/features/transfer/hooks/use-transfer-dnd.d.ts +26 -0
  128. package/dist/components/features/transfer/hooks/use-transfer-dnd.d.ts.map +1 -0
  129. package/dist/components/features/transfer/hooks/use-transfer-state.d.ts +20 -0
  130. package/dist/components/features/transfer/hooks/use-transfer-state.d.ts.map +1 -0
  131. package/dist/components/features/transfer/index.d.ts +3 -0
  132. package/dist/components/features/transfer/index.d.ts.map +1 -0
  133. package/dist/components/features/transfer/transfer.d.ts +6 -0
  134. package/dist/components/features/transfer/transfer.d.ts.map +1 -0
  135. package/dist/components/features/transfer/types.d.ts +69 -0
  136. package/dist/components/features/transfer/types.d.ts.map +1 -0
  137. package/dist/data-table/index.mjs +1 -1
  138. package/dist/date-picker/index.mjs +2 -2
  139. package/dist/date-time-picker/index.mjs +2 -0
  140. package/dist/date-time-picker-BomrW07W.mjs +178 -0
  141. package/dist/form/adapters/conform/index.mjs +346 -0
  142. package/dist/form/adapters/rhf/index.mjs +282 -0
  143. package/dist/form/index.mjs +3 -2
  144. package/dist/form/stepper/index.mjs +545 -0
  145. package/dist/form-CxrQ92WO.mjs +1685 -0
  146. package/dist/form-context-Ccxm-wqL.mjs +17 -0
  147. package/dist/get-field-constraints-BicgDkfH.mjs +51 -0
  148. package/dist/grid/index.mjs +1 -1
  149. package/dist/hooks/index.mjs +2 -2
  150. package/dist/index.mjs +16 -15
  151. package/dist/input-number/index.mjs +1 -1
  152. package/dist/map/index.mjs +1 -1
  153. package/dist/{map-ClxB41Hg.mjs → map-CWIQ-eql.mjs} +1 -1
  154. package/dist/more-actions/index.mjs +1 -1
  155. package/dist/page-title/index.mjs +1 -1
  156. package/dist/stepper/index.mjs +1 -320
  157. package/dist/stepper-DvIOp0hh.mjs +321 -0
  158. package/dist/tag-input/index.mjs +1 -1
  159. package/dist/task-queue/index.mjs +1 -1
  160. package/dist/time-picker/index.mjs +2 -0
  161. package/dist/time-picker-BoF7pZZ2.mjs +43 -0
  162. package/dist/transfer/index.mjs +2 -0
  163. package/dist/transfer-B2n8pgEQ.mjs +260 -0
  164. package/package.json +63 -2
  165. package/dist/form-Co3fM4B7.mjs +0 -2114
  166. /package/dist/{col-q-J99UHe.mjs → col-1T0Q3SlH.mjs} +0 -0
  167. /package/dist/{hooks-Cb7YlxN4.mjs → hooks-D8r2M2U6.mjs} +0 -0
  168. /package/dist/{input-number-mDB-5M5C.mjs → input-number-a7uydAsw.mjs} +0 -0
  169. /package/dist/{map-leaflet-imports-CaMm_rdF.mjs → map-leaflet-imports-CRSKA79m.mjs} +0 -0
  170. /package/dist/{more-actions-CGagbIDT.mjs → more-actions-ILnEZq_E.mjs} +0 -0
  171. /package/dist/{page-title-R7QbfbWp.mjs → page-title-ChsnpBiH.mjs} +0 -0
  172. /package/dist/{tag-input-BVSwNcRd.mjs → tag-input-T9cUX9-G.mjs} +0 -0
  173. /package/dist/{task-queue-dropdown-DyM5R8KF.mjs → task-queue-dropdown-Wcbj-f0V.mjs} +0 -0
  174. /package/dist/{to-api-format-BnbRFYQI.mjs → to-api-format-Bh3c01gr.mjs} +0 -0
  175. /package/dist/{use-copy-to-clipboard-BGdTmkFV.mjs → use-copy-to-clipboard-uNeeVHC4.mjs} +0 -0
@@ -0,0 +1,545 @@
1
+ import { t as cn } from "../../cn-D2KYQ917.mjs";
2
+ import { t as Button } from "../../button-BllvE9Lm.mjs";
3
+ import { n as useFormContext, t as FormProvider } from "../../form-context-Ccxm-wqL.mjs";
4
+ import { n as useAdapter } from "../../adapter-context-rWveHhDd.mjs";
5
+ import { t as defineStepper } from "../../stepper-DvIOp0hh.mjs";
6
+ import { CheckIcon } from "lucide-react";
7
+ import * as React$1 from "react";
8
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
+ import { z } from "zod";
10
+ //#region src/components/features/form/components/stepper/form-stepper.tsx
11
+ const FormStepperContext = React$1.createContext(null);
12
+ function useFormStepperContext() {
13
+ const context = React$1.use(FormStepperContext);
14
+ if (!context) throw new Error("useFormStepperContext must be used within a Form.Stepper component");
15
+ return context;
16
+ }
17
+ /**
18
+ * Recursively unwrap ZodIntersection (from .and()) to extract the base ZodObject.
19
+ *
20
+ * Zod v4 schema types use `def.type` as a string discriminant:
21
+ * - "intersection" (from .and()): merge left + right base objects
22
+ * - "object": return directly
23
+ *
24
+ * Note: In Zod v4, .superRefine() and .refine() return `this` (no wrapper),
25
+ * so only ZodIntersection needs unwrapping.
26
+ */
27
+ function getBaseObject(schema) {
28
+ if (schema.def.type === "intersection") {
29
+ const intersectionDef = schema.def;
30
+ const left = getBaseObject(intersectionDef.left);
31
+ const right = getBaseObject(intersectionDef.right);
32
+ return left.merge(right);
33
+ }
34
+ if (schema.def.type !== "object") return z.object({});
35
+ return schema;
36
+ }
37
+ /**
38
+ * Merge multiple zod schemas into one ZodObject for HTML constraint generation.
39
+ * Handles ZodIntersection (.and()) by unwrapping to base ZodObject shapes.
40
+ * Per-step validation still uses the original schemas with all refinements intact.
41
+ */
42
+ function mergeSchemas(steps) {
43
+ if (steps.length === 0) throw new Error("Form.Stepper requires at least one step");
44
+ return steps.reduce((acc, step, index) => {
45
+ const base = getBaseObject(step.schema);
46
+ if (index === 0) return base;
47
+ return acc.merge(base);
48
+ }, {});
49
+ }
50
+ /**
51
+ * Convert StepConfig[] to Stepperize step format
52
+ */
53
+ function toStepperizeSteps(steps) {
54
+ return steps.map((step) => ({
55
+ id: step.id,
56
+ label: step.label,
57
+ description: step.description
58
+ }));
59
+ }
60
+ /**
61
+ * Form.Stepper - Multi-step form container
62
+ *
63
+ * Uses Stepperize internally for step navigation and a single Conform form
64
+ * instance for all steps. Schemas are auto-merged for unified validation.
65
+ *
66
+ * @example
67
+ * ```tsx
68
+ * const steps = [
69
+ * { id: 'account', label: 'Account', schema: accountSchema },
70
+ * { id: 'profile', label: 'Profile', schema: profileSchema },
71
+ * ];
72
+ *
73
+ * <Form.Stepper steps={steps} onComplete={handleComplete}>
74
+ * <Form.StepperNavigation />
75
+ *
76
+ * <Form.Step id="account">
77
+ * <Form.Field name="email" label="Email" required>
78
+ * <Form.Input type="email" />
79
+ * </Form.Field>
80
+ * </Form.Step>
81
+ *
82
+ * <Form.Step id="profile">
83
+ * <Form.Field name="name" label="Full Name" required>
84
+ * <Form.Input />
85
+ * </Form.Field>
86
+ * </Form.Step>
87
+ *
88
+ * <Form.StepperControls />
89
+ * </Form.Stepper>
90
+ * ```
91
+ */
92
+ function FormStepper({ steps, children, onComplete, onStepChange, initialStep, className, defaultValues, id, formComponent }) {
93
+ const stepperDef = React$1.useMemo(() => {
94
+ return defineStepper(...toStepperizeSteps(steps));
95
+ }, [steps]);
96
+ const initialStepIndex = React$1.useMemo(() => {
97
+ if (!initialStep) return void 0;
98
+ const index = steps.findIndex((s) => s.id === initialStep);
99
+ return index >= 0 ? steps[index].id : void 0;
100
+ }, [initialStep, steps]);
101
+ const { Stepper } = stepperDef;
102
+ const providerProps = initialStepIndex ? { initialStep: initialStepIndex } : {};
103
+ return /* @__PURE__ */ jsx(Stepper.Provider, {
104
+ ...providerProps,
105
+ children: /* @__PURE__ */ jsx(FormStepperContent, {
106
+ steps,
107
+ stepperDef,
108
+ onComplete,
109
+ onStepChange,
110
+ className,
111
+ defaultValues,
112
+ id,
113
+ formComponent,
114
+ children
115
+ })
116
+ });
117
+ }
118
+ FormStepper.displayName = "Form.Stepper";
119
+ function FormStepperContent({ steps, stepperDef, children, onComplete, onStepChange, className, defaultValues, id, formComponent }) {
120
+ const { useStepper } = stepperDef;
121
+ const stepper = useStepper();
122
+ return /* @__PURE__ */ jsx(StepForm, {
123
+ steps,
124
+ stepper,
125
+ currentStepConfig: React$1.useMemo(() => steps.find((s) => s.id === stepper.state.current.data.id) ?? steps[0], [steps, stepper.state.current.data.id]),
126
+ combinedSchema: React$1.useMemo(() => mergeSchemas(steps), [steps]),
127
+ storedValues: React$1.useMemo(() => {
128
+ const allMetadata = steps.reduce((acc, step) => ({
129
+ ...acc,
130
+ ...stepper.metadata.get(step.id) || {}
131
+ }), {});
132
+ return {
133
+ ...defaultValues,
134
+ ...allMetadata
135
+ };
136
+ }, [
137
+ steps,
138
+ stepper,
139
+ defaultValues,
140
+ stepper.state.current.data.id
141
+ ]),
142
+ onComplete,
143
+ onStepChange,
144
+ className,
145
+ id,
146
+ formComponent,
147
+ children
148
+ }, stepper.state.current.data.id);
149
+ }
150
+ function StepForm({ steps, stepper, currentStepConfig, combinedSchema: _combinedSchema, storedValues, children, onComplete, onStepChange, className, id, formComponent: FormComp = "form" }) {
151
+ const adapter = useAdapter();
152
+ const [isSubmitting, setIsSubmitting] = React$1.useState(false);
153
+ const formRef = React$1.useRef(null);
154
+ const currentIndex = stepper.lookup.getIndex(stepper.state.current.data.id);
155
+ const handleStepSubmit = React$1.useCallback(async (data) => {
156
+ stepper.metadata.set(stepper.state.current.data.id, data);
157
+ if (stepper.state.isLast) {
158
+ setIsSubmitting(true);
159
+ try {
160
+ await onComplete({
161
+ ...steps.reduce((acc, step) => ({
162
+ ...acc,
163
+ ...stepper.metadata.get(step.id) || {}
164
+ }), {}),
165
+ ...data
166
+ });
167
+ } catch {} finally {
168
+ setIsSubmitting(false);
169
+ }
170
+ } else {
171
+ const nextStepId = stepper.lookup.getNext(stepper.state.current.data.id)?.id;
172
+ if (nextStepId) {
173
+ stepper.navigation.goTo(nextStepId);
174
+ onStepChange?.(nextStepId, "next");
175
+ }
176
+ }
177
+ }, [
178
+ stepper,
179
+ steps,
180
+ onComplete,
181
+ onStepChange
182
+ ]);
183
+ const instance = adapter.useCreateForm({
184
+ schema: currentStepConfig.schema,
185
+ defaultValues: storedValues,
186
+ mode: "onSubmit",
187
+ id: `${id ?? "stepper"}-${currentStepConfig.id}`,
188
+ onSubmit: handleStepSubmit,
189
+ formRef
190
+ });
191
+ const next = React$1.useCallback(() => {
192
+ formRef.current?.requestSubmit();
193
+ }, []);
194
+ const prev = React$1.useCallback(() => {
195
+ const currentValues = instance.getValues();
196
+ if (Object.keys(currentValues).length > 0) stepper.metadata.set(stepper.state.current.data.id, currentValues);
197
+ const prevStepId = stepper.lookup.getPrev(stepper.state.current.data.id)?.id;
198
+ if (prevStepId) {
199
+ stepper.navigation.goTo(prevStepId);
200
+ onStepChange?.(prevStepId, "prev");
201
+ }
202
+ }, [
203
+ instance,
204
+ stepper,
205
+ onStepChange
206
+ ]);
207
+ const goTo = React$1.useCallback((stepId) => {
208
+ if (stepper.lookup.getIndex(stepId) < currentIndex) {
209
+ const currentValues = instance.getValues();
210
+ if (Object.keys(currentValues).length > 0) stepper.metadata.set(stepper.state.current.data.id, currentValues);
211
+ stepper.navigation.goTo(stepId);
212
+ onStepChange?.(stepId, "prev");
213
+ }
214
+ }, [
215
+ instance,
216
+ stepper,
217
+ currentIndex,
218
+ onStepChange
219
+ ]);
220
+ const getStepData = React$1.useCallback((stepId) => stepper.metadata.get(stepId), [stepper]);
221
+ const getAllStepData = React$1.useCallback(() => {
222
+ return steps.reduce((acc, step) => ({
223
+ ...acc,
224
+ ...stepper.metadata.get(step.id) || {}
225
+ }), {});
226
+ }, [steps, stepper]);
227
+ const stepperContextValue = React$1.useMemo(() => ({
228
+ steps,
229
+ current: currentStepConfig,
230
+ currentIndex,
231
+ next,
232
+ prev,
233
+ goTo,
234
+ isFirst: stepper.state.isFirst,
235
+ isLast: stepper.state.isLast,
236
+ getStepData,
237
+ getAllStepData,
238
+ utils: { getIndex: (stepId) => stepper.lookup.getIndex(stepId) }
239
+ }), [
240
+ steps,
241
+ currentStepConfig,
242
+ currentIndex,
243
+ stepper,
244
+ next,
245
+ prev,
246
+ goTo,
247
+ getStepData,
248
+ getAllStepData
249
+ ]);
250
+ const contextValue = React$1.useMemo(() => ({
251
+ form: instance,
252
+ fields: instance.fields,
253
+ isSubmitting,
254
+ isDirty: instance.formState.isDirty,
255
+ isValid: instance.formState.isValid,
256
+ isSubmitted: instance.formState.isSubmitted,
257
+ submitCount: instance.formState.submitCount,
258
+ dirtyFields: instance.formState.dirtyFields,
259
+ touchedFields: instance.formState.touchedFields,
260
+ mode: "onChange",
261
+ displayTouchedFields: instance.touchedFields,
262
+ markFieldTouched: instance.markFieldTouched,
263
+ markAllFieldsTouched: instance.markAllFieldsTouched,
264
+ submit: () => formRef.current?.requestSubmit(),
265
+ reset: () => instance.reset(),
266
+ formId: instance.id
267
+ }), [
268
+ instance,
269
+ isSubmitting,
270
+ instance.formState
271
+ ]);
272
+ const renderProps = {
273
+ steps,
274
+ current: currentStepConfig,
275
+ currentIndex,
276
+ next,
277
+ prev,
278
+ goTo,
279
+ isFirst: stepper.state.isFirst,
280
+ isLast: stepper.state.isLast,
281
+ getStepData,
282
+ getAllStepData
283
+ };
284
+ const resolvedChildren = typeof children === "function" ? children(renderProps) : children;
285
+ return /* @__PURE__ */ jsx(FormStepperContext, {
286
+ value: stepperContextValue,
287
+ children: /* @__PURE__ */ jsx(FormProvider, {
288
+ value: contextValue,
289
+ children: /* @__PURE__ */ jsx(adapter.FormProvider, {
290
+ instance,
291
+ children: /* @__PURE__ */ jsx(FormComp, {
292
+ ref: formRef,
293
+ ...instance.formProps,
294
+ className: cn("space-y-6", className),
295
+ autoComplete: "off",
296
+ noValidate: true,
297
+ onSubmit: (e) => {
298
+ e.stopPropagation();
299
+ const adapterSubmit = instance.formProps.onSubmit;
300
+ adapterSubmit?.(e);
301
+ },
302
+ children: resolvedChildren
303
+ })
304
+ })
305
+ })
306
+ });
307
+ }
308
+ //#endregion
309
+ //#region src/components/features/form/components/stepper/form-step.tsx
310
+ /**
311
+ * Form.Step - Individual step content container
312
+ *
313
+ * Only renders its children when the step is active.
314
+ * Works with the single-form architecture - fields remain registered
315
+ * even when unmounted, preserving their values.
316
+ *
317
+ * @example
318
+ * ```tsx
319
+ * <Form.Step id="account">
320
+ * <Form.Field name="email" label="Email" required>
321
+ * <Form.Input type="email" />
322
+ * </Form.Field>
323
+ * </Form.Step>
324
+ * ```
325
+ */
326
+ function FormStep({ id, children }) {
327
+ const { current } = useFormStepperContext();
328
+ if (current.id !== id) return null;
329
+ return /* @__PURE__ */ jsx(Fragment$1, { children });
330
+ }
331
+ FormStep.displayName = "Form.Step";
332
+ //#endregion
333
+ //#region src/components/features/form/components/stepper/stepper-controls.tsx
334
+ /**
335
+ * Form.StepperControls - Navigation buttons (Previous/Next/Submit)
336
+ *
337
+ * Provides Previous and Next/Submit buttons for navigating between steps.
338
+ * The Next button triggers form validation before advancing.
339
+ * The Previous button navigates back without validation.
340
+ *
341
+ * @example
342
+ * ```tsx
343
+ * <Form.StepperControls
344
+ * prevLabel={(isFirst) => isFirst ? 'Cancel' : 'Previous'}
345
+ * nextLabel={(isLast) => isLast ? 'Submit' : 'Next'}
346
+ * loadingText="Creating..."
347
+ * onCancel={() => setOpen(false)}
348
+ * />
349
+ * ```
350
+ *
351
+ * @example With external loading state
352
+ * ```tsx
353
+ * <Form.StepperControls
354
+ * loading={fetcher.state === 'submitting'}
355
+ * disabled={!isValid}
356
+ * loadingText="Saving..."
357
+ * />
358
+ * ```
359
+ */
360
+ function StepperControls({ prevLabel = "Previous", nextLabel = (isLast) => isLast ? "Submit" : "Next", loadingText = "Submitting...", showPrev = true, loading, disabled, onPrev, onCancel, className }) {
361
+ const { prev, isFirst, isLast } = useFormStepperContext();
362
+ const { isSubmitting: formIsSubmitting } = useFormContext();
363
+ const isLoading = loading ?? formIsSubmitting;
364
+ const isDisabled = disabled ?? false;
365
+ const getPrevLabel = () => {
366
+ if (typeof prevLabel === "function") return prevLabel(isFirst);
367
+ return prevLabel;
368
+ };
369
+ const getNextLabel = () => {
370
+ if (typeof nextLabel === "function") return nextLabel(isLast);
371
+ return nextLabel;
372
+ };
373
+ const handlePrev = () => {
374
+ if (isFirst && onCancel) onCancel();
375
+ else {
376
+ onPrev?.();
377
+ prev();
378
+ }
379
+ };
380
+ return /* @__PURE__ */ jsxs("div", {
381
+ className: cn("flex items-center justify-between gap-3", className),
382
+ children: [/* @__PURE__ */ jsx("div", { children: showPrev && /* @__PURE__ */ jsx(Button, {
383
+ htmlType: "button",
384
+ type: "quaternary",
385
+ theme: "outline",
386
+ size: "small",
387
+ onClick: handlePrev,
388
+ disabled: isLoading || isDisabled,
389
+ children: getPrevLabel()
390
+ }) }), /* @__PURE__ */ jsx(Button, {
391
+ htmlType: "submit",
392
+ type: "primary",
393
+ size: "small",
394
+ loading: isLoading,
395
+ disabled: isLoading || isDisabled,
396
+ children: isLoading && isLast ? loadingText : getNextLabel()
397
+ })]
398
+ });
399
+ }
400
+ StepperControls.displayName = "Form.StepperControls";
401
+ //#endregion
402
+ //#region src/components/features/form/components/stepper/stepper-navigation.tsx
403
+ /**
404
+ * Form.StepperNavigation - Step indicators/progress
405
+ *
406
+ * Displays visual step indicators showing current progress through the form.
407
+ * Supports horizontal and vertical variants with optional label orientation.
408
+ *
409
+ * @example
410
+ * ```tsx
411
+ * <Form.StepperNavigation variant="horizontal" labelOrientation="vertical" />
412
+ * ```
413
+ */
414
+ function StepperNavigation({ variant = "horizontal", labelOrientation = "vertical", className }) {
415
+ const { steps, currentIndex } = useFormStepperContext();
416
+ if (variant === "horizontal" && labelOrientation === "vertical") return /* @__PURE__ */ jsx("nav", {
417
+ "aria-label": "Form steps",
418
+ className: cn("flex flex-row items-start justify-between", className),
419
+ children: steps.map((step, index) => {
420
+ const isActive = index === currentIndex;
421
+ const isCompleted = index < currentIndex;
422
+ return /* @__PURE__ */ jsxs("div", {
423
+ className: "relative flex flex-1 flex-col items-center",
424
+ children: [
425
+ !(index === steps.length - 1) && /* @__PURE__ */ jsx("div", { className: "bg-stepper-line absolute top-4 right-[calc(-50%+20px)] left-[calc(50%+20px)] h-0.5" }),
426
+ /* @__PURE__ */ jsx("div", {
427
+ className: cn("relative z-10 flex h-8 w-8 items-center justify-center rounded-full border bg-transparent text-sm font-medium transition-colors", isActive && "border-primary bg-primary text-primary-foreground", isCompleted && "border-tertiary-foreground bg-tertiary-foreground text-tertiary", !isActive && !isCompleted && "border-stepper-label text-stepper-label"),
428
+ "aria-current": isActive ? "step" : void 0,
429
+ children: isCompleted ? /* @__PURE__ */ jsx(CheckIcon, { className: "text-tertiary h-4 w-4" }) : index + 1
430
+ }),
431
+ /* @__PURE__ */ jsxs("div", {
432
+ className: "mt-1",
433
+ children: [/* @__PURE__ */ jsx("span", {
434
+ className: cn("text-xs font-medium", isActive && "text-foreground", isCompleted && "text-stepper-label", !isActive && !isCompleted && "text-stepper-label"),
435
+ children: step.label
436
+ }), step.description && /* @__PURE__ */ jsx("p", {
437
+ className: "text-muted-foreground mt-0.5 text-xs",
438
+ children: step.description
439
+ })]
440
+ })
441
+ ]
442
+ }, step.id);
443
+ })
444
+ });
445
+ if (variant === "horizontal") return /* @__PURE__ */ jsx("nav", {
446
+ "aria-label": "Form steps",
447
+ className: cn("flex flex-row items-center", className),
448
+ children: steps.map((step, index) => {
449
+ const isActive = index === currentIndex;
450
+ const isCompleted = index < currentIndex;
451
+ const isLast = index === steps.length - 1;
452
+ return /* @__PURE__ */ jsxs(React$1.Fragment, { children: [/* @__PURE__ */ jsxs("div", {
453
+ className: "flex items-center",
454
+ children: [/* @__PURE__ */ jsx("div", {
455
+ className: cn("flex h-8 w-8 items-center justify-center rounded-full border text-sm font-medium transition-colors", isActive && "border-primary bg-primary text-primary-foreground", isCompleted && "border-tertiary-foreground bg-tertiary-foreground text-tertiary", !isActive && !isCompleted && "border-stepper-label text-stepper-label"),
456
+ "aria-current": isActive ? "step" : void 0,
457
+ children: isCompleted ? /* @__PURE__ */ jsx(CheckIcon, { className: "text-tertiary size-4" }) : index + 1
458
+ }), /* @__PURE__ */ jsx("div", {
459
+ className: "ml-2",
460
+ children: /* @__PURE__ */ jsx("span", {
461
+ className: cn("text-sm font-medium", isActive && "text-foreground", isCompleted && "text-stepper-label", !isActive && !isCompleted && "text-stepper-label"),
462
+ children: step.label
463
+ })
464
+ })]
465
+ }), !isLast && /* @__PURE__ */ jsx("div", { className: "bg-stepper-line mx-4 h-0.5 min-w-8 flex-1" })] }, step.id);
466
+ })
467
+ });
468
+ return /* @__PURE__ */ jsx("nav", {
469
+ "aria-label": "Form steps",
470
+ className: cn("flex flex-col", className),
471
+ children: steps.map((step, index) => {
472
+ const isActive = index === currentIndex;
473
+ const isCompleted = index < currentIndex;
474
+ const isLast = index === steps.length - 1;
475
+ return /* @__PURE__ */ jsxs("div", {
476
+ className: "flex flex-row",
477
+ children: [/* @__PURE__ */ jsxs("div", {
478
+ className: "flex flex-col items-center",
479
+ children: [/* @__PURE__ */ jsx("div", {
480
+ className: cn("flex h-8 w-8 items-center justify-center rounded-full border text-sm font-medium transition-colors", isActive && "border-primary bg-primary text-primary-foreground", isCompleted && "border-tertiary-foreground bg-tertiary-foreground text-tertiary", !isActive && !isCompleted && "border-stepper-label text-stepper-label"),
481
+ "aria-current": isActive ? "step" : void 0,
482
+ children: isCompleted ? /* @__PURE__ */ jsx(CheckIcon, { className: "text-tertiary size-4" }) : index + 1
483
+ }), !isLast && /* @__PURE__ */ jsx("div", { className: "bg-stepper-line my-1 min-h-8 w-0.5 flex-1" })]
484
+ }), /* @__PURE__ */ jsxs("div", {
485
+ className: "ml-3 pb-8",
486
+ children: [/* @__PURE__ */ jsx("span", {
487
+ className: cn("text-sm font-medium", isActive && "text-foreground", isCompleted && "text-stepper-label", !isActive && !isCompleted && "text-stepper-label"),
488
+ children: step.label
489
+ }), step.description && /* @__PURE__ */ jsx("p", {
490
+ className: "text-muted-foreground mt-0.5 text-xs",
491
+ children: step.description
492
+ })]
493
+ })]
494
+ }, step.id);
495
+ })
496
+ });
497
+ }
498
+ StepperNavigation.displayName = "Form.StepperNavigation";
499
+ //#endregion
500
+ //#region src/components/features/form/hooks/use-stepper.ts
501
+ /**
502
+ * Hook to access the stepper context
503
+ * Must be used within a Form.Stepper component
504
+ *
505
+ * @example
506
+ * ```tsx
507
+ * function StepContent() {
508
+ * const {
509
+ * current,
510
+ * currentIndex,
511
+ * steps,
512
+ * next,
513
+ * prev,
514
+ * goTo,
515
+ * isFirst,
516
+ * isLast,
517
+ * } = useStepper();
518
+ *
519
+ * return (
520
+ * <div>
521
+ * <h2>Step {currentIndex + 1}: {current.label}</h2>
522
+ * <button onClick={prev} disabled={isFirst}>Previous</button>
523
+ * <button onClick={next} disabled={isLast}>Next</button>
524
+ * </div>
525
+ * );
526
+ * }
527
+ * ```
528
+ */
529
+ function useStepper() {
530
+ const context = useFormStepperContext();
531
+ return {
532
+ steps: context.steps,
533
+ current: context.current,
534
+ currentIndex: context.currentIndex,
535
+ next: context.next,
536
+ prev: context.prev,
537
+ goTo: context.goTo,
538
+ isFirst: context.isFirst,
539
+ isLast: context.isLast,
540
+ getStepData: context.getStepData,
541
+ getAllStepData: context.getAllStepData
542
+ };
543
+ }
544
+ //#endregion
545
+ export { FormStep, FormStepper, StepperControls, StepperNavigation, useStepper };