@rilaykit/workflow 4.0.0 → 5.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.
package/dist/index.d.mts CHANGED
@@ -1,11 +1,9 @@
1
- import { ril, FormConfiguration, StepLifecycleHooks, StepPermissions, CustomStepRenderer, DynamicStepConfig, NavigationConfig, PersistenceConfig, CompletionConfig, WorkflowAnalytics, WorkflowPlugin, StepConfig, WorkflowConfig, WorkflowContext, ValidationError, ValidationResult, RendererChildrenFunction, WorkflowNextButtonRendererProps, WorkflowPreviousButtonRendererProps, WorkflowSkipButtonRendererProps, WorkflowStepperRendererProps } from '@rilaykit/core';
1
+ import { ril, FormConfiguration, CustomStepRenderer, StepDataHelper, WorkflowContext, WorkflowAnalytics, WorkflowPlugin, StepConfig, WorkflowConfig, ComponentRendererBaseProps, WorkflowNextButtonRendererProps, WorkflowPreviousButtonRendererProps, WorkflowSkipButtonRendererProps, WorkflowStepperRendererProps } from '@rilaykit/core';
2
2
  export * from '@rilaykit/core';
3
- export { createZodValidator, ril } from '@rilaykit/core';
4
3
  import { form } from '@rilaykit/forms';
5
4
  export { form } from '@rilaykit/forms';
6
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
7
- import * as react from 'react';
8
- import react__default from 'react';
6
+ import React from 'react';
9
7
 
10
8
  /**
11
9
  * Enhanced step configuration interface for better type safety and simplicity
@@ -47,26 +45,41 @@ interface StepDefinition {
47
45
  * @default true
48
46
  */
49
47
  requiredToComplete?: boolean;
50
- /**
51
- * Lifecycle hooks for step events
52
- * Allows custom logic at different points in the step lifecycle
53
- */
54
- hooks?: StepLifecycleHooks;
55
- /**
56
- * Permission configuration for step access control
57
- * Defines who can view, edit, or complete this step
58
- */
59
- permissions?: StepPermissions;
60
48
  /**
61
49
  * Custom renderer for the step
62
50
  * Allows complete customization of step presentation
63
51
  */
64
52
  renderer?: CustomStepRenderer;
65
53
  /**
66
- * Dynamic step configuration
67
- * Enables conditional step behavior based on previous step data
54
+ * Callback function that executes after successful validation and before moving to next step
55
+ * Provides clean helper methods for modifying workflow data and pre-filling subsequent steps
56
+ *
57
+ * @param stepData - The validated data from the current step
58
+ * @param helper - Helper object with methods to modify workflow data cleanly
59
+ * @param context - Full workflow context for reference
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * onAfterValidation: async (stepData, helper, context) => {
64
+ * // API call based on current step data
65
+ * const companyInfo = await fetchCompanyBySiren(stepData.siren);
66
+ *
67
+ * // Pre-fill next step with clean helper methods
68
+ * helper.setNextStepFields({
69
+ * companyName: companyInfo.name,
70
+ * address: companyInfo.address,
71
+ * industry: companyInfo.sector
72
+ * });
73
+ *
74
+ * // Or set data for a specific step
75
+ * helper.setStepFields('company-details', {
76
+ * legalForm: companyInfo.legalForm,
77
+ * foundedYear: companyInfo.creation_date
78
+ * });
79
+ * }
80
+ * ```
68
81
  */
69
- dynamicConfig?: DynamicStepConfig;
82
+ onAfterValidation?: (stepData: Record<string, any>, helper: StepDataHelper, context: WorkflowContext) => void | Promise<void>;
70
83
  }
71
84
  /**
72
85
  * Configuration options for workflow behavior and features
@@ -77,12 +90,6 @@ interface StepDefinition {
77
90
  * @interface WorkflowOptions
78
91
  */
79
92
  interface WorkflowOptions {
80
- /** Navigation behavior configuration */
81
- navigation?: NavigationConfig;
82
- /** Data persistence settings */
83
- persistence?: PersistenceConfig;
84
- /** Workflow completion handling */
85
- completion?: CompletionConfig;
86
93
  /** Analytics and tracking configuration */
87
94
  analytics?: WorkflowAnalytics;
88
95
  }
@@ -128,9 +135,6 @@ declare class flow {
128
135
  private workflowName;
129
136
  private workflowDescription?;
130
137
  private steps;
131
- private navigation;
132
- private persistence?;
133
- private completion?;
134
138
  private analytics?;
135
139
  private plugins;
136
140
  private idGenerator;
@@ -166,7 +170,7 @@ declare class flow {
166
170
  *
167
171
  * This internal method handles the conversion from the user-friendly
168
172
  * StepDefinition interface to the internal StepConfig structure,
169
- * including ID generation and form configuration processing.
173
+ * including ID generation, form configuration processing, and validation setup.
170
174
  *
171
175
  * @private
172
176
  * @param stepDef - The step definition to convert
@@ -209,31 +213,6 @@ declare class flow {
209
213
  * ```
210
214
  */
211
215
  addStep(stepDefinitions: StepDefinition[]): this;
212
- /**
213
- * Add a dynamic step using StepDefinition with dynamicConfig
214
- *
215
- * Dynamic steps can change their behavior, visibility, or configuration
216
- * based on data from previous steps. This method is a convenience wrapper
217
- * around addStep() with enhanced type safety for dynamic configurations.
218
- *
219
- * @param stepDefinition - Step definition with required dynamicConfig
220
- * @returns The flow instance for method chaining
221
- *
222
- * @example
223
- * ```typescript
224
- * workflow.addDynamicStep({
225
- * title: 'Conditional Step',
226
- * formConfig: conditionalForm,
227
- * dynamicConfig: {
228
- * condition: (data) => data.userType === 'premium',
229
- * generator: (data) => generatePremiumForm(data)
230
- * }
231
- * });
232
- * ```
233
- */
234
- addDynamicStep(stepDefinition: StepDefinition & {
235
- dynamicConfig: DynamicStepConfig;
236
- }): this;
237
216
  /**
238
217
  * Universal configuration method for all workflow options
239
218
  *
@@ -429,20 +408,12 @@ declare class flow {
429
408
  * ```
430
409
  */
431
410
  getStats(): {
432
- /** Total number of steps in the workflow */
433
411
  totalSteps: number;
434
- /** Number of dynamic steps */
435
- dynamicSteps: number;
436
- /** Number of installed plugins */
437
- pluginsInstalled: number;
438
- /** Estimated total number of form fields across all steps */
439
- estimatedFields: number;
440
- /** Whether persistence is configured */
441
- hasPersistence: boolean;
442
- /** Whether analytics is configured */
412
+ totalFields: number;
413
+ averageFieldsPerStep: number;
414
+ maxFieldsInStep: number;
415
+ minFieldsInStep: number;
443
416
  hasAnalytics: boolean;
444
- /** Whether back navigation is allowed */
445
- allowBackNavigation: boolean;
446
417
  };
447
418
  /**
448
419
  * Build the final workflow configuration
@@ -549,14 +520,9 @@ interface WorkflowState {
549
520
  currentStepIndex: number;
550
521
  allData: Record<string, any>;
551
522
  stepData: Record<string, any>;
552
- errors: Record<string, ValidationError[]>;
553
- touched: Set<string>;
554
- isValidating: Set<string>;
555
523
  visitedSteps: Set<string>;
556
524
  isSubmitting: boolean;
557
525
  isTransitioning: boolean;
558
- persistedData?: any;
559
- resolvedSteps: StepConfig[];
560
526
  }
561
527
  interface WorkflowContextValue {
562
528
  workflowState: WorkflowState;
@@ -570,27 +536,22 @@ interface WorkflowContextValue {
570
536
  skipStep: () => Promise<boolean>;
571
537
  setValue: (fieldId: string, value: any) => void;
572
538
  setStepData: (data: Record<string, any>) => void;
573
- validateCurrentStep: () => Promise<ValidationResult>;
574
539
  submitWorkflow: () => Promise<void>;
575
540
  resetWorkflow: () => void;
576
- saveDraft: () => Promise<void>;
577
- loadDraft: () => Promise<void>;
578
- clearDraft: () => Promise<void>;
579
541
  }
580
542
  interface WorkflowProviderProps {
581
- children: react__default.ReactNode;
543
+ children: React.ReactNode;
582
544
  workflowConfig: WorkflowConfig;
583
545
  defaultValues?: Record<string, any>;
584
546
  onStepChange?: (fromStep: number, toStep: number, context: WorkflowContext) => void;
585
547
  onWorkflowComplete?: (data: Record<string, any>) => void | Promise<void>;
586
548
  className?: string;
587
- user?: any;
588
549
  }
589
- declare function WorkflowProvider({ children, workflowConfig, defaultValues, onStepChange, onWorkflowComplete, className, user, }: WorkflowProviderProps): react_jsx_runtime.JSX.Element;
550
+ declare function WorkflowProvider({ children, workflowConfig, defaultValues, onStepChange, onWorkflowComplete, className, }: WorkflowProviderProps): react_jsx_runtime.JSX.Element;
590
551
  declare function useWorkflowContext(): WorkflowContextValue;
591
552
 
592
553
  type WorkflowProps = Omit<WorkflowProviderProps, 'children' | 'workflowConfig'> & {
593
- children: react__default.ReactNode;
554
+ children: React.ReactNode;
594
555
  workflowConfig: WorkflowConfig | flow;
595
556
  };
596
557
  /**
@@ -607,34 +568,16 @@ declare function Workflow({ children, workflowConfig, ...props }: WorkflowProps)
607
568
  */
608
569
  declare function WorkflowBody(): react_jsx_runtime.JSX.Element | null;
609
570
 
610
- interface WorkflowNextButtonProps {
611
- className?: string;
612
- children?: React.ReactNode | RendererChildrenFunction<WorkflowNextButtonRendererProps>;
613
- renderAs?: 'default' | 'children' | boolean;
614
- }
615
- declare function WorkflowNextButton({ className, children, renderAs }: WorkflowNextButtonProps): react.ReactNode;
571
+ declare function WorkflowNextButton({ className, ...props }: ComponentRendererBaseProps<WorkflowNextButtonRendererProps>): react_jsx_runtime.JSX.Element;
616
572
 
617
- interface WorkflowPreviousButtonProps {
618
- className?: string;
619
- children?: React.ReactNode | RendererChildrenFunction<WorkflowPreviousButtonRendererProps>;
620
- renderAs?: 'default' | 'children' | boolean;
621
- }
622
- declare function WorkflowPreviousButton({ className, children, renderAs, }: WorkflowPreviousButtonProps): react.ReactNode;
573
+ declare function WorkflowPreviousButton({ className, ...props }: ComponentRendererBaseProps<WorkflowPreviousButtonRendererProps>): react_jsx_runtime.JSX.Element;
623
574
 
624
- interface WorkflowSkipButtonProps {
625
- className?: string;
626
- children?: React.ReactNode | RendererChildrenFunction<WorkflowSkipButtonRendererProps>;
627
- renderAs?: 'default' | 'children' | boolean;
628
- }
629
- declare function WorkflowSkipButton({ className, children, renderAs }: WorkflowSkipButtonProps): react.ReactNode;
575
+ declare function WorkflowSkipButton({ className, ...props }: ComponentRendererBaseProps<WorkflowSkipButtonRendererProps>): react_jsx_runtime.JSX.Element;
630
576
 
631
- interface WorkflowStepperProps {
577
+ interface WorkflowStepperProps extends ComponentRendererBaseProps<WorkflowStepperRendererProps> {
632
578
  onStepClick?: (stepIndex: number) => void;
633
- className?: string;
634
- children?: React.ReactNode | RendererChildrenFunction<WorkflowStepperRendererProps>;
635
- renderAs?: 'default' | 'children' | boolean;
636
579
  }
637
- declare function WorkflowStepper({ onStepClick, className, children, renderAs, }: WorkflowStepperProps): react.ReactNode;
580
+ declare function WorkflowStepper({ onStepClick, className, ...props }: WorkflowStepperProps): react_jsx_runtime.JSX.Element;
638
581
 
639
582
  interface LicensePayload {
640
583
  plan: 'ARCHITECT' | 'FOUNDRY';
@@ -704,4 +647,4 @@ declare class RilayLicenseManager {
704
647
  }>;
705
648
  }
706
649
 
707
- export { type LicensePayload, type LicensePlan, type LicenseResult, RilayLicenseManager, type StepDefinition, Workflow, WorkflowBody, type WorkflowContextValue, WorkflowNextButton, type WorkflowNextButtonProps, WorkflowPreviousButton, type WorkflowPreviousButtonProps, WorkflowProvider, type WorkflowProviderProps, WorkflowSkipButton, type WorkflowSkipButtonProps, WorkflowStepper, type WorkflowStepperProps, createFlow, flow, useWorkflowContext };
650
+ export { type LicensePayload, type LicensePlan, type LicenseResult, RilayLicenseManager, type StepDefinition, Workflow, WorkflowBody, type WorkflowContextValue, WorkflowNextButton, WorkflowPreviousButton, WorkflowProvider, WorkflowSkipButton, WorkflowStepper, createFlow, flow, useWorkflowContext };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,9 @@
1
- import { ril, FormConfiguration, StepLifecycleHooks, StepPermissions, CustomStepRenderer, DynamicStepConfig, NavigationConfig, PersistenceConfig, CompletionConfig, WorkflowAnalytics, WorkflowPlugin, StepConfig, WorkflowConfig, WorkflowContext, ValidationError, ValidationResult, RendererChildrenFunction, WorkflowNextButtonRendererProps, WorkflowPreviousButtonRendererProps, WorkflowSkipButtonRendererProps, WorkflowStepperRendererProps } from '@rilaykit/core';
1
+ import { ril, FormConfiguration, CustomStepRenderer, StepDataHelper, WorkflowContext, WorkflowAnalytics, WorkflowPlugin, StepConfig, WorkflowConfig, ComponentRendererBaseProps, WorkflowNextButtonRendererProps, WorkflowPreviousButtonRendererProps, WorkflowSkipButtonRendererProps, WorkflowStepperRendererProps } from '@rilaykit/core';
2
2
  export * from '@rilaykit/core';
3
- export { createZodValidator, ril } from '@rilaykit/core';
4
3
  import { form } from '@rilaykit/forms';
5
4
  export { form } from '@rilaykit/forms';
6
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
7
- import * as react from 'react';
8
- import react__default from 'react';
6
+ import React from 'react';
9
7
 
10
8
  /**
11
9
  * Enhanced step configuration interface for better type safety and simplicity
@@ -47,26 +45,41 @@ interface StepDefinition {
47
45
  * @default true
48
46
  */
49
47
  requiredToComplete?: boolean;
50
- /**
51
- * Lifecycle hooks for step events
52
- * Allows custom logic at different points in the step lifecycle
53
- */
54
- hooks?: StepLifecycleHooks;
55
- /**
56
- * Permission configuration for step access control
57
- * Defines who can view, edit, or complete this step
58
- */
59
- permissions?: StepPermissions;
60
48
  /**
61
49
  * Custom renderer for the step
62
50
  * Allows complete customization of step presentation
63
51
  */
64
52
  renderer?: CustomStepRenderer;
65
53
  /**
66
- * Dynamic step configuration
67
- * Enables conditional step behavior based on previous step data
54
+ * Callback function that executes after successful validation and before moving to next step
55
+ * Provides clean helper methods for modifying workflow data and pre-filling subsequent steps
56
+ *
57
+ * @param stepData - The validated data from the current step
58
+ * @param helper - Helper object with methods to modify workflow data cleanly
59
+ * @param context - Full workflow context for reference
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * onAfterValidation: async (stepData, helper, context) => {
64
+ * // API call based on current step data
65
+ * const companyInfo = await fetchCompanyBySiren(stepData.siren);
66
+ *
67
+ * // Pre-fill next step with clean helper methods
68
+ * helper.setNextStepFields({
69
+ * companyName: companyInfo.name,
70
+ * address: companyInfo.address,
71
+ * industry: companyInfo.sector
72
+ * });
73
+ *
74
+ * // Or set data for a specific step
75
+ * helper.setStepFields('company-details', {
76
+ * legalForm: companyInfo.legalForm,
77
+ * foundedYear: companyInfo.creation_date
78
+ * });
79
+ * }
80
+ * ```
68
81
  */
69
- dynamicConfig?: DynamicStepConfig;
82
+ onAfterValidation?: (stepData: Record<string, any>, helper: StepDataHelper, context: WorkflowContext) => void | Promise<void>;
70
83
  }
71
84
  /**
72
85
  * Configuration options for workflow behavior and features
@@ -77,12 +90,6 @@ interface StepDefinition {
77
90
  * @interface WorkflowOptions
78
91
  */
79
92
  interface WorkflowOptions {
80
- /** Navigation behavior configuration */
81
- navigation?: NavigationConfig;
82
- /** Data persistence settings */
83
- persistence?: PersistenceConfig;
84
- /** Workflow completion handling */
85
- completion?: CompletionConfig;
86
93
  /** Analytics and tracking configuration */
87
94
  analytics?: WorkflowAnalytics;
88
95
  }
@@ -128,9 +135,6 @@ declare class flow {
128
135
  private workflowName;
129
136
  private workflowDescription?;
130
137
  private steps;
131
- private navigation;
132
- private persistence?;
133
- private completion?;
134
138
  private analytics?;
135
139
  private plugins;
136
140
  private idGenerator;
@@ -166,7 +170,7 @@ declare class flow {
166
170
  *
167
171
  * This internal method handles the conversion from the user-friendly
168
172
  * StepDefinition interface to the internal StepConfig structure,
169
- * including ID generation and form configuration processing.
173
+ * including ID generation, form configuration processing, and validation setup.
170
174
  *
171
175
  * @private
172
176
  * @param stepDef - The step definition to convert
@@ -209,31 +213,6 @@ declare class flow {
209
213
  * ```
210
214
  */
211
215
  addStep(stepDefinitions: StepDefinition[]): this;
212
- /**
213
- * Add a dynamic step using StepDefinition with dynamicConfig
214
- *
215
- * Dynamic steps can change their behavior, visibility, or configuration
216
- * based on data from previous steps. This method is a convenience wrapper
217
- * around addStep() with enhanced type safety for dynamic configurations.
218
- *
219
- * @param stepDefinition - Step definition with required dynamicConfig
220
- * @returns The flow instance for method chaining
221
- *
222
- * @example
223
- * ```typescript
224
- * workflow.addDynamicStep({
225
- * title: 'Conditional Step',
226
- * formConfig: conditionalForm,
227
- * dynamicConfig: {
228
- * condition: (data) => data.userType === 'premium',
229
- * generator: (data) => generatePremiumForm(data)
230
- * }
231
- * });
232
- * ```
233
- */
234
- addDynamicStep(stepDefinition: StepDefinition & {
235
- dynamicConfig: DynamicStepConfig;
236
- }): this;
237
216
  /**
238
217
  * Universal configuration method for all workflow options
239
218
  *
@@ -429,20 +408,12 @@ declare class flow {
429
408
  * ```
430
409
  */
431
410
  getStats(): {
432
- /** Total number of steps in the workflow */
433
411
  totalSteps: number;
434
- /** Number of dynamic steps */
435
- dynamicSteps: number;
436
- /** Number of installed plugins */
437
- pluginsInstalled: number;
438
- /** Estimated total number of form fields across all steps */
439
- estimatedFields: number;
440
- /** Whether persistence is configured */
441
- hasPersistence: boolean;
442
- /** Whether analytics is configured */
412
+ totalFields: number;
413
+ averageFieldsPerStep: number;
414
+ maxFieldsInStep: number;
415
+ minFieldsInStep: number;
443
416
  hasAnalytics: boolean;
444
- /** Whether back navigation is allowed */
445
- allowBackNavigation: boolean;
446
417
  };
447
418
  /**
448
419
  * Build the final workflow configuration
@@ -549,14 +520,9 @@ interface WorkflowState {
549
520
  currentStepIndex: number;
550
521
  allData: Record<string, any>;
551
522
  stepData: Record<string, any>;
552
- errors: Record<string, ValidationError[]>;
553
- touched: Set<string>;
554
- isValidating: Set<string>;
555
523
  visitedSteps: Set<string>;
556
524
  isSubmitting: boolean;
557
525
  isTransitioning: boolean;
558
- persistedData?: any;
559
- resolvedSteps: StepConfig[];
560
526
  }
561
527
  interface WorkflowContextValue {
562
528
  workflowState: WorkflowState;
@@ -570,27 +536,22 @@ interface WorkflowContextValue {
570
536
  skipStep: () => Promise<boolean>;
571
537
  setValue: (fieldId: string, value: any) => void;
572
538
  setStepData: (data: Record<string, any>) => void;
573
- validateCurrentStep: () => Promise<ValidationResult>;
574
539
  submitWorkflow: () => Promise<void>;
575
540
  resetWorkflow: () => void;
576
- saveDraft: () => Promise<void>;
577
- loadDraft: () => Promise<void>;
578
- clearDraft: () => Promise<void>;
579
541
  }
580
542
  interface WorkflowProviderProps {
581
- children: react__default.ReactNode;
543
+ children: React.ReactNode;
582
544
  workflowConfig: WorkflowConfig;
583
545
  defaultValues?: Record<string, any>;
584
546
  onStepChange?: (fromStep: number, toStep: number, context: WorkflowContext) => void;
585
547
  onWorkflowComplete?: (data: Record<string, any>) => void | Promise<void>;
586
548
  className?: string;
587
- user?: any;
588
549
  }
589
- declare function WorkflowProvider({ children, workflowConfig, defaultValues, onStepChange, onWorkflowComplete, className, user, }: WorkflowProviderProps): react_jsx_runtime.JSX.Element;
550
+ declare function WorkflowProvider({ children, workflowConfig, defaultValues, onStepChange, onWorkflowComplete, className, }: WorkflowProviderProps): react_jsx_runtime.JSX.Element;
590
551
  declare function useWorkflowContext(): WorkflowContextValue;
591
552
 
592
553
  type WorkflowProps = Omit<WorkflowProviderProps, 'children' | 'workflowConfig'> & {
593
- children: react__default.ReactNode;
554
+ children: React.ReactNode;
594
555
  workflowConfig: WorkflowConfig | flow;
595
556
  };
596
557
  /**
@@ -607,34 +568,16 @@ declare function Workflow({ children, workflowConfig, ...props }: WorkflowProps)
607
568
  */
608
569
  declare function WorkflowBody(): react_jsx_runtime.JSX.Element | null;
609
570
 
610
- interface WorkflowNextButtonProps {
611
- className?: string;
612
- children?: React.ReactNode | RendererChildrenFunction<WorkflowNextButtonRendererProps>;
613
- renderAs?: 'default' | 'children' | boolean;
614
- }
615
- declare function WorkflowNextButton({ className, children, renderAs }: WorkflowNextButtonProps): react.ReactNode;
571
+ declare function WorkflowNextButton({ className, ...props }: ComponentRendererBaseProps<WorkflowNextButtonRendererProps>): react_jsx_runtime.JSX.Element;
616
572
 
617
- interface WorkflowPreviousButtonProps {
618
- className?: string;
619
- children?: React.ReactNode | RendererChildrenFunction<WorkflowPreviousButtonRendererProps>;
620
- renderAs?: 'default' | 'children' | boolean;
621
- }
622
- declare function WorkflowPreviousButton({ className, children, renderAs, }: WorkflowPreviousButtonProps): react.ReactNode;
573
+ declare function WorkflowPreviousButton({ className, ...props }: ComponentRendererBaseProps<WorkflowPreviousButtonRendererProps>): react_jsx_runtime.JSX.Element;
623
574
 
624
- interface WorkflowSkipButtonProps {
625
- className?: string;
626
- children?: React.ReactNode | RendererChildrenFunction<WorkflowSkipButtonRendererProps>;
627
- renderAs?: 'default' | 'children' | boolean;
628
- }
629
- declare function WorkflowSkipButton({ className, children, renderAs }: WorkflowSkipButtonProps): react.ReactNode;
575
+ declare function WorkflowSkipButton({ className, ...props }: ComponentRendererBaseProps<WorkflowSkipButtonRendererProps>): react_jsx_runtime.JSX.Element;
630
576
 
631
- interface WorkflowStepperProps {
577
+ interface WorkflowStepperProps extends ComponentRendererBaseProps<WorkflowStepperRendererProps> {
632
578
  onStepClick?: (stepIndex: number) => void;
633
- className?: string;
634
- children?: React.ReactNode | RendererChildrenFunction<WorkflowStepperRendererProps>;
635
- renderAs?: 'default' | 'children' | boolean;
636
579
  }
637
- declare function WorkflowStepper({ onStepClick, className, children, renderAs, }: WorkflowStepperProps): react.ReactNode;
580
+ declare function WorkflowStepper({ onStepClick, className, ...props }: WorkflowStepperProps): react_jsx_runtime.JSX.Element;
638
581
 
639
582
  interface LicensePayload {
640
583
  plan: 'ARCHITECT' | 'FOUNDRY';
@@ -704,4 +647,4 @@ declare class RilayLicenseManager {
704
647
  }>;
705
648
  }
706
649
 
707
- export { type LicensePayload, type LicensePlan, type LicenseResult, RilayLicenseManager, type StepDefinition, Workflow, WorkflowBody, type WorkflowContextValue, WorkflowNextButton, type WorkflowNextButtonProps, WorkflowPreviousButton, type WorkflowPreviousButtonProps, WorkflowProvider, type WorkflowProviderProps, WorkflowSkipButton, type WorkflowSkipButtonProps, WorkflowStepper, type WorkflowStepperProps, createFlow, flow, useWorkflowContext };
650
+ export { type LicensePayload, type LicensePlan, type LicenseResult, RilayLicenseManager, type StepDefinition, Workflow, WorkflowBody, type WorkflowContextValue, WorkflowNextButton, WorkflowPreviousButton, WorkflowProvider, WorkflowSkipButton, WorkflowStepper, createFlow, flow, useWorkflowContext };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var core=require('@rilaykit/core'),forms=require('@rilaykit/forms'),H=require('@noble/ed25519'),react=require('react'),jsxRuntime=require('react/jsx-runtime');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var H__namespace=/*#__PURE__*/_interopNamespace(H);var Q=1751361139160,j="8fdb6a454550326d331c3b3d1d1f8c707a371bdb6c7ea72a0a1e4ea6f1822620",f=class f{static async setLicenseKey(e){f.licenseKey=e||"",f.licenseKey?f.licenseResult=await f.validateLicense():f.licenseResult={valid:false,error:"MISSING"},f.isInitialized=true;}static async validateLicense(){if(!f.licenseKey)return {valid:false,error:"MISSING"};try{if(!f.licenseKey.startsWith("ril_"))return {valid:!1,error:"FORMAT_INVALID"};let e=f.licenseKey.slice(4),o=f.base64ToString(e).split(".");if(o.length!==3)return {valid:!1,error:"FORMAT_INVALID"};let[a,d,p]=o,n=`${a}.${d}`,c=new TextEncoder().encode(n),w=p.match(/.{2}/g);if(!w)return {valid:!1,error:"INVALID"};let k=new Uint8Array(w.map(u=>Number.parseInt(u,16))),h=f.hexToBytes(j);if(!await H__namespace.verify(k,c,h))return {valid:!1,error:"SIGNATURE_INVALID"};let g=f.base64ToString(d.replace(/-/g,"+").replace(/_/g,"/")),m=JSON.parse(g),y=Math.floor(Date.now()/1e3);return m.e<y?{valid:!1,error:"EXPIRED",data:f.decompressPayload(m)}:Q>m.e*1e3?{valid:!1,error:"EXPIRED",data:f.decompressPayload(m)}:m.p===void 0||!m.c||!m.i||!m.e||!m.t?{valid:!1,error:"INVALID"}:{valid:!0,data:f.decompressPayload(m)}}catch{return {valid:false,error:"INVALID"}}}static decompressPayload(e){return {plan:{0:"ARCHITECT",1:"FOUNDRY"}[e.p]||"ARCHITECT",company:e.c,customerId:e.i.toString(),expiry:e.e*1e3,iat:e.t*1e3}}static hexToBytes(e){let r=new Uint8Array(e.length/2);for(let o=0;o<e.length;o+=2)r[o/2]=Number.parseInt(e.substring(o,o+2),16);return r}static base64ToString(e){if(typeof atob<"u")return atob(e);if(typeof Buffer<"u")return Buffer.from(e,"base64").toString();let r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",o="",a=0,d=e.replace(/[^A-Za-z0-9+/]/g,"");for(;a<d.length;){let p=r.indexOf(d.charAt(a++)),n=r.indexOf(d.charAt(a++)),c=r.indexOf(d.charAt(a++)),w=r.indexOf(d.charAt(a++)),k=p<<18|n<<12|c<<6|w;o+=String.fromCharCode(k>>16&255),c!==64&&(o+=String.fromCharCode(k>>8&255)),w!==64&&(o+=String.fromCharCode(k&255));}return o}static getLicenseResult(){return f.isInitialized?f.licenseResult?f.licenseResult:{valid:false,error:"MISSING"}:{valid:false,error:"MISSING"}}static shouldDisplayWatermark(){return typeof window>"u"?false:!f.getLicenseResult().valid}static getWatermarkMessage(){let e=f.getLicenseResult();return {MISSING:"Rilay Workflow - For Trial Use Only",EXPIRED:"Rilay Workflow - License Expired",INVALID:"Rilay Workflow - Invalid License",FORMAT_INVALID:"Rilay Workflow - Invalid License Format",SIGNATURE_INVALID:"Rilay Workflow - Invalid License Signature"}[e.error||"MISSING"]||""}static logLicenseStatus(){let e=f.getLicenseResult();if(e.valid)return;let o={MISSING:"\u{1F527} Rilay Workflow - Trial Mode. Purchase a license at https://rilay.io/pricing",EXPIRED:"\u26A0\uFE0F Rilay Workflow - License Expired. Please renew your license.",INVALID:"\u274C Rilay Workflow - Invalid License. Please check your license key.",FORMAT_INVALID:"\u274C Rilay Workflow - Invalid License Format. Please check your license key.",SIGNATURE_INVALID:"\u274C Rilay Workflow - Invalid License Signature. Please check your license key."}[e.error||"MISSING"];console.warn(`%c${o}`,"color: #f59e0b; font-weight: bold;");}static async getLicenseInfo(){let e=f.getLicenseResult();return !e.valid||!e.data?{}:{plan:e.data.plan,company:e.data.company,expiryDate:new Date(e.data.expiry).toLocaleDateString()}}};f.licenseKey="",f.licenseResult=null,f.isInitialized=false;var D=f;var x=class i{constructor(e,r,o,a){this.steps=[];this.navigation={allowBackNavigation:true};this.plugins=[];this.idGenerator=new core.IdGenerator;this.config=e,this.workflowId=r,this.workflowName=o,this.workflowDescription=a,D.logLicenseStatus();}static create(e,r,o,a){return new i(e,r,o,a)}createStepFromDefinition(e){return {id:e.id||this.idGenerator.next("step"),title:e.title,description:e.description,formConfig:e.formConfig instanceof forms.form?e.formConfig.build():e.formConfig,allowSkip:e.allowSkip||false,requiredToComplete:e.requiredToComplete!==false,hooks:e.hooks,permissions:e.permissions,isDynamic:!!e.dynamicConfig,dynamicConfig:e.dynamicConfig,renderer:e.renderer}}addStep(e){let r=core.normalizeToArray(e);for(let o of r){let a=this.createStepFromDefinition(o);this.steps.push(a);}return this}addDynamicStep(e){return this.addStep(e)}configure(e){return e.navigation&&(this.navigation=core.configureObject(this.navigation,e.navigation)),e.persistence&&(this.persistence=e.persistence),e.completion&&(this.completion=e.completion),e.analytics&&(this.analytics=e.analytics),this}use(e){this.validatePluginDependencies(e),this.plugins.push(e);try{e.install(this);}catch(r){throw new Error(`Failed to install plugin "${e.name}": ${r instanceof Error?r.message:String(r)}`)}return this}validatePluginDependencies(e){if(!e.dependencies)return;let r=e.dependencies.filter(o=>!this.plugins.some(a=>a.name===o));if(r.length>0)throw new Error(`Plugin "${e.name}" requires missing dependencies: ${r.join(", ")}`)}removePlugin(e){return this.plugins=this.plugins.filter(r=>r.name!==e),this}updateStep(e,r){let o=this.steps.findIndex(a=>a.id===e);if(o===-1)throw new Error(`Step with ID "${e}" not found`);return this.steps[o]={...this.steps[o],...r},this}removeStep(e){return this.steps=this.steps.filter(r=>r.id!==e),this}getStep(e){return this.steps.find(r=>r.id===e)}getSteps(){return [...this.steps]}clearSteps(){return this.steps=[],this.idGenerator.reset(),this}clone(e,r){let o=new i(this.config,e||`${this.workflowId}-clone`,r||`${this.workflowName} (Copy)`,this.workflowDescription);return o.steps=core.deepClone(this.steps),o.navigation=core.deepClone(this.navigation),o.persistence=this.persistence?core.deepClone(this.persistence):void 0,o.completion=this.completion?core.deepClone(this.completion):void 0,o.analytics=this.analytics?core.deepClone(this.analytics):void 0,o.plugins=[...this.plugins],o}validate(){let e=new core.ValidationErrorBuilder;e.addIf(this.steps.length===0,"NO_STEPS","Workflow must have at least one step");let r=this.steps.map(o=>o.id);try{core.ensureUnique(r,"step");}catch(o){e.add("DUPLICATE_STEP_IDS",o instanceof Error?o.message:String(o));}for(let o of this.plugins)if(o.dependencies){let a=o.dependencies.filter(d=>!this.plugins.some(p=>p.name===d));e.addIf(a.length>0,"MISSING_PLUGIN_DEPENDENCIES",`Plugin "${o.name}" requires missing dependencies: ${a.join(", ")}`);}return e.build().map(o=>o.message)}getStats(){return {totalSteps:this.steps.length,dynamicSteps:this.steps.filter(e=>e.isDynamic).length,pluginsInstalled:this.plugins.length,estimatedFields:this.steps.reduce((e,r)=>e+r.formConfig.allFields.length,0),hasPersistence:!!this.persistence,hasAnalytics:!!this.analytics,allowBackNavigation:this.navigation.allowBackNavigation!==false}}build(){let e=this.validate();if(e.length>0)throw new Error(`Workflow validation failed: ${e.join(", ")}`);return {id:this.workflowId,name:this.workflowName,description:this.workflowDescription,steps:[...this.steps],navigation:this.navigation,persistence:this.persistence,completion:this.completion,analytics:this.analytics,plugins:[...this.plugins],renderConfig:this.config.getWorkflowRenderConfig()}}toJSON(){return {id:this.workflowId,name:this.workflowName,description:this.workflowDescription,steps:this.steps,navigation:this.navigation,persistence:this.persistence,completion:this.completion,analytics:this.analytics,plugins:this.plugins.map(e=>({name:e.name,version:e.version,dependencies:e.dependencies}))}}fromJSON(e){return e.id&&(this.workflowId=e.id),e.name&&(this.workflowName=e.name),e.description&&(this.workflowDescription=e.description),e.steps&&(this.steps=e.steps),e.navigation&&(this.navigation=e.navigation),e.persistence&&(this.persistence=e.persistence),e.completion&&(this.completion=e.completion),e.analytics&&(this.analytics=e.analytics),this}};function ae(i,e,r,o){return x.create(i,e,r,o)}core.ril.prototype.flow=function(i,e,r){return x.create(this,i,e,r)};function fe(i,e){switch(e.type){case "SET_CURRENT_STEP":return {...i,currentStepIndex:e.stepIndex,stepData:i.allData[i.resolvedSteps[e.stepIndex]?.id]||{}};case "SET_STEP_DATA":{let r=i.resolvedSteps[i.currentStepIndex]?.id;return {...i,stepData:e.data,allData:{...i.allData,[r]:e.data}}}case "SET_ALL_DATA":return {...i,allData:e.data};case "SET_FIELD_VALUE":{let r=i.resolvedSteps[i.currentStepIndex]?.id,o={...i.stepData,[e.fieldId]:e.value};return {...i,stepData:o,allData:{...i.allData,[r]:o}}}case "SET_ERROR":return {...i,errors:{...i.errors,[e.fieldId]:e.errors}};case "CLEAR_ERROR":{let r={...i.errors};return delete r[e.fieldId],{...i,errors:r}}case "MARK_TOUCHED":return {...i,touched:new Set([...i.touched,e.fieldId])};case "SET_VALIDATING":{let r=new Set(i.isValidating);return e.isValidating?r.add(e.fieldId):r.delete(e.fieldId),{...i,isValidating:r}}case "SET_SUBMITTING":return {...i,isSubmitting:e.isSubmitting};case "SET_TRANSITIONING":return {...i,isTransitioning:e.isTransitioning};case "MARK_STEP_VISITED":return {...i,visitedSteps:new Set([...i.visitedSteps,i.resolvedSteps[e.stepIndex]?.id])};case "SET_PERSISTED_DATA":return {...i,persistedData:e.data};case "SET_RESOLVED_STEPS":return {...i,resolvedSteps:e.steps};case "RESET_WORKFLOW":return {currentStepIndex:0,allData:{},stepData:{},errors:{},touched:new Set,isValidating:new Set,visitedSteps:new Set,isSubmitting:false,isTransitioning:false,resolvedSteps:i.resolvedSteps};default:return i}}var J=react.createContext(null);function F({children:i,workflowConfig:e,defaultValues:r={},onStepChange:o,onWorkflowComplete:a,className:d,user:p}){let[n,c]=react.useReducer(fe,{currentStepIndex:0,allData:r,stepData:{},errors:{},touched:new Set,isValidating:new Set,visitedSteps:new Set,isSubmitting:false,isTransitioning:false,resolvedSteps:e.steps}),w=react.useRef(null),k=react.useRef(Date.now()),h=react.useRef(new Map),E=react.useRef(false),g=react.useRef(null),m=react.useRef(o),y=react.useRef(a);m.current=o,y.current=a;let t=react.useMemo(()=>e,[e]),u=react.useMemo(()=>({workflowId:t.id,currentStepIndex:n.currentStepIndex,totalSteps:n.resolvedSteps.length,allData:n.allData,stepData:n.stepData,isFirstStep:n.currentStepIndex===0,isLastStep:n.currentStepIndex===n.resolvedSteps.length-1,visitedSteps:n.visitedSteps,user:p}),[t.id,n.currentStepIndex,n.resolvedSteps.length,n.allData,n.stepData,n.visitedSteps,p]);react.useEffect(()=>{(async()=>{let l=[];for(let S of t.steps)if(S.isDynamic&&S.dynamicConfig)try{let _=await S.dynamicConfig.resolver(n.allData,u);l.push(..._);}catch(_){console.error(`Failed to resolve dynamic step "${S.id}":`,_),l.push({...S,isDynamic:false});}else l.push(S);c({type:"SET_RESOLVED_STEPS",steps:l});})();},[t.steps,n.allData,u]),react.useEffect(()=>{t.analytics?.onWorkflowStart&&!E.current&&(E.current=true,t.analytics.onWorkflowStart(t.id,u));},[t.id,t.analytics,u]),react.useEffect(()=>{let s=n.resolvedSteps[n.currentStepIndex];if(s&&g.current!==s.id){if(g.current&&t.analytics?.onStepComplete){let l=h.current.get(g.current);l&&t.analytics.onStepComplete(g.current,Date.now()-l,n.stepData,u);}g.current=s.id,h.current.set(s.id,Date.now()),t.analytics?.onStepStart&&t.analytics.onStepStart(s.id,Date.now(),u);}},[n.currentStepIndex,n.resolvedSteps,t.analytics,u]);let C=react.useCallback(async()=>{if(t.persistence)try{let s={workflowId:t.id,currentStepIndex:n.currentStepIndex,allData:n.allData,metadata:{timestamp:Date.now(),version:"1.0.0",userId:p?.id,sessionId:crypto.randomUUID()}},l=t.persistence.key||`workflow-${t.id}`;await t.persistence.adapter.save(l,s),t.persistence.onSave&&await t.persistence.onSave(s);}catch(s){console.error("Failed to save workflow draft:",s),t.persistence.onError&&await t.persistence.onError(s,"save");}},[t,n.currentStepIndex,n.allData,p]),V=react.useCallback(async()=>{if(t.persistence)try{let s=t.persistence.key||`workflow-${t.id}`,l=await t.persistence.adapter.load(s);l&&l.workflowId===t.id&&(c({type:"SET_ALL_DATA",data:l.allData}),c({type:"SET_CURRENT_STEP",stepIndex:l.currentStepIndex}),c({type:"SET_PERSISTED_DATA",data:l}),t.persistence.onLoad&&await t.persistence.onLoad(l));}catch(s){console.error("Failed to load workflow draft:",s),t.persistence.onError&&await t.persistence.onError(s,"load");}},[t]),A=react.useCallback(async()=>{if(t.persistence)try{let s=t.persistence.key||`workflow-${t.id}`;await t.persistence.adapter.remove(s);}catch(s){console.error("Failed to clear workflow draft:",s),t.persistence.onError&&await t.persistence.onError(s,"remove");}},[t]);react.useEffect(()=>{t.persistence&&(async()=>{try{let l=t.persistence.key||`workflow-${t.id}`,S=await t.persistence.adapter.load(l);S&&S.workflowId===t.id&&(c({type:"SET_ALL_DATA",data:S.allData}),c({type:"SET_CURRENT_STEP",stepIndex:S.currentStepIndex}),c({type:"SET_PERSISTED_DATA",data:S}),t.persistence.onLoad&&await t.persistence.onLoad(S),console.log("Workflow data loaded from persistence:",S));}catch(l){console.error("Failed to load workflow draft on mount:",l),t.persistence.onError&&await t.persistence.onError(l,"load");}})();},[t.id]),react.useEffect(()=>{if(t.persistence?.saveOnStepChange)return w.current&&clearTimeout(w.current),w.current=setTimeout(()=>{C();},t.persistence.debounceMs||1e3),()=>{w.current&&clearTimeout(w.current);}},[n.allData,C,t.persistence]);let R=react.useMemo(()=>n.resolvedSteps[n.currentStepIndex],[n.resolvedSteps,n.currentStepIndex]),O=react.useMemo(()=>R?.formConfig,[R]),P=react.useCallback(async s=>{if(s<0||s>=n.resolvedSteps.length)return false;let l=n.resolvedSteps[s];if(l.permissions)try{if(!(l.permissions.customGuard?await l.permissions.customGuard(p,u):!0))return console.warn(`Access denied to step "${l.id}"`),!1}catch(S){return console.error(`Permission check failed for step "${l.id}":`,S),false}if(l.hooks?.onBeforeEnter)try{await l.hooks.onBeforeEnter(n.stepData,n.allData,u);}catch(S){return console.error(`onBeforeEnter hook failed for step "${l.id}":`,S),t.analytics?.onError&&t.analytics.onError(S,u),false}c({type:"SET_TRANSITIONING",isTransitioning:true});try{return m.current&&m.current(n.currentStepIndex,s,u),c({type:"SET_CURRENT_STEP",stepIndex:s}),c({type:"MARK_STEP_VISITED",stepIndex:s}),!0}catch(S){return console.error("Step transition failed:",S),t.analytics?.onError&&t.analytics.onError(S,u),false}finally{c({type:"SET_TRANSITIONING",isTransitioning:false});}},[n.resolvedSteps,n.currentStepIndex,n.stepData,n.allData,p,u,t.analytics]),B=react.useCallback((s,l)=>{c({type:"SET_FIELD_VALUE",fieldId:s,value:l});},[]),U=react.useCallback(s=>{c({type:"SET_STEP_DATA",data:s});},[]),M=react.useCallback(async()=>R?{isValid:true,errors:[]}:{isValid:true,errors:[]},[R]),L=react.useCallback(async()=>P(n.currentStepIndex+1),[P,n.currentStepIndex]),G=react.useCallback(async()=>t.navigation?.allowBackNavigation?P(n.currentStepIndex-1):false,[t.navigation,n.currentStepIndex,P]),$=react.useCallback(async()=>!R?.allowSkip||!t.navigation?.allowStepSkipping?false:(t.analytics?.onStepSkip&&t.analytics.onStepSkip(R.id,"user_skip",u),P(n.currentStepIndex+1)),[R,t.navigation,t.analytics,u,P,n.currentStepIndex]),K=react.useCallback(async()=>{c({type:"SET_SUBMITTING",isSubmitting:true});try{if(y.current&&await y.current(n.allData),await A(),t.analytics?.onWorkflowComplete){let s=Date.now()-k.current;t.analytics.onWorkflowComplete(t.id,s,n.allData);}}catch(s){throw console.error("Workflow submission failed:",s),t.analytics?.onError&&t.analytics.onError(s,u),s}finally{c({type:"SET_SUBMITTING",isSubmitting:false});}},[n.allData,y,A,t.analytics,u]),z=react.useCallback(()=>{c({type:"RESET_WORKFLOW"});},[]),Y=react.useMemo(()=>({workflowState:n,workflowConfig:t,currentStep:R,context:u,formConfig:O,goToStep:P,goNext:L,goPrevious:G,skipStep:$,setValue:B,setStepData:U,validateCurrentStep:M,submitWorkflow:K,resetWorkflow:z,saveDraft:C,loadDraft:V,clearDraft:A}),[n,t,R,u,O,P,L,G,$,B,U,M,K,z,C,V,A]),Z=react.useCallback(async()=>{await L();},[L]);return jsxRuntime.jsx(J.Provider,{value:Y,children:jsxRuntime.jsx(forms.FormProvider,{formConfig:R?.formConfig,defaultValues:n?.allData[R?.id]||{},onFieldChange:B,"data-workflow-id":t.id,className:d,onSubmit:Z,children:i})})}function I(){let i=react.useContext(J);if(!i)throw new Error("useWorkflowContext must be used within a WorkflowProvider");return i}function we({children:i,workflowConfig:e,...r}){let[o,a]=react.useState(false),d=D.shouldDisplayWatermark(),p=D.getWatermarkMessage(),n=e instanceof x?e.build():e;return react.useEffect(()=>{a(true);},[]),jsxRuntime.jsxs("div",{style:{position:"relative"},children:[jsxRuntime.jsx(F,{...r,workflowConfig:n,children:i}),o&&d&&jsxRuntime.jsx("div",{style:{position:"absolute",top:"10px",right:"10px",background:"rgba(0, 0, 0, 0.8)",color:"white",padding:"4px 8px",borderRadius:"4px",fontSize:"12px",fontFamily:"monospace",zIndex:1e3,pointerEvents:"none",opacity:.7},children:p})]})}function ke(){let{currentStep:i}=I();if(!i)return null;let{formConfig:e,renderer:r}=i;return e?r?r(i):jsxRuntime.jsx(forms.FormBody,{}):null}function Re({className:i,children:e,renderAs:r}){let{context:o,submitWorkflow:a,workflowState:d,workflowConfig:p,currentStep:n}=I(),{submit:c,formState:w}=forms.useFormContext(),k=!d.isTransitioning&&!d.isSubmitting,h=async C=>{C?.preventDefault(),k&&await c(C);},E=async C=>{C?.preventDefault(),k&&await a();},g={isLastStep:o.isLastStep,canGoNext:k,isSubmitting:d.isSubmitting,onNext:h,onSubmit:E,className:i,currentStep:n,stepData:w.values||{},allData:o.allData,context:o};if(r==="children"||r===true){if(typeof e!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');return e(g)}let y=p.renderConfig?.nextButtonRenderer;if(!y)throw new Error(`No nextButtonRenderer configured for workflow "${p.id}". Please configure a nextButtonRenderer using config.setWorkflowNextButtonRenderer() or config.setWorkflowRenderConfig().`);let t=core.resolveRendererChildren(e,g),u={...g,children:t};return y(u)}function Ce({className:i,children:e,renderAs:r}){let{context:o,goPrevious:a,workflowState:d,workflowConfig:p,currentStep:n}=I(),{formState:c}=forms.useFormContext(),w=o.currentStepIndex>0&&p.navigation?.allowBackNavigation!==false&&!d.isTransitioning&&!d.isSubmitting;if(p.navigation?.allowBackNavigation===false)throw new Error(`WorkflowPreviousButton is rendered but allowBackNavigation is disabled in workflow "${p.id}". Either enable back navigation or remove the WorkflowPreviousButton component.`);let h={canGoPrevious:w,onPrevious:async t=>{t?.preventDefault(),w&&await a();},className:i,currentStep:n,stepData:c.values||{},allData:o.allData,context:o};if(r==="children"||r===true){if(typeof e!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');return e(h)}let g=p.renderConfig?.previousButtonRenderer;if(!g)throw new Error(`No previousButtonRenderer configured for workflow "${p.id}". Please configure a previousButtonRenderer using config.setWorkflowPreviousButtonRenderer() or config.setWorkflowRenderConfig().`);let m=core.resolveRendererChildren(e,h),y={...h,children:m};return g(y)}function xe({className:i,children:e,renderAs:r}){let{currentStep:o,skipStep:a,workflowState:d,workflowConfig:p,context:n}=I(),{formState:c}=forms.useFormContext(),w=!!o?.allowSkip&&p.navigation?.allowStepSkipping!==false&&!d.isTransitioning&&!d.isSubmitting,h={canSkip:w,onSkip:async t=>{t?.preventDefault(),w&&await a();},className:i,currentStep:o,stepData:c.values||{},allData:n.allData,context:n};if(r==="children"||r===true){if(typeof e!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');return e(h)}let g=p.renderConfig?.skipButtonRenderer;if(!g)throw new Error(`No skipButtonRenderer configured for workflow "${p.id}". Please configure a skipButtonRenderer using config.setWorkflowSkipButtonRenderer() or config.setWorkflowRenderConfig().`);let m=core.resolveRendererChildren(e,h),y={...h,children:m};return g(y)}function We({onStepClick:i,className:e,children:r,renderAs:o}){let{workflowConfig:a,workflowState:d,goToStep:p}=I(),n=E=>{i?i(E):p(E);},c={steps:d.resolvedSteps,currentStepIndex:d.currentStepIndex,visitedSteps:d.visitedSteps,onStepClick:n,className:e};if(o==="children"||o===true){if(typeof r!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');return r(c)}let k=a.renderConfig?.stepperRenderer;if(!k)throw new Error(`No stepperRenderer configured for workflow "${a.id}". Please configure a stepperRenderer using config.setStepperRenderer() or config.setWorkflowRenderConfig().`);return k(c)}
2
- Object.defineProperty(exports,"createZodValidator",{enumerable:true,get:function(){return core.createZodValidator}});Object.defineProperty(exports,"ril",{enumerable:true,get:function(){return core.ril}});Object.defineProperty(exports,"form",{enumerable:true,get:function(){return forms.form}});exports.RilayLicenseManager=D;exports.Workflow=we;exports.WorkflowBody=ke;exports.WorkflowNextButton=Re;exports.WorkflowPreviousButton=Ce;exports.WorkflowProvider=F;exports.WorkflowSkipButton=xe;exports.WorkflowStepper=We;exports.createFlow=ae;exports.flow=x;exports.useWorkflowContext=I;
1
+ 'use strict';var core=require('@rilaykit/core'),forms=require('@rilaykit/forms'),O=require('@noble/ed25519'),react=require('react'),jsxRuntime=require('react/jsx-runtime');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var O__namespace=/*#__PURE__*/_interopNamespace(O);var X=1751361139160,Y="8fdb6a454550326d331c3b3d1d1f8c707a371bdb6c7ea72a0a1e4ea6f1822620",p=class p{static async setLicenseKey(e){p.licenseKey=e||"",p.licenseKey?p.licenseResult=await p.validateLicense():p.licenseResult={valid:false,error:"MISSING"},p.isInitialized=true;}static async validateLicense(){if(!p.licenseKey)return {valid:false,error:"MISSING"};try{if(!p.licenseKey.startsWith("ril_"))return {valid:!1,error:"FORMAT_INVALID"};let e=p.licenseKey.slice(4),r=p.base64ToString(e).split(".");if(r.length!==3)return {valid:!1,error:"FORMAT_INVALID"};let[s,f,n]=r,l=`${s}.${f}`,u=new TextEncoder().encode(l),w=n.match(/.{2}/g);if(!w)return {valid:!1,error:"INVALID"};let m=new Uint8Array(w.map(E=>Number.parseInt(E,16))),g=p.hexToBytes(Y);if(!await O__namespace.verify(m,u,g))return {valid:!1,error:"SIGNATURE_INVALID"};let x=p.base64ToString(f.replace(/-/g,"+").replace(/_/g,"/")),o=JSON.parse(x),d=Math.floor(Date.now()/1e3);return o.e<d?{valid:!1,error:"EXPIRED",data:p.decompressPayload(o)}:X>o.e*1e3?{valid:!1,error:"EXPIRED",data:p.decompressPayload(o)}:o.p===void 0||!o.c||!o.i||!o.e||!o.t?{valid:!1,error:"INVALID"}:{valid:!0,data:p.decompressPayload(o)}}catch{return {valid:false,error:"INVALID"}}}static decompressPayload(e){return {plan:{0:"ARCHITECT",1:"FOUNDRY"}[e.p]||"ARCHITECT",company:e.c,customerId:e.i.toString(),expiry:e.e*1e3,iat:e.t*1e3}}static hexToBytes(e){let t=new Uint8Array(e.length/2);for(let r=0;r<e.length;r+=2)t[r/2]=Number.parseInt(e.substring(r,r+2),16);return t}static base64ToString(e){if(typeof atob<"u")return atob(e);if(typeof Buffer<"u")return Buffer.from(e,"base64").toString();let t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",r="",s=0,f=e.replace(/[^A-Za-z0-9+/]/g,"");for(;s<f.length;){let n=t.indexOf(f.charAt(s++)),l=t.indexOf(f.charAt(s++)),u=t.indexOf(f.charAt(s++)),w=t.indexOf(f.charAt(s++)),m=n<<18|l<<12|u<<6|w;r+=String.fromCharCode(m>>16&255),u!==64&&(r+=String.fromCharCode(m>>8&255)),w!==64&&(r+=String.fromCharCode(m&255));}return r}static getLicenseResult(){return p.isInitialized?p.licenseResult?p.licenseResult:{valid:false,error:"MISSING"}:{valid:false,error:"MISSING"}}static shouldDisplayWatermark(){return typeof window>"u"?false:!p.getLicenseResult().valid}static getWatermarkMessage(){let e=p.getLicenseResult();return {MISSING:"Rilay Workflow - For Trial Use Only",EXPIRED:"Rilay Workflow - License Expired",INVALID:"Rilay Workflow - Invalid License",FORMAT_INVALID:"Rilay Workflow - Invalid License Format",SIGNATURE_INVALID:"Rilay Workflow - Invalid License Signature"}[e.error||"MISSING"]||""}static logLicenseStatus(){let e=p.getLicenseResult();if(e.valid)return;let r={MISSING:"\u{1F527} Rilay Workflow - Trial Mode. Purchase a license at https://rilay.io/pricing",EXPIRED:"\u26A0\uFE0F Rilay Workflow - License Expired. Please renew your license.",INVALID:"\u274C Rilay Workflow - Invalid License. Please check your license key.",FORMAT_INVALID:"\u274C Rilay Workflow - Invalid License Format. Please check your license key.",SIGNATURE_INVALID:"\u274C Rilay Workflow - Invalid License Signature. Please check your license key."}[e.error||"MISSING"];console.warn(`%c${r}`,"color: #f59e0b; font-weight: bold;");}static async getLicenseInfo(){let e=p.getLicenseResult();return !e.valid||!e.data?{}:{plan:e.data.plan,company:e.data.company,expiryDate:new Date(e.data.expiry).toLocaleDateString()}}};p.licenseKey="",p.licenseResult=null,p.isInitialized=false;var h=p;var I=class i{constructor(e,t,r,s){this.steps=[];this.plugins=[];this.idGenerator=new core.IdGenerator;this.config=e,this.workflowId=t,this.workflowName=r,this.workflowDescription=s,h.logLicenseStatus();}static create(e,t,r,s){return new i(e,t,r,s)}createStepFromDefinition(e){return {id:e.id||this.idGenerator.next("step"),title:e.title,description:e.description,formConfig:e.formConfig instanceof forms.form?e.formConfig.build():e.formConfig,allowSkip:e.allowSkip||false,renderer:e.renderer,onAfterValidation:e.onAfterValidation}}addStep(e){let t=core.normalizeToArray(e);for(let r of t){let s=this.createStepFromDefinition(r);this.steps.push(s);}return this}configure(e){return e.analytics&&(this.analytics=e.analytics),this}use(e){this.validatePluginDependencies(e),this.plugins.push(e);try{e.install(this);}catch(t){throw new Error(`Failed to install plugin "${e.name}": ${t instanceof Error?t.message:String(t)}`)}return this}validatePluginDependencies(e){if(!e.dependencies)return;let t=e.dependencies.filter(r=>!this.plugins.some(s=>s.name===r));if(t.length>0)throw new Error(`Plugin "${e.name}" requires missing dependencies: ${t.join(", ")}`)}removePlugin(e){return this.plugins=this.plugins.filter(t=>t.name!==e),this}updateStep(e,t){let r=this.steps.findIndex(s=>s.id===e);if(r===-1)throw new Error(`Step with ID "${e}" not found`);return this.steps[r]={...this.steps[r],...t},this}removeStep(e){return this.steps=this.steps.filter(t=>t.id!==e),this}getStep(e){return this.steps.find(t=>t.id===e)}getSteps(){return [...this.steps]}clearSteps(){return this.steps=[],this.idGenerator.reset(),this}clone(e,t){let r=new i(this.config,e||`${this.workflowId}-clone`,t||this.workflowName);return r.steps=core.deepClone(this.steps),r.analytics=this.analytics?core.deepClone(this.analytics):void 0,r.plugins=[...this.plugins],r}validate(){let e=[];this.steps.length===0&&e.push("Workflow must have at least one step");let t=this.steps.map(r=>r.id);try{core.ensureUnique(t,"step");}catch(r){e.push(r instanceof Error?r.message:String(r));}for(let r of this.plugins)if(r.dependencies){let s=r.dependencies.filter(f=>!this.plugins.some(n=>n.name===f));s.length>0&&e.push(`Plugin "${r.name}" requires missing dependencies: ${s.join(", ")}`);}return e}getStats(){let e=this.steps.reduce((r,s)=>r+s.formConfig.allFields.length,0),t=this.steps.map(r=>r.formConfig.allFields.length);return {totalSteps:this.steps.length,totalFields:e,averageFieldsPerStep:this.steps.length>0?e/this.steps.length:0,maxFieldsInStep:t.length>0?Math.max(...t):0,minFieldsInStep:t.length>0?Math.min(...t):0,hasAnalytics:!!this.analytics}}build(){let e=this.validate();if(e.length>0)throw new Error(`Workflow validation failed: ${e.join(", ")}`);return {id:this.workflowId,name:this.workflowName,description:this.workflowDescription,steps:this.steps,analytics:this.analytics,plugins:this.plugins,renderConfig:this.config.getWorkflowRenderConfig()}}toJSON(){return {id:this.workflowId,name:this.workflowName,description:this.workflowDescription,steps:this.steps,analytics:this.analytics,plugins:this.plugins.map(e=>({name:e.name,version:e.version}))}}fromJSON(e){return this.workflowId=e.workflowId,this.workflowName=e.workflowName,this.workflowDescription=e.workflowDescription,this.steps=e.steps,this.analytics=e.analytics,this.plugins=e.plugins||[],this}};function re(i,e,t,r){return I.create(i,e,t,r)}core.ril.prototype.flow=function(i,e,t){return I.create(this,i,e,t)};function ae(i,e){switch(e.type){case "SET_CURRENT_STEP":return {...i,currentStepIndex:e.stepIndex};case "SET_STEP_DATA":{let t=e.stepId;return {...i,stepData:e.data,allData:{...i.allData,[t]:e.data}}}case "SET_ALL_DATA":return {...i,allData:e.data};case "SET_FIELD_VALUE":{let t=e.stepId,r={...i.stepData,[e.fieldId]:e.value};return {...i,stepData:r,allData:{...i.allData,[t]:r}}}case "SET_SUBMITTING":return {...i,isSubmitting:e.isSubmitting};case "SET_TRANSITIONING":return {...i,isTransitioning:e.isTransitioning};case "MARK_STEP_VISITED":return {...i,visitedSteps:new Set([...i.visitedSteps,e.stepId])};case "RESET_WORKFLOW":return {currentStepIndex:0,allData:{},stepData:{},visitedSteps:new Set,isSubmitting:false,isTransitioning:false};default:return i}}var $=react.createContext(null);function N({children:i,workflowConfig:e,defaultValues:t={},onStepChange:r,onWorkflowComplete:s,className:f}){let[n,l]=react.useReducer(ae,{currentStepIndex:0,allData:t,stepData:{},visitedSteps:new Set,isSubmitting:false,isTransitioning:false}),u=react.useRef(Date.now()),w=react.useRef(new Map),m=react.useRef(false),g=react.useRef(null),T=react.useRef(r),x=react.useRef(s);T.current=r,x.current=s;let o=react.useMemo(()=>e,[e]),d=react.useMemo(()=>({workflowId:o.id,currentStepIndex:n.currentStepIndex,totalSteps:o.steps.length,allData:n.allData,stepData:n.stepData,isFirstStep:n.currentStepIndex===0,isLastStep:n.currentStepIndex===o.steps.length-1,visitedSteps:n.visitedSteps}),[o.id,n.currentStepIndex,o.steps.length,n.allData,n.stepData,n.visitedSteps]);react.useEffect(()=>{o.analytics?.onWorkflowStart&&!m.current&&(m.current=true,o.analytics.onWorkflowStart(o.id,d));},[o.id,o.analytics,d]),react.useEffect(()=>{let a=o.steps[n.currentStepIndex];if(a&&g.current!==a.id){if(g.current&&o.analytics?.onStepComplete){let c=w.current.get(g.current);c&&o.analytics.onStepComplete(g.current,Date.now()-c,n.stepData,d);}g.current=a.id,w.current.set(a.id,Date.now()),o.analytics?.onStepStart&&o.analytics.onStepStart(a.id,Date.now(),d);}},[n.currentStepIndex,o.steps,o.analytics,d]);let S=react.useMemo(()=>o.steps[n.currentStepIndex],[o.steps,n.currentStepIndex]),E=react.useMemo(()=>S?.formConfig,[S]),D=react.useCallback(async a=>{if(a<0||a>=o.steps.length)return false;l({type:"SET_TRANSITIONING",isTransitioning:true});try{return T.current&&T.current(n.currentStepIndex,a,d),l({type:"SET_CURRENT_STEP",stepIndex:a}),l({type:"MARK_STEP_VISITED",stepIndex:a,stepId:o.steps[a].id}),!0}catch(c){return console.error("Step transition failed:",c),o.analytics?.onError&&o.analytics.onError(c,d),false}finally{l({type:"SET_TRANSITIONING",isTransitioning:false});}},[o.steps,n.currentStepIndex,d,o.analytics]),L=react.useCallback(()=>({setStepData:(a,c)=>{l({type:"SET_STEP_DATA",data:c,stepId:a});},setStepFields:(a,c)=>{let C={...n.allData[a]||{},...c};l({type:"SET_STEP_DATA",data:C,stepId:a});},getStepData:a=>n.allData[a]||{},setNextStepField:(a,c)=>{let v=n.currentStepIndex+1;if(v<o.steps.length){let C=o.steps[v].id,J={...n.allData[C]||{},[a]:c};l({type:"SET_STEP_DATA",data:J,stepId:C});}},setNextStepFields:a=>{let c=n.currentStepIndex+1;if(c<o.steps.length){let v=o.steps[c].id,_={...n.allData[v]||{},...a};l({type:"SET_STEP_DATA",data:_,stepId:v});}},getAllData:()=>({...n.allData}),getSteps:()=>[...o.steps]}),[n.allData,n.currentStepIndex,o.steps]),A=react.useCallback((a,c)=>{l({type:"SET_FIELD_VALUE",fieldId:a,value:c,stepId:S?.id||""});},[S?.id]),F=react.useCallback(a=>{l({type:"SET_STEP_DATA",data:a,stepId:S?.id||""});},[S?.id]),W=react.useCallback(async()=>{if(S?.onAfterValidation)try{let c=L();await S.onAfterValidation(n.stepData,c,d);}catch(c){return console.error("onAfterValidation failed:",c),o.analytics?.onError&&o.analytics.onError(c,d),false}let a=n.currentStepIndex+1;return D(a)},[S,L,n.stepData,d,o.analytics,D,n.currentStepIndex]),B=react.useCallback(async()=>D(n.currentStepIndex-1),[n.currentStepIndex,D]),b=react.useCallback(async()=>{l({type:"SET_SUBMITTING",isSubmitting:true});try{if(x.current&&await x.current(n.allData),o.analytics?.onWorkflowComplete){let a=Date.now()-u.current;o.analytics.onWorkflowComplete(o.id,a,n.allData);}}catch(a){throw console.error("Workflow submission failed:",a),o.analytics?.onError&&o.analytics.onError(a,d),a}finally{l({type:"SET_SUBMITTING",isSubmitting:false});}},[n.allData,x,o.analytics,d]),V=react.useCallback(async()=>S?.allowSkip?(o.analytics?.onStepSkip&&o.analytics.onStepSkip(S.id,"user_skip",d),d.isLastStep?(await b(),true):W()):false,[S,o.analytics,d,W,b]),M=react.useCallback(()=>{l({type:"RESET_WORKFLOW"});},[]),z=react.useMemo(()=>({workflowState:n,workflowConfig:o,currentStep:S,context:d,formConfig:E,goToStep:D,goNext:W,goPrevious:B,skipStep:V,setValue:A,setStepData:F,submitWorkflow:b,resetWorkflow:M}),[n,o,S,d,E,D,W,B,V,A,F,b,M]),q=react.useCallback(async()=>{await W();},[W]);return jsxRuntime.jsx($.Provider,{value:z,children:jsxRuntime.jsx(forms.FormProvider,{formConfig:S?.formConfig,defaultValues:n?.allData[S?.id]||{},onFieldChange:A,"data-workflow-id":o.id,className:f,onSubmit:q,children:i})})}function y(){let i=react.useContext($);if(!i)throw new Error("useWorkflowContext must be used within a WorkflowProvider");return i}function ce({children:i,workflowConfig:e,...t}){let[r,s]=react.useState(false),f=h.shouldDisplayWatermark(),n=h.getWatermarkMessage(),l=react.useMemo(()=>e instanceof I?e.build():e,[e]);return react.useEffect(()=>{s(true);},[]),jsxRuntime.jsxs("div",{style:{position:"relative"},children:[jsxRuntime.jsx(N,{...t,workflowConfig:l,children:i}),r&&f&&jsxRuntime.jsx("div",{style:{position:"absolute",top:"10px",right:"10px",background:"rgba(0, 0, 0, 0.8)",color:"white",padding:"4px 8px",borderRadius:"4px",fontSize:"12px",fontFamily:"monospace",zIndex:1e3,pointerEvents:"none",opacity:.7},children:n})]})}function Se(){let{currentStep:i}=y();if(!i)return null;let{formConfig:e,renderer:t}=i;return e?t?t(i):jsxRuntime.jsx(forms.FormBody,{}):null}function ye({className:i,...e}){let{context:t,workflowState:r,workflowConfig:s,currentStep:f}=y(),{submit:n,formState:l}=forms.useFormContext(),u=!r.isTransitioning&&!r.isSubmitting,w=async g=>{g?.preventDefault(),u&&await n(g);},m={isLastStep:t.isLastStep,canGoNext:u,isSubmitting:l.isSubmitting||r.isSubmitting,onSubmit:w,className:i,currentStep:f,stepData:l.values||{},allData:t.allData,context:t};return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"WorkflowNextButton",renderer:s.renderConfig?.nextButtonRenderer,props:m,...e})}function xe({className:i,...e}){let{context:t,goPrevious:r,workflowState:s,workflowConfig:f,currentStep:n}=y(),{formState:l}=forms.useFormContext(),u=t.currentStepIndex>0&&!s.isTransitioning&&!s.isSubmitting,m={canGoPrevious:u,onPrevious:async g=>{g?.preventDefault(),u&&await r();},className:i,currentStep:n,stepData:l.values||{},allData:t.allData,context:t};return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"WorkflowPreviousButton",renderer:f.renderConfig?.previousButtonRenderer,props:m,...e})}function Re({className:i,...e}){let{currentStep:t,skipStep:r,workflowState:s,workflowConfig:f,context:n}=y(),{formState:l}=forms.useFormContext(),u=!!t?.allowSkip&&!s.isTransitioning&&!s.isSubmitting,m={canSkip:u,onSkip:async g=>{g?.preventDefault(),u&&await r();},className:i,currentStep:t,stepData:l.values||{},allData:n.allData,context:n};return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"WorkflowSkipButton",renderer:f.renderConfig?.skipButtonRenderer,props:m,...e})}function Te({onStepClick:i,className:e,...t}){let{workflowConfig:r,workflowState:s,goToStep:f}=y(),n=u=>{i?i(u):f(u);},l={steps:r.steps,currentStepIndex:s.currentStepIndex,visitedSteps:s.visitedSteps,onStepClick:n,className:e};return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"WorkflowStepper",renderer:r.renderConfig?.stepperRenderer,props:l,...t})}
2
+ Object.defineProperty(exports,"form",{enumerable:true,get:function(){return forms.form}});exports.RilayLicenseManager=h;exports.Workflow=ce;exports.WorkflowBody=Se;exports.WorkflowNextButton=ye;exports.WorkflowPreviousButton=xe;exports.WorkflowProvider=N;exports.WorkflowSkipButton=Re;exports.WorkflowStepper=Te;exports.createFlow=re;exports.flow=I;exports.useWorkflowContext=y;Object.keys(core).forEach(function(k){if(k!=='default'&&!Object.prototype.hasOwnProperty.call(exports,k))Object.defineProperty(exports,k,{enumerable:true,get:function(){return core[k]}})});
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import {ril,IdGenerator,normalizeToArray,configureObject,deepClone,ValidationErrorBuilder,ensureUnique,resolveRendererChildren}from'@rilaykit/core';export{createZodValidator,ril}from'@rilaykit/core';import {form,FormProvider,FormBody,useFormContext}from'@rilaykit/forms';export{form}from'@rilaykit/forms';import*as H from'@noble/ed25519';import {createContext,useReducer,useRef,useMemo,useEffect,useCallback,useContext,useState}from'react';import {jsx,jsxs}from'react/jsx-runtime';var Q=1751361139160,j="8fdb6a454550326d331c3b3d1d1f8c707a371bdb6c7ea72a0a1e4ea6f1822620",f=class f{static async setLicenseKey(e){f.licenseKey=e||"",f.licenseKey?f.licenseResult=await f.validateLicense():f.licenseResult={valid:false,error:"MISSING"},f.isInitialized=true;}static async validateLicense(){if(!f.licenseKey)return {valid:false,error:"MISSING"};try{if(!f.licenseKey.startsWith("ril_"))return {valid:!1,error:"FORMAT_INVALID"};let e=f.licenseKey.slice(4),o=f.base64ToString(e).split(".");if(o.length!==3)return {valid:!1,error:"FORMAT_INVALID"};let[a,d,p]=o,n=`${a}.${d}`,c=new TextEncoder().encode(n),w=p.match(/.{2}/g);if(!w)return {valid:!1,error:"INVALID"};let k=new Uint8Array(w.map(u=>Number.parseInt(u,16))),h=f.hexToBytes(j);if(!await H.verify(k,c,h))return {valid:!1,error:"SIGNATURE_INVALID"};let g=f.base64ToString(d.replace(/-/g,"+").replace(/_/g,"/")),m=JSON.parse(g),y=Math.floor(Date.now()/1e3);return m.e<y?{valid:!1,error:"EXPIRED",data:f.decompressPayload(m)}:Q>m.e*1e3?{valid:!1,error:"EXPIRED",data:f.decompressPayload(m)}:m.p===void 0||!m.c||!m.i||!m.e||!m.t?{valid:!1,error:"INVALID"}:{valid:!0,data:f.decompressPayload(m)}}catch{return {valid:false,error:"INVALID"}}}static decompressPayload(e){return {plan:{0:"ARCHITECT",1:"FOUNDRY"}[e.p]||"ARCHITECT",company:e.c,customerId:e.i.toString(),expiry:e.e*1e3,iat:e.t*1e3}}static hexToBytes(e){let r=new Uint8Array(e.length/2);for(let o=0;o<e.length;o+=2)r[o/2]=Number.parseInt(e.substring(o,o+2),16);return r}static base64ToString(e){if(typeof atob<"u")return atob(e);if(typeof Buffer<"u")return Buffer.from(e,"base64").toString();let r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",o="",a=0,d=e.replace(/[^A-Za-z0-9+/]/g,"");for(;a<d.length;){let p=r.indexOf(d.charAt(a++)),n=r.indexOf(d.charAt(a++)),c=r.indexOf(d.charAt(a++)),w=r.indexOf(d.charAt(a++)),k=p<<18|n<<12|c<<6|w;o+=String.fromCharCode(k>>16&255),c!==64&&(o+=String.fromCharCode(k>>8&255)),w!==64&&(o+=String.fromCharCode(k&255));}return o}static getLicenseResult(){return f.isInitialized?f.licenseResult?f.licenseResult:{valid:false,error:"MISSING"}:{valid:false,error:"MISSING"}}static shouldDisplayWatermark(){return typeof window>"u"?false:!f.getLicenseResult().valid}static getWatermarkMessage(){let e=f.getLicenseResult();return {MISSING:"Rilay Workflow - For Trial Use Only",EXPIRED:"Rilay Workflow - License Expired",INVALID:"Rilay Workflow - Invalid License",FORMAT_INVALID:"Rilay Workflow - Invalid License Format",SIGNATURE_INVALID:"Rilay Workflow - Invalid License Signature"}[e.error||"MISSING"]||""}static logLicenseStatus(){let e=f.getLicenseResult();if(e.valid)return;let o={MISSING:"\u{1F527} Rilay Workflow - Trial Mode. Purchase a license at https://rilay.io/pricing",EXPIRED:"\u26A0\uFE0F Rilay Workflow - License Expired. Please renew your license.",INVALID:"\u274C Rilay Workflow - Invalid License. Please check your license key.",FORMAT_INVALID:"\u274C Rilay Workflow - Invalid License Format. Please check your license key.",SIGNATURE_INVALID:"\u274C Rilay Workflow - Invalid License Signature. Please check your license key."}[e.error||"MISSING"];console.warn(`%c${o}`,"color: #f59e0b; font-weight: bold;");}static async getLicenseInfo(){let e=f.getLicenseResult();return !e.valid||!e.data?{}:{plan:e.data.plan,company:e.data.company,expiryDate:new Date(e.data.expiry).toLocaleDateString()}}};f.licenseKey="",f.licenseResult=null,f.isInitialized=false;var D=f;var x=class i{constructor(e,r,o,a){this.steps=[];this.navigation={allowBackNavigation:true};this.plugins=[];this.idGenerator=new IdGenerator;this.config=e,this.workflowId=r,this.workflowName=o,this.workflowDescription=a,D.logLicenseStatus();}static create(e,r,o,a){return new i(e,r,o,a)}createStepFromDefinition(e){return {id:e.id||this.idGenerator.next("step"),title:e.title,description:e.description,formConfig:e.formConfig instanceof form?e.formConfig.build():e.formConfig,allowSkip:e.allowSkip||false,requiredToComplete:e.requiredToComplete!==false,hooks:e.hooks,permissions:e.permissions,isDynamic:!!e.dynamicConfig,dynamicConfig:e.dynamicConfig,renderer:e.renderer}}addStep(e){let r=normalizeToArray(e);for(let o of r){let a=this.createStepFromDefinition(o);this.steps.push(a);}return this}addDynamicStep(e){return this.addStep(e)}configure(e){return e.navigation&&(this.navigation=configureObject(this.navigation,e.navigation)),e.persistence&&(this.persistence=e.persistence),e.completion&&(this.completion=e.completion),e.analytics&&(this.analytics=e.analytics),this}use(e){this.validatePluginDependencies(e),this.plugins.push(e);try{e.install(this);}catch(r){throw new Error(`Failed to install plugin "${e.name}": ${r instanceof Error?r.message:String(r)}`)}return this}validatePluginDependencies(e){if(!e.dependencies)return;let r=e.dependencies.filter(o=>!this.plugins.some(a=>a.name===o));if(r.length>0)throw new Error(`Plugin "${e.name}" requires missing dependencies: ${r.join(", ")}`)}removePlugin(e){return this.plugins=this.plugins.filter(r=>r.name!==e),this}updateStep(e,r){let o=this.steps.findIndex(a=>a.id===e);if(o===-1)throw new Error(`Step with ID "${e}" not found`);return this.steps[o]={...this.steps[o],...r},this}removeStep(e){return this.steps=this.steps.filter(r=>r.id!==e),this}getStep(e){return this.steps.find(r=>r.id===e)}getSteps(){return [...this.steps]}clearSteps(){return this.steps=[],this.idGenerator.reset(),this}clone(e,r){let o=new i(this.config,e||`${this.workflowId}-clone`,r||`${this.workflowName} (Copy)`,this.workflowDescription);return o.steps=deepClone(this.steps),o.navigation=deepClone(this.navigation),o.persistence=this.persistence?deepClone(this.persistence):void 0,o.completion=this.completion?deepClone(this.completion):void 0,o.analytics=this.analytics?deepClone(this.analytics):void 0,o.plugins=[...this.plugins],o}validate(){let e=new ValidationErrorBuilder;e.addIf(this.steps.length===0,"NO_STEPS","Workflow must have at least one step");let r=this.steps.map(o=>o.id);try{ensureUnique(r,"step");}catch(o){e.add("DUPLICATE_STEP_IDS",o instanceof Error?o.message:String(o));}for(let o of this.plugins)if(o.dependencies){let a=o.dependencies.filter(d=>!this.plugins.some(p=>p.name===d));e.addIf(a.length>0,"MISSING_PLUGIN_DEPENDENCIES",`Plugin "${o.name}" requires missing dependencies: ${a.join(", ")}`);}return e.build().map(o=>o.message)}getStats(){return {totalSteps:this.steps.length,dynamicSteps:this.steps.filter(e=>e.isDynamic).length,pluginsInstalled:this.plugins.length,estimatedFields:this.steps.reduce((e,r)=>e+r.formConfig.allFields.length,0),hasPersistence:!!this.persistence,hasAnalytics:!!this.analytics,allowBackNavigation:this.navigation.allowBackNavigation!==false}}build(){let e=this.validate();if(e.length>0)throw new Error(`Workflow validation failed: ${e.join(", ")}`);return {id:this.workflowId,name:this.workflowName,description:this.workflowDescription,steps:[...this.steps],navigation:this.navigation,persistence:this.persistence,completion:this.completion,analytics:this.analytics,plugins:[...this.plugins],renderConfig:this.config.getWorkflowRenderConfig()}}toJSON(){return {id:this.workflowId,name:this.workflowName,description:this.workflowDescription,steps:this.steps,navigation:this.navigation,persistence:this.persistence,completion:this.completion,analytics:this.analytics,plugins:this.plugins.map(e=>({name:e.name,version:e.version,dependencies:e.dependencies}))}}fromJSON(e){return e.id&&(this.workflowId=e.id),e.name&&(this.workflowName=e.name),e.description&&(this.workflowDescription=e.description),e.steps&&(this.steps=e.steps),e.navigation&&(this.navigation=e.navigation),e.persistence&&(this.persistence=e.persistence),e.completion&&(this.completion=e.completion),e.analytics&&(this.analytics=e.analytics),this}};function ae(i,e,r,o){return x.create(i,e,r,o)}ril.prototype.flow=function(i,e,r){return x.create(this,i,e,r)};function fe(i,e){switch(e.type){case "SET_CURRENT_STEP":return {...i,currentStepIndex:e.stepIndex,stepData:i.allData[i.resolvedSteps[e.stepIndex]?.id]||{}};case "SET_STEP_DATA":{let r=i.resolvedSteps[i.currentStepIndex]?.id;return {...i,stepData:e.data,allData:{...i.allData,[r]:e.data}}}case "SET_ALL_DATA":return {...i,allData:e.data};case "SET_FIELD_VALUE":{let r=i.resolvedSteps[i.currentStepIndex]?.id,o={...i.stepData,[e.fieldId]:e.value};return {...i,stepData:o,allData:{...i.allData,[r]:o}}}case "SET_ERROR":return {...i,errors:{...i.errors,[e.fieldId]:e.errors}};case "CLEAR_ERROR":{let r={...i.errors};return delete r[e.fieldId],{...i,errors:r}}case "MARK_TOUCHED":return {...i,touched:new Set([...i.touched,e.fieldId])};case "SET_VALIDATING":{let r=new Set(i.isValidating);return e.isValidating?r.add(e.fieldId):r.delete(e.fieldId),{...i,isValidating:r}}case "SET_SUBMITTING":return {...i,isSubmitting:e.isSubmitting};case "SET_TRANSITIONING":return {...i,isTransitioning:e.isTransitioning};case "MARK_STEP_VISITED":return {...i,visitedSteps:new Set([...i.visitedSteps,i.resolvedSteps[e.stepIndex]?.id])};case "SET_PERSISTED_DATA":return {...i,persistedData:e.data};case "SET_RESOLVED_STEPS":return {...i,resolvedSteps:e.steps};case "RESET_WORKFLOW":return {currentStepIndex:0,allData:{},stepData:{},errors:{},touched:new Set,isValidating:new Set,visitedSteps:new Set,isSubmitting:false,isTransitioning:false,resolvedSteps:i.resolvedSteps};default:return i}}var J=createContext(null);function F({children:i,workflowConfig:e,defaultValues:r={},onStepChange:o,onWorkflowComplete:a,className:d,user:p}){let[n,c]=useReducer(fe,{currentStepIndex:0,allData:r,stepData:{},errors:{},touched:new Set,isValidating:new Set,visitedSteps:new Set,isSubmitting:false,isTransitioning:false,resolvedSteps:e.steps}),w=useRef(null),k=useRef(Date.now()),h=useRef(new Map),E=useRef(false),g=useRef(null),m=useRef(o),y=useRef(a);m.current=o,y.current=a;let t=useMemo(()=>e,[e]),u=useMemo(()=>({workflowId:t.id,currentStepIndex:n.currentStepIndex,totalSteps:n.resolvedSteps.length,allData:n.allData,stepData:n.stepData,isFirstStep:n.currentStepIndex===0,isLastStep:n.currentStepIndex===n.resolvedSteps.length-1,visitedSteps:n.visitedSteps,user:p}),[t.id,n.currentStepIndex,n.resolvedSteps.length,n.allData,n.stepData,n.visitedSteps,p]);useEffect(()=>{(async()=>{let l=[];for(let S of t.steps)if(S.isDynamic&&S.dynamicConfig)try{let _=await S.dynamicConfig.resolver(n.allData,u);l.push(..._);}catch(_){console.error(`Failed to resolve dynamic step "${S.id}":`,_),l.push({...S,isDynamic:false});}else l.push(S);c({type:"SET_RESOLVED_STEPS",steps:l});})();},[t.steps,n.allData,u]),useEffect(()=>{t.analytics?.onWorkflowStart&&!E.current&&(E.current=true,t.analytics.onWorkflowStart(t.id,u));},[t.id,t.analytics,u]),useEffect(()=>{let s=n.resolvedSteps[n.currentStepIndex];if(s&&g.current!==s.id){if(g.current&&t.analytics?.onStepComplete){let l=h.current.get(g.current);l&&t.analytics.onStepComplete(g.current,Date.now()-l,n.stepData,u);}g.current=s.id,h.current.set(s.id,Date.now()),t.analytics?.onStepStart&&t.analytics.onStepStart(s.id,Date.now(),u);}},[n.currentStepIndex,n.resolvedSteps,t.analytics,u]);let C=useCallback(async()=>{if(t.persistence)try{let s={workflowId:t.id,currentStepIndex:n.currentStepIndex,allData:n.allData,metadata:{timestamp:Date.now(),version:"1.0.0",userId:p?.id,sessionId:crypto.randomUUID()}},l=t.persistence.key||`workflow-${t.id}`;await t.persistence.adapter.save(l,s),t.persistence.onSave&&await t.persistence.onSave(s);}catch(s){console.error("Failed to save workflow draft:",s),t.persistence.onError&&await t.persistence.onError(s,"save");}},[t,n.currentStepIndex,n.allData,p]),V=useCallback(async()=>{if(t.persistence)try{let s=t.persistence.key||`workflow-${t.id}`,l=await t.persistence.adapter.load(s);l&&l.workflowId===t.id&&(c({type:"SET_ALL_DATA",data:l.allData}),c({type:"SET_CURRENT_STEP",stepIndex:l.currentStepIndex}),c({type:"SET_PERSISTED_DATA",data:l}),t.persistence.onLoad&&await t.persistence.onLoad(l));}catch(s){console.error("Failed to load workflow draft:",s),t.persistence.onError&&await t.persistence.onError(s,"load");}},[t]),A=useCallback(async()=>{if(t.persistence)try{let s=t.persistence.key||`workflow-${t.id}`;await t.persistence.adapter.remove(s);}catch(s){console.error("Failed to clear workflow draft:",s),t.persistence.onError&&await t.persistence.onError(s,"remove");}},[t]);useEffect(()=>{t.persistence&&(async()=>{try{let l=t.persistence.key||`workflow-${t.id}`,S=await t.persistence.adapter.load(l);S&&S.workflowId===t.id&&(c({type:"SET_ALL_DATA",data:S.allData}),c({type:"SET_CURRENT_STEP",stepIndex:S.currentStepIndex}),c({type:"SET_PERSISTED_DATA",data:S}),t.persistence.onLoad&&await t.persistence.onLoad(S),console.log("Workflow data loaded from persistence:",S));}catch(l){console.error("Failed to load workflow draft on mount:",l),t.persistence.onError&&await t.persistence.onError(l,"load");}})();},[t.id]),useEffect(()=>{if(t.persistence?.saveOnStepChange)return w.current&&clearTimeout(w.current),w.current=setTimeout(()=>{C();},t.persistence.debounceMs||1e3),()=>{w.current&&clearTimeout(w.current);}},[n.allData,C,t.persistence]);let R=useMemo(()=>n.resolvedSteps[n.currentStepIndex],[n.resolvedSteps,n.currentStepIndex]),O=useMemo(()=>R?.formConfig,[R]),P=useCallback(async s=>{if(s<0||s>=n.resolvedSteps.length)return false;let l=n.resolvedSteps[s];if(l.permissions)try{if(!(l.permissions.customGuard?await l.permissions.customGuard(p,u):!0))return console.warn(`Access denied to step "${l.id}"`),!1}catch(S){return console.error(`Permission check failed for step "${l.id}":`,S),false}if(l.hooks?.onBeforeEnter)try{await l.hooks.onBeforeEnter(n.stepData,n.allData,u);}catch(S){return console.error(`onBeforeEnter hook failed for step "${l.id}":`,S),t.analytics?.onError&&t.analytics.onError(S,u),false}c({type:"SET_TRANSITIONING",isTransitioning:true});try{return m.current&&m.current(n.currentStepIndex,s,u),c({type:"SET_CURRENT_STEP",stepIndex:s}),c({type:"MARK_STEP_VISITED",stepIndex:s}),!0}catch(S){return console.error("Step transition failed:",S),t.analytics?.onError&&t.analytics.onError(S,u),false}finally{c({type:"SET_TRANSITIONING",isTransitioning:false});}},[n.resolvedSteps,n.currentStepIndex,n.stepData,n.allData,p,u,t.analytics]),B=useCallback((s,l)=>{c({type:"SET_FIELD_VALUE",fieldId:s,value:l});},[]),U=useCallback(s=>{c({type:"SET_STEP_DATA",data:s});},[]),M=useCallback(async()=>R?{isValid:true,errors:[]}:{isValid:true,errors:[]},[R]),L=useCallback(async()=>P(n.currentStepIndex+1),[P,n.currentStepIndex]),G=useCallback(async()=>t.navigation?.allowBackNavigation?P(n.currentStepIndex-1):false,[t.navigation,n.currentStepIndex,P]),$=useCallback(async()=>!R?.allowSkip||!t.navigation?.allowStepSkipping?false:(t.analytics?.onStepSkip&&t.analytics.onStepSkip(R.id,"user_skip",u),P(n.currentStepIndex+1)),[R,t.navigation,t.analytics,u,P,n.currentStepIndex]),K=useCallback(async()=>{c({type:"SET_SUBMITTING",isSubmitting:true});try{if(y.current&&await y.current(n.allData),await A(),t.analytics?.onWorkflowComplete){let s=Date.now()-k.current;t.analytics.onWorkflowComplete(t.id,s,n.allData);}}catch(s){throw console.error("Workflow submission failed:",s),t.analytics?.onError&&t.analytics.onError(s,u),s}finally{c({type:"SET_SUBMITTING",isSubmitting:false});}},[n.allData,y,A,t.analytics,u]),z=useCallback(()=>{c({type:"RESET_WORKFLOW"});},[]),Y=useMemo(()=>({workflowState:n,workflowConfig:t,currentStep:R,context:u,formConfig:O,goToStep:P,goNext:L,goPrevious:G,skipStep:$,setValue:B,setStepData:U,validateCurrentStep:M,submitWorkflow:K,resetWorkflow:z,saveDraft:C,loadDraft:V,clearDraft:A}),[n,t,R,u,O,P,L,G,$,B,U,M,K,z,C,V,A]),Z=useCallback(async()=>{await L();},[L]);return jsx(J.Provider,{value:Y,children:jsx(FormProvider,{formConfig:R?.formConfig,defaultValues:n?.allData[R?.id]||{},onFieldChange:B,"data-workflow-id":t.id,className:d,onSubmit:Z,children:i})})}function I(){let i=useContext(J);if(!i)throw new Error("useWorkflowContext must be used within a WorkflowProvider");return i}function we({children:i,workflowConfig:e,...r}){let[o,a]=useState(false),d=D.shouldDisplayWatermark(),p=D.getWatermarkMessage(),n=e instanceof x?e.build():e;return useEffect(()=>{a(true);},[]),jsxs("div",{style:{position:"relative"},children:[jsx(F,{...r,workflowConfig:n,children:i}),o&&d&&jsx("div",{style:{position:"absolute",top:"10px",right:"10px",background:"rgba(0, 0, 0, 0.8)",color:"white",padding:"4px 8px",borderRadius:"4px",fontSize:"12px",fontFamily:"monospace",zIndex:1e3,pointerEvents:"none",opacity:.7},children:p})]})}function ke(){let{currentStep:i}=I();if(!i)return null;let{formConfig:e,renderer:r}=i;return e?r?r(i):jsx(FormBody,{}):null}function Re({className:i,children:e,renderAs:r}){let{context:o,submitWorkflow:a,workflowState:d,workflowConfig:p,currentStep:n}=I(),{submit:c,formState:w}=useFormContext(),k=!d.isTransitioning&&!d.isSubmitting,h=async C=>{C?.preventDefault(),k&&await c(C);},E=async C=>{C?.preventDefault(),k&&await a();},g={isLastStep:o.isLastStep,canGoNext:k,isSubmitting:d.isSubmitting,onNext:h,onSubmit:E,className:i,currentStep:n,stepData:w.values||{},allData:o.allData,context:o};if(r==="children"||r===true){if(typeof e!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');return e(g)}let y=p.renderConfig?.nextButtonRenderer;if(!y)throw new Error(`No nextButtonRenderer configured for workflow "${p.id}". Please configure a nextButtonRenderer using config.setWorkflowNextButtonRenderer() or config.setWorkflowRenderConfig().`);let t=resolveRendererChildren(e,g),u={...g,children:t};return y(u)}function Ce({className:i,children:e,renderAs:r}){let{context:o,goPrevious:a,workflowState:d,workflowConfig:p,currentStep:n}=I(),{formState:c}=useFormContext(),w=o.currentStepIndex>0&&p.navigation?.allowBackNavigation!==false&&!d.isTransitioning&&!d.isSubmitting;if(p.navigation?.allowBackNavigation===false)throw new Error(`WorkflowPreviousButton is rendered but allowBackNavigation is disabled in workflow "${p.id}". Either enable back navigation or remove the WorkflowPreviousButton component.`);let h={canGoPrevious:w,onPrevious:async t=>{t?.preventDefault(),w&&await a();},className:i,currentStep:n,stepData:c.values||{},allData:o.allData,context:o};if(r==="children"||r===true){if(typeof e!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');return e(h)}let g=p.renderConfig?.previousButtonRenderer;if(!g)throw new Error(`No previousButtonRenderer configured for workflow "${p.id}". Please configure a previousButtonRenderer using config.setWorkflowPreviousButtonRenderer() or config.setWorkflowRenderConfig().`);let m=resolveRendererChildren(e,h),y={...h,children:m};return g(y)}function xe({className:i,children:e,renderAs:r}){let{currentStep:o,skipStep:a,workflowState:d,workflowConfig:p,context:n}=I(),{formState:c}=useFormContext(),w=!!o?.allowSkip&&p.navigation?.allowStepSkipping!==false&&!d.isTransitioning&&!d.isSubmitting,h={canSkip:w,onSkip:async t=>{t?.preventDefault(),w&&await a();},className:i,currentStep:o,stepData:c.values||{},allData:n.allData,context:n};if(r==="children"||r===true){if(typeof e!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');return e(h)}let g=p.renderConfig?.skipButtonRenderer;if(!g)throw new Error(`No skipButtonRenderer configured for workflow "${p.id}". Please configure a skipButtonRenderer using config.setWorkflowSkipButtonRenderer() or config.setWorkflowRenderConfig().`);let m=resolveRendererChildren(e,h),y={...h,children:m};return g(y)}function We({onStepClick:i,className:e,children:r,renderAs:o}){let{workflowConfig:a,workflowState:d,goToStep:p}=I(),n=E=>{i?i(E):p(E);},c={steps:d.resolvedSteps,currentStepIndex:d.currentStepIndex,visitedSteps:d.visitedSteps,onStepClick:n,className:e};if(o==="children"||o===true){if(typeof r!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');return r(c)}let k=a.renderConfig?.stepperRenderer;if(!k)throw new Error(`No stepperRenderer configured for workflow "${a.id}". Please configure a stepperRenderer using config.setStepperRenderer() or config.setWorkflowRenderConfig().`);return k(c)}
2
- export{D as RilayLicenseManager,we as Workflow,ke as WorkflowBody,Re as WorkflowNextButton,Ce as WorkflowPreviousButton,F as WorkflowProvider,xe as WorkflowSkipButton,We as WorkflowStepper,ae as createFlow,x as flow,I as useWorkflowContext};
1
+ import {ril,IdGenerator,normalizeToArray,deepClone,ensureUnique,ComponentRendererWrapper}from'@rilaykit/core';export*from'@rilaykit/core';import {form,FormProvider,FormBody,useFormContext}from'@rilaykit/forms';export{form}from'@rilaykit/forms';import*as O from'@noble/ed25519';import {createContext,useReducer,useRef,useMemo,useEffect,useCallback,useContext,useState}from'react';import {jsx,jsxs}from'react/jsx-runtime';var X=1751361139160,Y="8fdb6a454550326d331c3b3d1d1f8c707a371bdb6c7ea72a0a1e4ea6f1822620",p=class p{static async setLicenseKey(e){p.licenseKey=e||"",p.licenseKey?p.licenseResult=await p.validateLicense():p.licenseResult={valid:false,error:"MISSING"},p.isInitialized=true;}static async validateLicense(){if(!p.licenseKey)return {valid:false,error:"MISSING"};try{if(!p.licenseKey.startsWith("ril_"))return {valid:!1,error:"FORMAT_INVALID"};let e=p.licenseKey.slice(4),r=p.base64ToString(e).split(".");if(r.length!==3)return {valid:!1,error:"FORMAT_INVALID"};let[s,f,n]=r,l=`${s}.${f}`,u=new TextEncoder().encode(l),w=n.match(/.{2}/g);if(!w)return {valid:!1,error:"INVALID"};let m=new Uint8Array(w.map(E=>Number.parseInt(E,16))),g=p.hexToBytes(Y);if(!await O.verify(m,u,g))return {valid:!1,error:"SIGNATURE_INVALID"};let x=p.base64ToString(f.replace(/-/g,"+").replace(/_/g,"/")),o=JSON.parse(x),d=Math.floor(Date.now()/1e3);return o.e<d?{valid:!1,error:"EXPIRED",data:p.decompressPayload(o)}:X>o.e*1e3?{valid:!1,error:"EXPIRED",data:p.decompressPayload(o)}:o.p===void 0||!o.c||!o.i||!o.e||!o.t?{valid:!1,error:"INVALID"}:{valid:!0,data:p.decompressPayload(o)}}catch{return {valid:false,error:"INVALID"}}}static decompressPayload(e){return {plan:{0:"ARCHITECT",1:"FOUNDRY"}[e.p]||"ARCHITECT",company:e.c,customerId:e.i.toString(),expiry:e.e*1e3,iat:e.t*1e3}}static hexToBytes(e){let t=new Uint8Array(e.length/2);for(let r=0;r<e.length;r+=2)t[r/2]=Number.parseInt(e.substring(r,r+2),16);return t}static base64ToString(e){if(typeof atob<"u")return atob(e);if(typeof Buffer<"u")return Buffer.from(e,"base64").toString();let t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",r="",s=0,f=e.replace(/[^A-Za-z0-9+/]/g,"");for(;s<f.length;){let n=t.indexOf(f.charAt(s++)),l=t.indexOf(f.charAt(s++)),u=t.indexOf(f.charAt(s++)),w=t.indexOf(f.charAt(s++)),m=n<<18|l<<12|u<<6|w;r+=String.fromCharCode(m>>16&255),u!==64&&(r+=String.fromCharCode(m>>8&255)),w!==64&&(r+=String.fromCharCode(m&255));}return r}static getLicenseResult(){return p.isInitialized?p.licenseResult?p.licenseResult:{valid:false,error:"MISSING"}:{valid:false,error:"MISSING"}}static shouldDisplayWatermark(){return typeof window>"u"?false:!p.getLicenseResult().valid}static getWatermarkMessage(){let e=p.getLicenseResult();return {MISSING:"Rilay Workflow - For Trial Use Only",EXPIRED:"Rilay Workflow - License Expired",INVALID:"Rilay Workflow - Invalid License",FORMAT_INVALID:"Rilay Workflow - Invalid License Format",SIGNATURE_INVALID:"Rilay Workflow - Invalid License Signature"}[e.error||"MISSING"]||""}static logLicenseStatus(){let e=p.getLicenseResult();if(e.valid)return;let r={MISSING:"\u{1F527} Rilay Workflow - Trial Mode. Purchase a license at https://rilay.io/pricing",EXPIRED:"\u26A0\uFE0F Rilay Workflow - License Expired. Please renew your license.",INVALID:"\u274C Rilay Workflow - Invalid License. Please check your license key.",FORMAT_INVALID:"\u274C Rilay Workflow - Invalid License Format. Please check your license key.",SIGNATURE_INVALID:"\u274C Rilay Workflow - Invalid License Signature. Please check your license key."}[e.error||"MISSING"];console.warn(`%c${r}`,"color: #f59e0b; font-weight: bold;");}static async getLicenseInfo(){let e=p.getLicenseResult();return !e.valid||!e.data?{}:{plan:e.data.plan,company:e.data.company,expiryDate:new Date(e.data.expiry).toLocaleDateString()}}};p.licenseKey="",p.licenseResult=null,p.isInitialized=false;var h=p;var I=class i{constructor(e,t,r,s){this.steps=[];this.plugins=[];this.idGenerator=new IdGenerator;this.config=e,this.workflowId=t,this.workflowName=r,this.workflowDescription=s,h.logLicenseStatus();}static create(e,t,r,s){return new i(e,t,r,s)}createStepFromDefinition(e){return {id:e.id||this.idGenerator.next("step"),title:e.title,description:e.description,formConfig:e.formConfig instanceof form?e.formConfig.build():e.formConfig,allowSkip:e.allowSkip||false,renderer:e.renderer,onAfterValidation:e.onAfterValidation}}addStep(e){let t=normalizeToArray(e);for(let r of t){let s=this.createStepFromDefinition(r);this.steps.push(s);}return this}configure(e){return e.analytics&&(this.analytics=e.analytics),this}use(e){this.validatePluginDependencies(e),this.plugins.push(e);try{e.install(this);}catch(t){throw new Error(`Failed to install plugin "${e.name}": ${t instanceof Error?t.message:String(t)}`)}return this}validatePluginDependencies(e){if(!e.dependencies)return;let t=e.dependencies.filter(r=>!this.plugins.some(s=>s.name===r));if(t.length>0)throw new Error(`Plugin "${e.name}" requires missing dependencies: ${t.join(", ")}`)}removePlugin(e){return this.plugins=this.plugins.filter(t=>t.name!==e),this}updateStep(e,t){let r=this.steps.findIndex(s=>s.id===e);if(r===-1)throw new Error(`Step with ID "${e}" not found`);return this.steps[r]={...this.steps[r],...t},this}removeStep(e){return this.steps=this.steps.filter(t=>t.id!==e),this}getStep(e){return this.steps.find(t=>t.id===e)}getSteps(){return [...this.steps]}clearSteps(){return this.steps=[],this.idGenerator.reset(),this}clone(e,t){let r=new i(this.config,e||`${this.workflowId}-clone`,t||this.workflowName);return r.steps=deepClone(this.steps),r.analytics=this.analytics?deepClone(this.analytics):void 0,r.plugins=[...this.plugins],r}validate(){let e=[];this.steps.length===0&&e.push("Workflow must have at least one step");let t=this.steps.map(r=>r.id);try{ensureUnique(t,"step");}catch(r){e.push(r instanceof Error?r.message:String(r));}for(let r of this.plugins)if(r.dependencies){let s=r.dependencies.filter(f=>!this.plugins.some(n=>n.name===f));s.length>0&&e.push(`Plugin "${r.name}" requires missing dependencies: ${s.join(", ")}`);}return e}getStats(){let e=this.steps.reduce((r,s)=>r+s.formConfig.allFields.length,0),t=this.steps.map(r=>r.formConfig.allFields.length);return {totalSteps:this.steps.length,totalFields:e,averageFieldsPerStep:this.steps.length>0?e/this.steps.length:0,maxFieldsInStep:t.length>0?Math.max(...t):0,minFieldsInStep:t.length>0?Math.min(...t):0,hasAnalytics:!!this.analytics}}build(){let e=this.validate();if(e.length>0)throw new Error(`Workflow validation failed: ${e.join(", ")}`);return {id:this.workflowId,name:this.workflowName,description:this.workflowDescription,steps:this.steps,analytics:this.analytics,plugins:this.plugins,renderConfig:this.config.getWorkflowRenderConfig()}}toJSON(){return {id:this.workflowId,name:this.workflowName,description:this.workflowDescription,steps:this.steps,analytics:this.analytics,plugins:this.plugins.map(e=>({name:e.name,version:e.version}))}}fromJSON(e){return this.workflowId=e.workflowId,this.workflowName=e.workflowName,this.workflowDescription=e.workflowDescription,this.steps=e.steps,this.analytics=e.analytics,this.plugins=e.plugins||[],this}};function re(i,e,t,r){return I.create(i,e,t,r)}ril.prototype.flow=function(i,e,t){return I.create(this,i,e,t)};function ae(i,e){switch(e.type){case "SET_CURRENT_STEP":return {...i,currentStepIndex:e.stepIndex};case "SET_STEP_DATA":{let t=e.stepId;return {...i,stepData:e.data,allData:{...i.allData,[t]:e.data}}}case "SET_ALL_DATA":return {...i,allData:e.data};case "SET_FIELD_VALUE":{let t=e.stepId,r={...i.stepData,[e.fieldId]:e.value};return {...i,stepData:r,allData:{...i.allData,[t]:r}}}case "SET_SUBMITTING":return {...i,isSubmitting:e.isSubmitting};case "SET_TRANSITIONING":return {...i,isTransitioning:e.isTransitioning};case "MARK_STEP_VISITED":return {...i,visitedSteps:new Set([...i.visitedSteps,e.stepId])};case "RESET_WORKFLOW":return {currentStepIndex:0,allData:{},stepData:{},visitedSteps:new Set,isSubmitting:false,isTransitioning:false};default:return i}}var $=createContext(null);function N({children:i,workflowConfig:e,defaultValues:t={},onStepChange:r,onWorkflowComplete:s,className:f}){let[n,l]=useReducer(ae,{currentStepIndex:0,allData:t,stepData:{},visitedSteps:new Set,isSubmitting:false,isTransitioning:false}),u=useRef(Date.now()),w=useRef(new Map),m=useRef(false),g=useRef(null),T=useRef(r),x=useRef(s);T.current=r,x.current=s;let o=useMemo(()=>e,[e]),d=useMemo(()=>({workflowId:o.id,currentStepIndex:n.currentStepIndex,totalSteps:o.steps.length,allData:n.allData,stepData:n.stepData,isFirstStep:n.currentStepIndex===0,isLastStep:n.currentStepIndex===o.steps.length-1,visitedSteps:n.visitedSteps}),[o.id,n.currentStepIndex,o.steps.length,n.allData,n.stepData,n.visitedSteps]);useEffect(()=>{o.analytics?.onWorkflowStart&&!m.current&&(m.current=true,o.analytics.onWorkflowStart(o.id,d));},[o.id,o.analytics,d]),useEffect(()=>{let a=o.steps[n.currentStepIndex];if(a&&g.current!==a.id){if(g.current&&o.analytics?.onStepComplete){let c=w.current.get(g.current);c&&o.analytics.onStepComplete(g.current,Date.now()-c,n.stepData,d);}g.current=a.id,w.current.set(a.id,Date.now()),o.analytics?.onStepStart&&o.analytics.onStepStart(a.id,Date.now(),d);}},[n.currentStepIndex,o.steps,o.analytics,d]);let S=useMemo(()=>o.steps[n.currentStepIndex],[o.steps,n.currentStepIndex]),E=useMemo(()=>S?.formConfig,[S]),D=useCallback(async a=>{if(a<0||a>=o.steps.length)return false;l({type:"SET_TRANSITIONING",isTransitioning:true});try{return T.current&&T.current(n.currentStepIndex,a,d),l({type:"SET_CURRENT_STEP",stepIndex:a}),l({type:"MARK_STEP_VISITED",stepIndex:a,stepId:o.steps[a].id}),!0}catch(c){return console.error("Step transition failed:",c),o.analytics?.onError&&o.analytics.onError(c,d),false}finally{l({type:"SET_TRANSITIONING",isTransitioning:false});}},[o.steps,n.currentStepIndex,d,o.analytics]),L=useCallback(()=>({setStepData:(a,c)=>{l({type:"SET_STEP_DATA",data:c,stepId:a});},setStepFields:(a,c)=>{let C={...n.allData[a]||{},...c};l({type:"SET_STEP_DATA",data:C,stepId:a});},getStepData:a=>n.allData[a]||{},setNextStepField:(a,c)=>{let v=n.currentStepIndex+1;if(v<o.steps.length){let C=o.steps[v].id,J={...n.allData[C]||{},[a]:c};l({type:"SET_STEP_DATA",data:J,stepId:C});}},setNextStepFields:a=>{let c=n.currentStepIndex+1;if(c<o.steps.length){let v=o.steps[c].id,_={...n.allData[v]||{},...a};l({type:"SET_STEP_DATA",data:_,stepId:v});}},getAllData:()=>({...n.allData}),getSteps:()=>[...o.steps]}),[n.allData,n.currentStepIndex,o.steps]),A=useCallback((a,c)=>{l({type:"SET_FIELD_VALUE",fieldId:a,value:c,stepId:S?.id||""});},[S?.id]),F=useCallback(a=>{l({type:"SET_STEP_DATA",data:a,stepId:S?.id||""});},[S?.id]),W=useCallback(async()=>{if(S?.onAfterValidation)try{let c=L();await S.onAfterValidation(n.stepData,c,d);}catch(c){return console.error("onAfterValidation failed:",c),o.analytics?.onError&&o.analytics.onError(c,d),false}let a=n.currentStepIndex+1;return D(a)},[S,L,n.stepData,d,o.analytics,D,n.currentStepIndex]),B=useCallback(async()=>D(n.currentStepIndex-1),[n.currentStepIndex,D]),b=useCallback(async()=>{l({type:"SET_SUBMITTING",isSubmitting:true});try{if(x.current&&await x.current(n.allData),o.analytics?.onWorkflowComplete){let a=Date.now()-u.current;o.analytics.onWorkflowComplete(o.id,a,n.allData);}}catch(a){throw console.error("Workflow submission failed:",a),o.analytics?.onError&&o.analytics.onError(a,d),a}finally{l({type:"SET_SUBMITTING",isSubmitting:false});}},[n.allData,x,o.analytics,d]),V=useCallback(async()=>S?.allowSkip?(o.analytics?.onStepSkip&&o.analytics.onStepSkip(S.id,"user_skip",d),d.isLastStep?(await b(),true):W()):false,[S,o.analytics,d,W,b]),M=useCallback(()=>{l({type:"RESET_WORKFLOW"});},[]),z=useMemo(()=>({workflowState:n,workflowConfig:o,currentStep:S,context:d,formConfig:E,goToStep:D,goNext:W,goPrevious:B,skipStep:V,setValue:A,setStepData:F,submitWorkflow:b,resetWorkflow:M}),[n,o,S,d,E,D,W,B,V,A,F,b,M]),q=useCallback(async()=>{await W();},[W]);return jsx($.Provider,{value:z,children:jsx(FormProvider,{formConfig:S?.formConfig,defaultValues:n?.allData[S?.id]||{},onFieldChange:A,"data-workflow-id":o.id,className:f,onSubmit:q,children:i})})}function y(){let i=useContext($);if(!i)throw new Error("useWorkflowContext must be used within a WorkflowProvider");return i}function ce({children:i,workflowConfig:e,...t}){let[r,s]=useState(false),f=h.shouldDisplayWatermark(),n=h.getWatermarkMessage(),l=useMemo(()=>e instanceof I?e.build():e,[e]);return useEffect(()=>{s(true);},[]),jsxs("div",{style:{position:"relative"},children:[jsx(N,{...t,workflowConfig:l,children:i}),r&&f&&jsx("div",{style:{position:"absolute",top:"10px",right:"10px",background:"rgba(0, 0, 0, 0.8)",color:"white",padding:"4px 8px",borderRadius:"4px",fontSize:"12px",fontFamily:"monospace",zIndex:1e3,pointerEvents:"none",opacity:.7},children:n})]})}function Se(){let{currentStep:i}=y();if(!i)return null;let{formConfig:e,renderer:t}=i;return e?t?t(i):jsx(FormBody,{}):null}function ye({className:i,...e}){let{context:t,workflowState:r,workflowConfig:s,currentStep:f}=y(),{submit:n,formState:l}=useFormContext(),u=!r.isTransitioning&&!r.isSubmitting,w=async g=>{g?.preventDefault(),u&&await n(g);},m={isLastStep:t.isLastStep,canGoNext:u,isSubmitting:l.isSubmitting||r.isSubmitting,onSubmit:w,className:i,currentStep:f,stepData:l.values||{},allData:t.allData,context:t};return jsx(ComponentRendererWrapper,{name:"WorkflowNextButton",renderer:s.renderConfig?.nextButtonRenderer,props:m,...e})}function xe({className:i,...e}){let{context:t,goPrevious:r,workflowState:s,workflowConfig:f,currentStep:n}=y(),{formState:l}=useFormContext(),u=t.currentStepIndex>0&&!s.isTransitioning&&!s.isSubmitting,m={canGoPrevious:u,onPrevious:async g=>{g?.preventDefault(),u&&await r();},className:i,currentStep:n,stepData:l.values||{},allData:t.allData,context:t};return jsx(ComponentRendererWrapper,{name:"WorkflowPreviousButton",renderer:f.renderConfig?.previousButtonRenderer,props:m,...e})}function Re({className:i,...e}){let{currentStep:t,skipStep:r,workflowState:s,workflowConfig:f,context:n}=y(),{formState:l}=useFormContext(),u=!!t?.allowSkip&&!s.isTransitioning&&!s.isSubmitting,m={canSkip:u,onSkip:async g=>{g?.preventDefault(),u&&await r();},className:i,currentStep:t,stepData:l.values||{},allData:n.allData,context:n};return jsx(ComponentRendererWrapper,{name:"WorkflowSkipButton",renderer:f.renderConfig?.skipButtonRenderer,props:m,...e})}function Te({onStepClick:i,className:e,...t}){let{workflowConfig:r,workflowState:s,goToStep:f}=y(),n=u=>{i?i(u):f(u);},l={steps:r.steps,currentStepIndex:s.currentStepIndex,visitedSteps:s.visitedSteps,onStepClick:n,className:e};return jsx(ComponentRendererWrapper,{name:"WorkflowStepper",renderer:r.renderConfig?.stepperRenderer,props:l,...t})}
2
+ export{h as RilayLicenseManager,ce as Workflow,Se as WorkflowBody,ye as WorkflowNextButton,xe as WorkflowPreviousButton,N as WorkflowProvider,Re as WorkflowSkipButton,Te as WorkflowStepper,re as createFlow,I as flow,y as useWorkflowContext};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rilaykit/workflow",
3
- "version": "4.0.0",
3
+ "version": "5.0.0",
4
4
  "description": "Commercial workflow and multi-step form utilities for RilayKit - License required for all use",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -26,8 +26,8 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@noble/ed25519": "^1.7.1",
29
- "@rilaykit/core": "4.0.0",
30
- "@rilaykit/forms": "4.0.0"
29
+ "@rilaykit/core": "5.0.0",
30
+ "@rilaykit/forms": "5.0.0"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "react": ">=18.0.0",