@wizzard-packages/core 0.1.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.
@@ -0,0 +1,499 @@
1
+ /**
2
+ * @module Types (Core)
3
+ */
4
+ /**
5
+ * Full state of the wizard.
6
+ */
7
+ interface IWizardState<T = unknown, StepId extends string = string> {
8
+ /** Global wizard data object */
9
+ data: T;
10
+ /** Current errors map by step and field */
11
+ errors: Record<StepId, Record<string, string>>;
12
+ /** Active step configuration (if any) */
13
+ currentStep: IStepConfig<T, StepId> | null;
14
+ /** Numeric index of current step in active steps list */
15
+ currentStepIndex: number;
16
+ /** True if currently on the first active step */
17
+ isFirstStep: boolean;
18
+ /** True if currently on the last active step */
19
+ isLastStep: boolean;
20
+ /** True if the wizard is in an initial loading/hydrating state */
21
+ isLoading: boolean;
22
+ /** True if an async action (like navigation or validation) is in progress */
23
+ isPending: boolean;
24
+ /** List of steps that currently meet their visibility conditions */
25
+ activeSteps: IStepConfig<T, StepId>[];
26
+ /** String ID of the current step */
27
+ currentStepId: StepId | '';
28
+ /** History of visited steps (navigation path) */
29
+ history: StepId[];
30
+ /** Set of step IDs that are currently performing async work */
31
+ busySteps: Set<StepId>;
32
+ /** Set of step IDs that have been visited by the user */
33
+ visitedSteps: Set<StepId>;
34
+ /** Set of step IDs that have passed validation */
35
+ completedSteps: Set<StepId>;
36
+ /** Set of step IDs that currently have active validation errors */
37
+ errorSteps: Set<StepId>;
38
+ /** Current wizard configuration */
39
+ config: IWizardConfig<T, StepId>;
40
+ /** Percentage of completion (0-100) */
41
+ progress: number;
42
+ /** Number of active steps */
43
+ activeStepsCount: number;
44
+ /** Alias for isPending */
45
+ isBusy: boolean;
46
+ /** True if any field has been modified since initialization */
47
+ isDirty: boolean;
48
+ /** Set of paths to fields that have been modified */
49
+ dirtyFields: Set<string>;
50
+ /** Breadcrumb items for navigation UI */
51
+ breadcrumbs: IBreadcrumb<StepId>[];
52
+ /** Result of the last goToStep action */
53
+ goToStepResult?: boolean | null | 'init';
54
+ }
55
+ /**
56
+ * Store interface for reading state and dispatching actions.
57
+ */
58
+ interface IWizardStore<T, StepId extends string = string> {
59
+ getSnapshot(): IWizardState<T, StepId>;
60
+ dispatch(action: WizardAction<T, StepId>): void;
61
+ update(newData: T, changedPath?: string | string[]): void;
62
+ updateMeta(newMeta: Partial<IWizardState<T, StepId>>): void;
63
+ setInitialData(data: T): void;
64
+ updateErrors(newErrors: Record<string, Record<string, string>>): void;
65
+ setStepErrors(stepId: string, errors: Record<string, string> | undefined | null): boolean;
66
+ deleteError(stepId: string, path: string): boolean;
67
+ subscribe(listener: () => void): () => void;
68
+ subscribeToActions(listener: (action: WizardAction<T, StepId>) => void): () => void;
69
+ injectPersistence(adapter: IPersistenceAdapter): void;
70
+ save(stepId?: StepId): void;
71
+ hydrate(): void;
72
+ errorsMap: Map<string, Map<string, string>>;
73
+ resolveActiveSteps(data?: T): Promise<IStepConfig<T, StepId>[]>;
74
+ goToStep(stepId: StepId, options?: {
75
+ validate?: boolean;
76
+ providedActiveSteps?: IStepConfig<T, StepId>[];
77
+ }): Promise<boolean>;
78
+ validateStep: (stepId: StepId) => Promise<boolean>;
79
+ validateAll: () => Promise<{
80
+ isValid: boolean;
81
+ errors: Record<string, Record<string, string>>;
82
+ }>;
83
+ }
84
+ /**
85
+ * Public actions available to control the wizard.
86
+ */
87
+ interface IWizardActions<StepId extends string = string> {
88
+ goToNextStep: () => Promise<void>;
89
+ goToPrevStep: () => Promise<void>;
90
+ goToStep: (stepId: StepId, providedActiveSteps?: any[], options?: {
91
+ validate?: boolean;
92
+ }) => Promise<boolean>;
93
+ setStepData: (stepId: StepId, data: unknown) => void;
94
+ handleStepChange: (field: string, value: unknown) => void;
95
+ validateStep: (sid: StepId) => Promise<boolean>;
96
+ validateAll: () => Promise<{
97
+ isValid: boolean;
98
+ errors: Record<string, Record<string, string>>;
99
+ }>;
100
+ save: (stepIds?: StepId | StepId[] | boolean) => void;
101
+ clearStorage: () => void;
102
+ reset: () => void;
103
+ setData: (path: string, value: unknown, options?: {
104
+ debounceValidation?: number;
105
+ }) => void;
106
+ updateData: (data: Partial<any>, options?: {
107
+ replace?: boolean;
108
+ persist?: boolean;
109
+ }) => void;
110
+ getData: (path: string, defaultValue?: unknown) => unknown;
111
+ updateConfig: (config: Partial<IWizardConfig<any, StepId>>) => void;
112
+ }
113
+ /**
114
+ * Validation Result Interface
115
+ */
116
+ type ValidationResult = {
117
+ isValid: boolean;
118
+ errors?: Record<string, string>;
119
+ };
120
+ /**
121
+ * Validator Adapter Interface
122
+ */
123
+ interface IValidatorAdapter<TData = unknown> {
124
+ validate: (data: TData) => Promise<ValidationResult> | ValidationResult;
125
+ }
126
+ /**
127
+ * Persistence strategy for step data.
128
+ */
129
+ type PersistenceMode = 'onStepChange' | 'onChange' | 'manual';
130
+ /**
131
+ * Validation strategy for step data.
132
+ */
133
+ type ValidationMode = 'onChange' | 'onStepChange' | 'manual';
134
+ /**
135
+ * Persistence Adapter Interface
136
+ */
137
+ interface IPersistenceAdapter {
138
+ saveStep: <T>(stepId: string, data: T) => void;
139
+ getStep: <T>(stepId: string) => T | undefined;
140
+ getStepWithMeta?: <T>(stepId: string) => {
141
+ data: T;
142
+ timestamp: number;
143
+ } | undefined;
144
+ clearStep: (stepId: string) => void;
145
+ clear: () => void;
146
+ }
147
+ /**
148
+ * Step Navigation Direction
149
+ */
150
+ type StepDirection = 'next' | 'prev';
151
+ /**
152
+ * Step Configuration
153
+ */
154
+ interface IStepConfig<TStepData = unknown, StepId extends string = string> {
155
+ id: StepId;
156
+ label: string;
157
+ condition?: (data: TStepData, metadata: Partial<IWizardState<TStepData, StepId>> & {
158
+ data?: TStepData | undefined;
159
+ allErrors?: any;
160
+ }) => boolean | Promise<boolean>;
161
+ showWhilePending?: boolean;
162
+ conditionDependsOn?: string[];
163
+ beforeLeave?: (data: TStepData, direction: StepDirection, metadata: Partial<IWizardState<TStepData, StepId>> & {
164
+ data?: TStepData | undefined;
165
+ allErrors?: any;
166
+ }) => boolean | Promise<boolean>;
167
+ validationAdapter?: IValidatorAdapter<TStepData>;
168
+ /** @deprecated Use validationMode instead */
169
+ autoValidate?: boolean;
170
+ validationMode?: ValidationMode;
171
+ component?: any;
172
+ persistenceAdapter?: IPersistenceAdapter;
173
+ persistenceMode?: PersistenceMode;
174
+ dependsOn?: string[];
175
+ clearData?: string | string[] | ((data: TStepData, changedFields: string[]) => Partial<TStepData>);
176
+ canNavigateTo?: (data: TStepData, metadata: Partial<IWizardState<TStepData, StepId>> & {
177
+ data?: TStepData | undefined;
178
+ allErrors?: any;
179
+ }) => boolean | Promise<boolean>;
180
+ }
181
+ /**
182
+ * Global Wizard Configuration.
183
+ */
184
+ interface IWizardConfig<T = unknown, StepId extends string = string> {
185
+ steps: IStepConfig<T, StepId>[];
186
+ /** @deprecated Use validationMode instead */
187
+ autoValidate?: boolean;
188
+ validationMode?: ValidationMode;
189
+ validationDebounceTime?: number;
190
+ persistence?: {
191
+ mode?: PersistenceMode;
192
+ adapter?: IPersistenceAdapter;
193
+ storageKey?: string;
194
+ debounceTime?: number;
195
+ };
196
+ onConflict?: 'merge' | 'replace' | 'keep-local';
197
+ analytics?: {
198
+ onEvent: WizardEventHandler<StepId>;
199
+ };
200
+ middlewares?: WizardMiddleware<T, StepId>[];
201
+ navigationMode?: 'sequential' | 'visited' | 'free';
202
+ onStepChange?: (fromStep: StepId | null, toStep: StepId, data: T) => void;
203
+ }
204
+ /**
205
+ * Action Types
206
+ */
207
+ type WizardAction<T = any, StepId extends string = string> = {
208
+ type: 'INIT';
209
+ payload: {
210
+ data: T;
211
+ config: IWizardConfig<T, StepId>;
212
+ };
213
+ } | {
214
+ type: 'SET_DATA';
215
+ payload: {
216
+ path: string;
217
+ value: any;
218
+ options?: any;
219
+ };
220
+ } | {
221
+ type: 'UPDATE_DATA';
222
+ payload: {
223
+ data: Partial<T>;
224
+ options?: any;
225
+ };
226
+ } | {
227
+ type: 'GO_TO_STEP';
228
+ payload: {
229
+ from: StepId;
230
+ to: StepId;
231
+ result: boolean | null | 'init';
232
+ nextVisitedSteps?: Set<StepId>;
233
+ nextHistory?: StepId[];
234
+ };
235
+ } | {
236
+ type: 'VALIDATE_START';
237
+ payload: {
238
+ stepId: StepId;
239
+ };
240
+ } | {
241
+ type: 'VALIDATE_END';
242
+ payload: {
243
+ stepId: StepId;
244
+ result: ValidationResult;
245
+ };
246
+ } | {
247
+ type: 'SET_STEP_ERRORS';
248
+ payload: {
249
+ stepId: StepId;
250
+ errors: Record<string, string> | undefined | null;
251
+ };
252
+ } | {
253
+ type: 'RESET';
254
+ payload: {
255
+ data: T;
256
+ };
257
+ } | {
258
+ type: 'UPDATE_META';
259
+ payload: {
260
+ meta: Partial<IWizardState<T, StepId>>;
261
+ };
262
+ } | {
263
+ type: 'SET_CURRENT_STEP_ID';
264
+ payload: {
265
+ stepId: StepId | '';
266
+ };
267
+ } | {
268
+ type: 'SET_HISTORY';
269
+ payload: {
270
+ history: StepId[];
271
+ };
272
+ } | {
273
+ type: 'SET_ACTIVE_STEPS';
274
+ payload: {
275
+ steps: IStepConfig<T, StepId>[];
276
+ };
277
+ } | {
278
+ type: 'SET_VISITED_STEPS';
279
+ payload: {
280
+ steps: Set<StepId>;
281
+ };
282
+ } | {
283
+ type: 'SET_COMPLETED_STEPS';
284
+ payload: {
285
+ steps: Set<StepId>;
286
+ };
287
+ } | {
288
+ type: 'SET_ERROR_STEPS';
289
+ payload: {
290
+ steps: Set<StepId>;
291
+ };
292
+ } | {
293
+ type: 'RESTORE_SNAPSHOT';
294
+ payload: {
295
+ snapshot: any;
296
+ };
297
+ };
298
+ /**
299
+ * Middleware API
300
+ */
301
+ interface MiddlewareAPI<T = any, StepId extends string = string> {
302
+ dispatch: (action: WizardAction<T, StepId>) => void;
303
+ getState: () => T;
304
+ getSnapshot: () => IWizardState<T, StepId>;
305
+ }
306
+ /**
307
+ * Middleware Type Definition
308
+ */
309
+ type WizardMiddleware<T = any, StepId extends string = string> = (api: MiddlewareAPI<T, StepId>) => (next: (action: WizardAction<T, StepId>) => void) => (action: WizardAction<T, StepId>) => void;
310
+ /**
311
+ * Standardized Event Names
312
+ */
313
+ type WizardEventName = 'step_change' | 'validation_error' | 'wizard_reset';
314
+ /**
315
+ * Event Payloads
316
+ */
317
+ type WizardEventPayloads<StepId extends string = string> = {
318
+ step_change: {
319
+ from: StepId | null;
320
+ to: StepId;
321
+ timestamp: number;
322
+ };
323
+ validation_error: {
324
+ stepId: StepId;
325
+ errors: Record<string, string> | undefined;
326
+ timestamp: number;
327
+ };
328
+ wizard_reset: {
329
+ data: any;
330
+ timestamp?: number;
331
+ };
332
+ };
333
+ /**
334
+ * Generic Event Handler Type
335
+ */
336
+ type WizardEventHandler<StepId extends string = string> = <E extends WizardEventName>(name: E, payload: WizardEventPayloads<StepId>[E]) => void;
337
+ /**
338
+ * Breadcrumb Status
339
+ */
340
+ type BreadcrumbStatus = 'visited' | 'current' | 'upcoming' | 'completed' | 'error' | 'hidden';
341
+ /**
342
+ * Breadcrumb Interface
343
+ */
344
+ interface IBreadcrumb<StepId extends string = string> {
345
+ id: StepId;
346
+ label: string;
347
+ status: BreadcrumbStatus;
348
+ }
349
+ /**
350
+ * High-level context for the wizard, combining state and actions.
351
+ */
352
+ interface IWizardContext<T = unknown, StepId extends string = string> extends Omit<IWizardState<T, StepId>, 'errors'>, IWizardActions<StepId> {
353
+ /**
354
+ * The internal store instance.
355
+ */
356
+ store: IWizardStore<T, StepId>;
357
+ /**
358
+ * Combined error map (flat)
359
+ */
360
+ errors: Record<string, string>;
361
+ /**
362
+ * All errors by step and field.
363
+ */
364
+ allErrors: Record<StepId, Record<string, string>>;
365
+ }
366
+
367
+ /**
368
+ * Core event-driven store for managing wizard state, data, and navigation.
369
+ *
370
+ * @template T Type of the global wizard data object
371
+ * @template StepId String union of valid step IDs
372
+ */
373
+ declare class WizardStore<T, StepId extends string = string> implements IWizardStore<T, StepId> {
374
+ private initialData;
375
+ private dirtyFields;
376
+ private state;
377
+ private listeners;
378
+ private actionListeners;
379
+ errorsMap: Map<StepId, Map<string, string>>;
380
+ private middlewareChain;
381
+ private persistenceAdapter?;
382
+ private persistenceDebounceTimers;
383
+ private stepsMap;
384
+ subscribeToActions(listener: (action: WizardAction<T, StepId>) => void): () => boolean;
385
+ private notifyActions;
386
+ constructor(initialData: T, middlewares?: WizardMiddleware<T, StepId>[]);
387
+ private setupMiddlewares;
388
+ /**
389
+ * Processes an action through the middleware chain and updates the state.
390
+ * This is the primary way to trigger any state change in the wizard.
391
+ *
392
+ * @param action The action to perform
393
+ */
394
+ dispatch(action: WizardAction<T, StepId>): void;
395
+ /**
396
+ * Internal dispatch that actually performs the state updates
397
+ */
398
+ private internalDispatch;
399
+ private updateDataByPath;
400
+ private updateBulkData;
401
+ /**
402
+ * Returns the current immutable snapshot of the wizard state.
403
+ */
404
+ getSnapshot: () => IWizardState<T, StepId>;
405
+ /**
406
+ * Performs a granular data update at a specific path.
407
+ * Automatically calculates dirty fields and triggers auto-save if configured.
408
+ *
409
+ * @param newData Full new data object
410
+ * @param changedPath Path(s) that were modified
411
+ */
412
+ update(newData: T, changedPath?: string | string[]): void;
413
+ updateMeta(newMeta: Partial<IWizardState<T, StepId>>): void;
414
+ private syncDerivedState;
415
+ /**
416
+ * Sets the initial data for the wizard.
417
+ * Resets dirty tracking based on this new data.
418
+ */
419
+ setInitialData(data: T): void;
420
+ private syncErrors;
421
+ updateErrors(newErrors: Record<StepId, Record<string, string>>): void;
422
+ setStepErrors(stepId: StepId, errors: Record<string, string> | undefined | null): boolean;
423
+ deleteError(stepId: StepId, path: string): boolean;
424
+ private notify;
425
+ subscribe: (listener: () => void) => () => boolean;
426
+ injectPersistence(adapter: IPersistenceAdapter): void;
427
+ /**
428
+ * Restores wizard state from persistence storage.
429
+ * Implements "latest wins" conflict resolution based on step timestamps.
430
+ */
431
+ hydrate(): void;
432
+ private saveMeta;
433
+ clearStepStorage(stepId: string): void;
434
+ /**
435
+ * Manually triggers data persistence for specific steps or the current step.
436
+ *
437
+ * @param stepId Optional ID of step to save. If omitted, saves current step.
438
+ */
439
+ save(stepId?: StepId): void;
440
+ private saveStepData;
441
+ private handleStepChangePersistence;
442
+ private checkAutoSave;
443
+ private conditionCache;
444
+ /**
445
+ * Evaluates visibility conditions for all steps and returns only those that should be active.
446
+ * Uses memoization to avoid redundant async calls if dependencies haven't changed.
447
+ *
448
+ * @param data Optional data override for evaluation
449
+ */
450
+ resolveActiveSteps(data?: T): Promise<IStepConfig<T, StepId>[]>;
451
+ validateStep(stepId: StepId): Promise<boolean>;
452
+ validateAll(): Promise<{
453
+ isValid: boolean;
454
+ errors: Record<string, Record<string, string>>;
455
+ }>;
456
+ goToStep(stepId: StepId, options?: {
457
+ validate?: boolean;
458
+ providedActiveSteps?: IStepConfig<T, StepId>[];
459
+ }): Promise<boolean>;
460
+ }
461
+
462
+ /**
463
+ * Parses a string path into an array of keys using a cache.
464
+ */
465
+ declare function toPath(path: string): string[];
466
+ /**
467
+ * Retrieves a value from an object by path.
468
+ */
469
+ declare function getByPath(obj: any, path: string, defaultValue?: unknown): unknown;
470
+ /**
471
+ * Immutably sets a value in an object by path.
472
+ */
473
+ declare function setByPath<T extends object>(obj: T, path: string, value: unknown): T;
474
+ /**
475
+ * Simple shallow equality check.
476
+ */
477
+ declare function shallowEqual(a: any, b: any): boolean;
478
+
479
+ /**
480
+ * Utility types for dot-notation paths
481
+ */
482
+ type Primitive = null | undefined | string | number | boolean | symbol | bigint;
483
+ type IsTuple<T extends ReadonlyArray<any>> = number extends T['length'] ? false : true;
484
+ type TupleKeys<T extends ReadonlyArray<any>> = Exclude<keyof T, keyof any[]>;
485
+ type PathImpl<K extends string | number, V> = V extends Primitive ? `${K}` : `${K}` | `${K}.${Path<V>}`;
486
+ /**
487
+ * Dot-notation path for a nested data type.
488
+ */
489
+ type Path<T> = T extends ReadonlyArray<infer V> ? IsTuple<T> extends true ? {
490
+ [K in TupleKeys<T>]-?: PathImpl<K & string, T[K]>;
491
+ }[TupleKeys<T>] : PathImpl<number, V> : {
492
+ [K in keyof T]-?: PathImpl<K & string, T[K]>;
493
+ }[keyof T];
494
+ /**
495
+ * Value type resolved from a dot-notation path.
496
+ */
497
+ type PathValue<T, P extends Path<T>> = T extends any ? P extends `${infer K}.${infer R}` ? K extends keyof T ? R extends Path<T[K]> ? PathValue<T[K], R> : never : K extends `${number}` ? T extends ReadonlyArray<infer V> ? R extends Path<V> ? PathValue<V, R> : never : never : never : P extends keyof T ? T[P] : P extends `${number}` ? T extends ReadonlyArray<infer V> ? V : never : never : never;
498
+
499
+ export { type BreadcrumbStatus, type IBreadcrumb, type IPersistenceAdapter, type IStepConfig, type IValidatorAdapter, type IWizardActions, type IWizardConfig, type IWizardContext, type IWizardState, type IWizardStore, type MiddlewareAPI, type Path, type PathValue, type PersistenceMode, type StepDirection, type ValidationMode, type ValidationResult, type WizardAction, type WizardEventHandler, type WizardEventName, type WizardEventPayloads, type WizardMiddleware, WizardStore, getByPath, setByPath, shallowEqual, toPath };