wizzard-stepper-react 1.3.1 → 1.4.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.
- package/README.md +142 -34
- package/dist/index.cjs +418 -123
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +138 -18
- package/dist/index.d.ts +138 -18
- package/dist/index.js +421 -123
- package/dist/index.js.map +1 -1
- package/package.json +10 -6
package/dist/index.js
CHANGED
|
@@ -3,7 +3,17 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
|
|
5
5
|
// src/context/WizardContext.tsx
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
createContext,
|
|
8
|
+
useContext,
|
|
9
|
+
useEffect,
|
|
10
|
+
useMemo,
|
|
11
|
+
useState,
|
|
12
|
+
useCallback,
|
|
13
|
+
useSyncExternalStore,
|
|
14
|
+
useRef,
|
|
15
|
+
useTransition
|
|
16
|
+
} from "react";
|
|
7
17
|
|
|
8
18
|
// src/adapters/persistence/MemoryAdapter.ts
|
|
9
19
|
var MemoryAdapter = class {
|
|
@@ -34,6 +44,9 @@ function getByPath(obj, path, defaultValue) {
|
|
|
34
44
|
}
|
|
35
45
|
function setByPath(obj, path, value) {
|
|
36
46
|
if (!path) return value;
|
|
47
|
+
if (!path.includes(".") && !path.includes("[") && !path.includes("]")) {
|
|
48
|
+
return { ...obj, [path]: value };
|
|
49
|
+
}
|
|
37
50
|
const keys = path.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
|
|
38
51
|
const update = (current, index) => {
|
|
39
52
|
if (index === keys.length) return value;
|
|
@@ -54,39 +67,83 @@ function setByPath(obj, path, value) {
|
|
|
54
67
|
|
|
55
68
|
// src/context/WizardContext.tsx
|
|
56
69
|
import { jsx } from "react/jsx-runtime";
|
|
57
|
-
var
|
|
70
|
+
var WizardStateContext = createContext(
|
|
71
|
+
void 0
|
|
72
|
+
);
|
|
73
|
+
var WizardActionsContext = createContext(
|
|
74
|
+
void 0
|
|
75
|
+
);
|
|
76
|
+
var WizardStore = class {
|
|
77
|
+
constructor(initialData) {
|
|
78
|
+
__publicField(this, "state");
|
|
79
|
+
__publicField(this, "listeners", /* @__PURE__ */ new Set());
|
|
80
|
+
__publicField(this, "getSnapshot", () => this.state);
|
|
81
|
+
__publicField(this, "subscribe", (listener) => {
|
|
82
|
+
this.listeners.add(listener);
|
|
83
|
+
return () => this.listeners.delete(listener);
|
|
84
|
+
});
|
|
85
|
+
this.state = { data: initialData, errors: {} };
|
|
86
|
+
}
|
|
87
|
+
update(newData) {
|
|
88
|
+
this.state = { ...this.state, data: newData };
|
|
89
|
+
this.notify();
|
|
90
|
+
}
|
|
91
|
+
updateErrors(newErrors) {
|
|
92
|
+
this.state = { ...this.state, errors: newErrors };
|
|
93
|
+
this.notify();
|
|
94
|
+
}
|
|
95
|
+
notify() {
|
|
96
|
+
this.listeners.forEach((l) => l());
|
|
97
|
+
}
|
|
98
|
+
};
|
|
58
99
|
function WizardProvider({
|
|
59
100
|
config,
|
|
60
101
|
initialData,
|
|
61
102
|
children
|
|
62
103
|
}) {
|
|
63
104
|
const [currentStepId, setCurrentStepId] = useState("");
|
|
64
|
-
const [wizardData, setWizardData] = useState(initialData || {});
|
|
65
105
|
const [visitedSteps, setVisitedSteps] = useState(/* @__PURE__ */ new Set());
|
|
66
106
|
const [completedSteps, setCompletedSteps] = useState(/* @__PURE__ */ new Set());
|
|
67
107
|
const [errorSteps, setErrorSteps] = useState(/* @__PURE__ */ new Set());
|
|
68
|
-
const [
|
|
108
|
+
const [, setAllErrorsState] = useState({});
|
|
69
109
|
const [isLoading, setIsLoading] = useState(true);
|
|
110
|
+
const [isPending, startTransition] = useTransition();
|
|
111
|
+
const storeRef = useRef(new WizardStore(initialData || {}));
|
|
112
|
+
const [wizardData, setWizardData] = useState(initialData || {});
|
|
70
113
|
const persistenceAdapter = useMemo(() => {
|
|
71
114
|
return config.persistence?.adapter || new MemoryAdapter();
|
|
72
115
|
}, [config.persistence?.adapter]);
|
|
73
116
|
const persistenceMode = config.persistence?.mode || "onStepChange";
|
|
74
|
-
const activeSteps =
|
|
75
|
-
|
|
117
|
+
const [activeSteps, setActiveSteps] = useState(
|
|
118
|
+
() => config.steps.filter((s) => !s.condition || s.condition(wizardData))
|
|
119
|
+
);
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
const nextActiveSteps = config.steps.filter((step) => {
|
|
76
122
|
if (step.condition) {
|
|
77
123
|
return step.condition(wizardData);
|
|
78
124
|
}
|
|
79
125
|
return true;
|
|
80
126
|
});
|
|
81
|
-
|
|
127
|
+
const currentIds = activeSteps.map((s) => s.id).join(",");
|
|
128
|
+
const nextIds = nextActiveSteps.map((s) => s.id).join(",");
|
|
129
|
+
if (currentIds !== nextIds) {
|
|
130
|
+
setActiveSteps(nextActiveSteps);
|
|
131
|
+
}
|
|
132
|
+
}, [config.steps, wizardData, activeSteps]);
|
|
82
133
|
useEffect(() => {
|
|
83
134
|
if (!currentStepId && activeSteps.length > 0) {
|
|
84
135
|
setCurrentStepId(activeSteps[0].id);
|
|
85
136
|
setIsLoading(false);
|
|
86
137
|
}
|
|
87
138
|
}, [activeSteps, currentStepId]);
|
|
88
|
-
const currentStep = useMemo(
|
|
89
|
-
|
|
139
|
+
const currentStep = useMemo(
|
|
140
|
+
() => activeSteps.find((s) => s.id === currentStepId) || null,
|
|
141
|
+
[activeSteps, currentStepId]
|
|
142
|
+
);
|
|
143
|
+
const currentStepIndex = useMemo(
|
|
144
|
+
() => activeSteps.findIndex((s) => s.id === currentStepId),
|
|
145
|
+
[activeSteps, currentStepId]
|
|
146
|
+
);
|
|
90
147
|
const isFirstStep = currentStepIndex === 0;
|
|
91
148
|
const isLastStep = currentStepIndex === activeSteps.length - 1;
|
|
92
149
|
const META_KEY = "__wizzard_meta__";
|
|
@@ -106,103 +163,159 @@ function WizardProvider({
|
|
|
106
163
|
}
|
|
107
164
|
});
|
|
108
165
|
if (Object.keys(loadedData).length > 0) {
|
|
109
|
-
setWizardData((prev) =>
|
|
166
|
+
setWizardData((prev) => {
|
|
167
|
+
const newData = { ...prev, ...loadedData };
|
|
168
|
+
storeRef.current.update(newData);
|
|
169
|
+
return newData;
|
|
170
|
+
});
|
|
110
171
|
}
|
|
111
172
|
setIsLoading(false);
|
|
112
173
|
}, [config.steps, persistenceAdapter]);
|
|
113
174
|
useEffect(() => {
|
|
114
175
|
hydrate();
|
|
115
176
|
}, [hydrate]);
|
|
116
|
-
const saveData = useCallback(
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
177
|
+
const saveData = useCallback(
|
|
178
|
+
(mode, stepId, data) => {
|
|
179
|
+
if (mode === persistenceMode || mode === "manual") {
|
|
180
|
+
persistenceAdapter.saveStep(stepId, data);
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
[persistenceAdapter, persistenceMode]
|
|
184
|
+
);
|
|
185
|
+
const validationTimeoutRef = useRef(
|
|
186
|
+
null
|
|
187
|
+
);
|
|
188
|
+
const validateStep = useCallback(
|
|
189
|
+
async (stepId, data) => {
|
|
190
|
+
const step = config.steps.find((s) => s.id === stepId);
|
|
191
|
+
if (!step || !step.validationAdapter) return true;
|
|
192
|
+
const result = await step.validationAdapter.validate(data);
|
|
193
|
+
if (!result.isValid) {
|
|
194
|
+
const newAllErrors = {
|
|
195
|
+
...storeRef.current.getSnapshot().errors,
|
|
196
|
+
[stepId]: result.errors || {}
|
|
197
|
+
};
|
|
198
|
+
storeRef.current.updateErrors(newAllErrors);
|
|
199
|
+
setAllErrorsState(newAllErrors);
|
|
200
|
+
setErrorSteps((prev) => {
|
|
201
|
+
const next = new Set(prev);
|
|
202
|
+
next.add(stepId);
|
|
203
|
+
return next;
|
|
204
|
+
});
|
|
205
|
+
return false;
|
|
206
|
+
} else {
|
|
207
|
+
const newAllErrors = { ...storeRef.current.getSnapshot().errors };
|
|
208
|
+
delete newAllErrors[stepId];
|
|
209
|
+
storeRef.current.updateErrors(newAllErrors);
|
|
210
|
+
setAllErrorsState(newAllErrors);
|
|
211
|
+
setErrorSteps((prev) => {
|
|
212
|
+
const next = new Set(prev);
|
|
213
|
+
next.delete(stepId);
|
|
214
|
+
return next;
|
|
215
|
+
});
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
[config.steps]
|
|
220
|
+
);
|
|
221
|
+
const setStepData = useCallback(
|
|
222
|
+
(stepId, data) => {
|
|
223
|
+
const prevData = storeRef.current.getSnapshot().data;
|
|
224
|
+
const newData = { ...prevData, ...data };
|
|
225
|
+
storeRef.current.update(newData);
|
|
226
|
+
startTransition(() => {
|
|
227
|
+
setWizardData(newData);
|
|
228
|
+
});
|
|
124
229
|
if (persistenceMode === "onChange") {
|
|
125
230
|
saveData("onChange", stepId, newData);
|
|
126
231
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const setData = useCallback(
|
|
131
|
-
|
|
132
|
-
const
|
|
232
|
+
},
|
|
233
|
+
[persistenceMode, saveData]
|
|
234
|
+
);
|
|
235
|
+
const setData = useCallback(
|
|
236
|
+
(path, value, options) => {
|
|
237
|
+
const prevData = storeRef.current.getSnapshot().data;
|
|
238
|
+
const newData = setByPath(prevData, path, value);
|
|
239
|
+
storeRef.current.update(newData);
|
|
240
|
+
startTransition(() => {
|
|
241
|
+
setWizardData(newData);
|
|
242
|
+
});
|
|
243
|
+
if (options?.debounceValidation) {
|
|
244
|
+
if (validationTimeoutRef.current)
|
|
245
|
+
clearTimeout(validationTimeoutRef.current);
|
|
246
|
+
validationTimeoutRef.current = setTimeout(() => {
|
|
247
|
+
validateStep(currentStepId, newData);
|
|
248
|
+
}, options.debounceValidation);
|
|
249
|
+
} else {
|
|
250
|
+
validateStep(currentStepId, newData);
|
|
251
|
+
}
|
|
133
252
|
if (persistenceMode === "onChange") {
|
|
134
253
|
saveData("onChange", currentStepId, newData);
|
|
135
254
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
255
|
+
},
|
|
256
|
+
[persistenceMode, saveData, currentStepId, validateStep]
|
|
257
|
+
);
|
|
139
258
|
const getData = useCallback((path, defaultValue) => {
|
|
140
|
-
return getByPath(
|
|
141
|
-
}, [
|
|
142
|
-
const handleStepChange = useCallback(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if (!step.validationAdapter) return true;
|
|
150
|
-
const result = await step.validationAdapter.validate(wizardData);
|
|
151
|
-
if (!result.isValid) {
|
|
152
|
-
setAllErrors((prev) => ({
|
|
153
|
-
...prev,
|
|
154
|
-
[stepId]: result.errors || {}
|
|
155
|
-
}));
|
|
156
|
-
setErrorSteps((prev) => new Set(prev).add(stepId));
|
|
157
|
-
return false;
|
|
158
|
-
} else {
|
|
159
|
-
setAllErrors((prev) => {
|
|
160
|
-
const next = { ...prev };
|
|
161
|
-
delete next[stepId];
|
|
162
|
-
return next;
|
|
163
|
-
});
|
|
164
|
-
setErrorSteps((prev) => {
|
|
165
|
-
const next = new Set(prev);
|
|
166
|
-
next.delete(stepId);
|
|
167
|
-
return next;
|
|
168
|
-
});
|
|
169
|
-
return true;
|
|
170
|
-
}
|
|
171
|
-
}, [config.steps, wizardData]);
|
|
259
|
+
return getByPath(storeRef.current.getSnapshot().data, path, defaultValue);
|
|
260
|
+
}, []);
|
|
261
|
+
const handleStepChange = useCallback(
|
|
262
|
+
(field, value) => {
|
|
263
|
+
if (!currentStepId) return;
|
|
264
|
+
setData(field, value);
|
|
265
|
+
},
|
|
266
|
+
[setData, currentStepId]
|
|
267
|
+
);
|
|
172
268
|
const validateAll = useCallback(async () => {
|
|
173
269
|
let isValid = true;
|
|
270
|
+
const currentData = storeRef.current.getSnapshot().data;
|
|
174
271
|
for (const step of activeSteps) {
|
|
175
|
-
const stepValid = await validateStep(step.id);
|
|
272
|
+
const stepValid = await validateStep(step.id, currentData);
|
|
176
273
|
if (!stepValid) isValid = false;
|
|
177
274
|
}
|
|
178
275
|
return isValid;
|
|
179
276
|
}, [activeSteps, validateStep]);
|
|
180
|
-
const goToStep = useCallback(
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
const
|
|
185
|
-
if (
|
|
186
|
-
const
|
|
187
|
-
if (
|
|
277
|
+
const goToStep = useCallback(
|
|
278
|
+
async (stepId) => {
|
|
279
|
+
const targetIndex = activeSteps.findIndex((s) => s.id === stepId);
|
|
280
|
+
if (targetIndex === -1) return false;
|
|
281
|
+
const currentData = storeRef.current.getSnapshot().data;
|
|
282
|
+
if (targetIndex > currentStepIndex) {
|
|
283
|
+
const shouldValidate = currentStep?.autoValidate ?? config.autoValidate ?? true;
|
|
284
|
+
if (shouldValidate) {
|
|
285
|
+
const isValid = await validateStep(currentStepId, currentData);
|
|
286
|
+
if (!isValid) return false;
|
|
287
|
+
}
|
|
188
288
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
289
|
+
if (persistenceMode === "onStepChange" && currentStep) {
|
|
290
|
+
saveData("onStepChange", currentStepId, currentData);
|
|
291
|
+
}
|
|
292
|
+
const nextVisited = new Set(visitedSteps).add(currentStepId);
|
|
293
|
+
setVisitedSteps(nextVisited);
|
|
294
|
+
setCurrentStepId(stepId);
|
|
295
|
+
if (persistenceMode !== "manual") {
|
|
296
|
+
persistenceAdapter.saveStep(META_KEY, {
|
|
297
|
+
currentStepId: stepId,
|
|
298
|
+
visited: Array.from(nextVisited),
|
|
299
|
+
completed: Array.from(completedSteps)
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
window.scrollTo(0, 0);
|
|
303
|
+
return true;
|
|
304
|
+
},
|
|
305
|
+
[
|
|
306
|
+
activeSteps,
|
|
307
|
+
currentStepId,
|
|
308
|
+
currentStep,
|
|
309
|
+
currentStepIndex,
|
|
310
|
+
config.autoValidate,
|
|
311
|
+
persistenceMode,
|
|
312
|
+
saveData,
|
|
313
|
+
validateStep,
|
|
314
|
+
visitedSteps,
|
|
315
|
+
completedSteps,
|
|
316
|
+
persistenceAdapter
|
|
317
|
+
]
|
|
318
|
+
);
|
|
206
319
|
const goToNextStep = useCallback(async () => {
|
|
207
320
|
if (isLastStep) return;
|
|
208
321
|
const nextStep = activeSteps[currentStepIndex + 1];
|
|
@@ -216,12 +329,21 @@ function WizardProvider({
|
|
|
216
329
|
currentStepId: nextStep.id,
|
|
217
330
|
visited: Array.from(new Set(visitedSteps).add(currentStepId)),
|
|
218
331
|
completed: Array.from(nextCompleted)
|
|
219
|
-
// Updated completed steps
|
|
220
332
|
});
|
|
221
333
|
}
|
|
222
334
|
}
|
|
223
335
|
}
|
|
224
|
-
}, [
|
|
336
|
+
}, [
|
|
337
|
+
activeSteps,
|
|
338
|
+
currentStepIndex,
|
|
339
|
+
isLastStep,
|
|
340
|
+
currentStepId,
|
|
341
|
+
goToStep,
|
|
342
|
+
visitedSteps,
|
|
343
|
+
completedSteps,
|
|
344
|
+
persistenceMode,
|
|
345
|
+
persistenceAdapter
|
|
346
|
+
]);
|
|
225
347
|
const goToPrevStep = useCallback(() => {
|
|
226
348
|
if (isFirstStep) return;
|
|
227
349
|
const prevStep = activeSteps[currentStepIndex - 1];
|
|
@@ -229,45 +351,212 @@ function WizardProvider({
|
|
|
229
351
|
goToStep(prevStep.id);
|
|
230
352
|
}
|
|
231
353
|
}, [activeSteps, currentStepIndex, isFirstStep, goToStep]);
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
354
|
+
const clearStorage = useCallback(
|
|
355
|
+
() => persistenceAdapter.clear(),
|
|
356
|
+
[persistenceAdapter]
|
|
357
|
+
);
|
|
358
|
+
const save = useCallback(
|
|
359
|
+
() => saveData("manual", currentStepId, storeRef.current.getSnapshot().data),
|
|
360
|
+
[saveData, currentStepId]
|
|
361
|
+
);
|
|
362
|
+
const stateValue = useMemo(
|
|
363
|
+
() => ({
|
|
364
|
+
currentStep,
|
|
365
|
+
currentStepIndex,
|
|
366
|
+
isFirstStep,
|
|
367
|
+
isLastStep,
|
|
368
|
+
isLoading,
|
|
369
|
+
isPending,
|
|
370
|
+
activeSteps,
|
|
371
|
+
visitedSteps,
|
|
372
|
+
completedSteps,
|
|
373
|
+
errorSteps,
|
|
374
|
+
store: storeRef.current
|
|
375
|
+
}),
|
|
376
|
+
[
|
|
377
|
+
currentStep,
|
|
378
|
+
currentStepIndex,
|
|
379
|
+
isFirstStep,
|
|
380
|
+
isLastStep,
|
|
381
|
+
isLoading,
|
|
382
|
+
isPending,
|
|
383
|
+
activeSteps,
|
|
384
|
+
visitedSteps,
|
|
385
|
+
completedSteps,
|
|
386
|
+
errorSteps
|
|
387
|
+
]
|
|
388
|
+
);
|
|
389
|
+
const actionsValue = useMemo(
|
|
390
|
+
() => ({
|
|
391
|
+
goToNextStep,
|
|
392
|
+
goToPrevStep,
|
|
393
|
+
goToStep,
|
|
394
|
+
setStepData,
|
|
395
|
+
handleStepChange,
|
|
396
|
+
validateStep: (sid) => validateStep(sid, storeRef.current.getSnapshot().data),
|
|
397
|
+
validateAll,
|
|
398
|
+
save,
|
|
399
|
+
clearStorage,
|
|
400
|
+
setData,
|
|
401
|
+
getData
|
|
402
|
+
}),
|
|
403
|
+
[
|
|
404
|
+
goToNextStep,
|
|
405
|
+
goToPrevStep,
|
|
406
|
+
goToStep,
|
|
407
|
+
setStepData,
|
|
408
|
+
handleStepChange,
|
|
409
|
+
validateStep,
|
|
410
|
+
validateAll,
|
|
411
|
+
save,
|
|
412
|
+
clearStorage,
|
|
413
|
+
setData,
|
|
414
|
+
getData
|
|
415
|
+
]
|
|
416
|
+
);
|
|
417
|
+
return /* @__PURE__ */ jsx(WizardStateContext.Provider, { value: stateValue, children: /* @__PURE__ */ jsx(WizardActionsContext.Provider, { value: actionsValue, children }) });
|
|
257
418
|
}
|
|
258
|
-
function
|
|
259
|
-
const context = useContext(
|
|
419
|
+
function useWizardState() {
|
|
420
|
+
const context = useContext(WizardStateContext);
|
|
260
421
|
if (!context) {
|
|
261
|
-
throw new Error("
|
|
422
|
+
throw new Error("useWizardState must be used within a WizardProvider");
|
|
262
423
|
}
|
|
263
424
|
return context;
|
|
264
425
|
}
|
|
426
|
+
function useWizardValue(path) {
|
|
427
|
+
const { store } = useWizardState();
|
|
428
|
+
const lastStateRef = useRef(null);
|
|
429
|
+
const lastValueRef = useRef(null);
|
|
430
|
+
const getSnapshot = useCallback(() => {
|
|
431
|
+
const fullState = store.getSnapshot();
|
|
432
|
+
const data = fullState.data;
|
|
433
|
+
if (data === lastStateRef.current) {
|
|
434
|
+
return lastValueRef.current;
|
|
435
|
+
}
|
|
436
|
+
const value = getByPath(data, path);
|
|
437
|
+
lastStateRef.current = data;
|
|
438
|
+
lastValueRef.current = value;
|
|
439
|
+
return value;
|
|
440
|
+
}, [store, path]);
|
|
441
|
+
return useSyncExternalStore(store.subscribe, getSnapshot);
|
|
442
|
+
}
|
|
443
|
+
function useWizardError(path) {
|
|
444
|
+
const { store } = useWizardState();
|
|
445
|
+
const lastStateRef = useRef(null);
|
|
446
|
+
const lastValueRef = useRef(null);
|
|
447
|
+
const getSnapshot = useCallback(() => {
|
|
448
|
+
const fullState = store.getSnapshot();
|
|
449
|
+
const errors = fullState.errors;
|
|
450
|
+
if (errors === lastStateRef.current) {
|
|
451
|
+
return lastValueRef.current;
|
|
452
|
+
}
|
|
453
|
+
let foundError;
|
|
454
|
+
Object.values(errors).forEach((stepErrors) => {
|
|
455
|
+
const typedStepErrors = stepErrors;
|
|
456
|
+
if (typedStepErrors[path]) foundError = typedStepErrors[path];
|
|
457
|
+
});
|
|
458
|
+
lastStateRef.current = errors;
|
|
459
|
+
lastValueRef.current = foundError;
|
|
460
|
+
return foundError;
|
|
461
|
+
}, [store, path]);
|
|
462
|
+
return useSyncExternalStore(store.subscribe, getSnapshot);
|
|
463
|
+
}
|
|
464
|
+
function useWizardSelector(selector) {
|
|
465
|
+
const { store } = useWizardState();
|
|
466
|
+
const lastStateRef = useRef(null);
|
|
467
|
+
const lastResultRef = useRef(null);
|
|
468
|
+
const getSnapshot = useCallback(() => {
|
|
469
|
+
const fullState = store.getSnapshot();
|
|
470
|
+
if (fullState === lastStateRef.current) {
|
|
471
|
+
return lastResultRef.current;
|
|
472
|
+
}
|
|
473
|
+
const result = selector(fullState.data);
|
|
474
|
+
lastStateRef.current = fullState;
|
|
475
|
+
lastResultRef.current = result;
|
|
476
|
+
return result;
|
|
477
|
+
}, [store, selector]);
|
|
478
|
+
return useSyncExternalStore(store.subscribe, getSnapshot);
|
|
479
|
+
}
|
|
480
|
+
function useWizardActions() {
|
|
481
|
+
const context = useContext(WizardActionsContext);
|
|
482
|
+
if (!context) {
|
|
483
|
+
throw new Error("useWizardActions must be used within a WizardProvider");
|
|
484
|
+
}
|
|
485
|
+
return context;
|
|
486
|
+
}
|
|
487
|
+
function useWizardContext() {
|
|
488
|
+
const state = useWizardState();
|
|
489
|
+
const actions = useWizardActions();
|
|
490
|
+
const wizardData = useWizardSelector((s) => s);
|
|
491
|
+
const fullState = state.store.getSnapshot();
|
|
492
|
+
return useMemo(
|
|
493
|
+
() => ({
|
|
494
|
+
...state,
|
|
495
|
+
...actions,
|
|
496
|
+
wizardData,
|
|
497
|
+
allErrors: fullState.errors
|
|
498
|
+
}),
|
|
499
|
+
[state, actions, wizardData, fullState.errors]
|
|
500
|
+
);
|
|
501
|
+
}
|
|
265
502
|
|
|
266
503
|
// src/hooks/useWizard.ts
|
|
267
504
|
var useWizard = () => {
|
|
268
505
|
return useWizardContext();
|
|
269
506
|
};
|
|
270
507
|
|
|
508
|
+
// src/factory.tsx
|
|
509
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
510
|
+
function createWizardFactory() {
|
|
511
|
+
const WizardProvider2 = ({
|
|
512
|
+
config,
|
|
513
|
+
initialData,
|
|
514
|
+
children
|
|
515
|
+
}) => {
|
|
516
|
+
return /* @__PURE__ */ jsx2(
|
|
517
|
+
WizardProvider,
|
|
518
|
+
{
|
|
519
|
+
config,
|
|
520
|
+
initialData,
|
|
521
|
+
children
|
|
522
|
+
}
|
|
523
|
+
);
|
|
524
|
+
};
|
|
525
|
+
const useWizard2 = () => {
|
|
526
|
+
return useWizard();
|
|
527
|
+
};
|
|
528
|
+
const useWizardContext2 = () => {
|
|
529
|
+
return useWizardContext();
|
|
530
|
+
};
|
|
531
|
+
const useWizardValue2 = (path) => {
|
|
532
|
+
return useWizardValue(path);
|
|
533
|
+
};
|
|
534
|
+
const useWizardSelector2 = (selector) => {
|
|
535
|
+
return useWizardSelector(selector);
|
|
536
|
+
};
|
|
537
|
+
const useWizardError2 = (path) => {
|
|
538
|
+
return useWizardError(path);
|
|
539
|
+
};
|
|
540
|
+
const useWizardActions2 = () => {
|
|
541
|
+
return useWizardActions();
|
|
542
|
+
};
|
|
543
|
+
const useWizardState2 = () => {
|
|
544
|
+
return useWizardState();
|
|
545
|
+
};
|
|
546
|
+
const createStep = (config) => config;
|
|
547
|
+
return {
|
|
548
|
+
WizardProvider: WizardProvider2,
|
|
549
|
+
useWizard: useWizard2,
|
|
550
|
+
useWizardContext: useWizardContext2,
|
|
551
|
+
useWizardValue: useWizardValue2,
|
|
552
|
+
useWizardSelector: useWizardSelector2,
|
|
553
|
+
useWizardError: useWizardError2,
|
|
554
|
+
useWizardActions: useWizardActions2,
|
|
555
|
+
useWizardState: useWizardState2,
|
|
556
|
+
createStep
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
|
|
271
560
|
// src/adapters/persistence/LocalStorageAdapter.ts
|
|
272
561
|
var LocalStorageAdapter = class {
|
|
273
562
|
constructor(prefix = "wizard_") {
|
|
@@ -317,16 +606,17 @@ var ZodAdapter = class {
|
|
|
317
606
|
return { isValid: true };
|
|
318
607
|
}
|
|
319
608
|
const errors = {};
|
|
320
|
-
result.error
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
609
|
+
if (result.error) {
|
|
610
|
+
result.error.issues.forEach((err) => {
|
|
611
|
+
const path = err.path.join(".");
|
|
612
|
+
errors[path] = err.message;
|
|
613
|
+
});
|
|
614
|
+
}
|
|
324
615
|
return { isValid: false, errors };
|
|
325
616
|
}
|
|
326
617
|
};
|
|
327
618
|
|
|
328
619
|
// src/adapters/validation/YupAdapter.ts
|
|
329
|
-
import { ValidationError } from "yup";
|
|
330
620
|
var YupAdapter = class {
|
|
331
621
|
constructor(schema) {
|
|
332
622
|
__publicField(this, "schema");
|
|
@@ -337,9 +627,10 @@ var YupAdapter = class {
|
|
|
337
627
|
await this.schema.validate(data, { abortEarly: false });
|
|
338
628
|
return { isValid: true };
|
|
339
629
|
} catch (err) {
|
|
340
|
-
if (err
|
|
630
|
+
if (err && typeof err === "object" && "inner" in err) {
|
|
631
|
+
const yupError = err;
|
|
341
632
|
const errors = {};
|
|
342
|
-
|
|
633
|
+
yupError.inner.forEach((error) => {
|
|
343
634
|
if (error.path) {
|
|
344
635
|
errors[error.path] = error.message;
|
|
345
636
|
}
|
|
@@ -354,11 +645,18 @@ export {
|
|
|
354
645
|
LocalStorageAdapter,
|
|
355
646
|
MemoryAdapter,
|
|
356
647
|
WizardProvider,
|
|
648
|
+
WizardStore,
|
|
357
649
|
YupAdapter,
|
|
358
650
|
ZodAdapter,
|
|
651
|
+
createWizardFactory,
|
|
359
652
|
getByPath,
|
|
360
653
|
setByPath,
|
|
361
654
|
useWizard,
|
|
362
|
-
|
|
655
|
+
useWizardActions,
|
|
656
|
+
useWizardContext,
|
|
657
|
+
useWizardError,
|
|
658
|
+
useWizardSelector,
|
|
659
|
+
useWizardState,
|
|
660
|
+
useWizardValue
|
|
363
661
|
};
|
|
364
662
|
//# sourceMappingURL=index.js.map
|