@secmia/openui-flow 4.0.1 → 4.2.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.js CHANGED
@@ -40,7 +40,8 @@ __export(index_exports, {
40
40
  defaultRequirements: () => defaultRequirements,
41
41
  evaluateNextStep: () => evaluateNextStep,
42
42
  getMissingRequirements: () => getMissingRequirements,
43
- initialContext: () => initialContext
43
+ initialContext: () => initialContext,
44
+ useAdaptiveFlow: () => useAdaptiveFlow
44
45
  });
45
46
  module.exports = __toCommonJS(index_exports);
46
47
 
@@ -70,6 +71,8 @@ var defaultRequirements = [
70
71
  DefaultAppRequirements.EMAIL_VERIFIED,
71
72
  DefaultAppRequirements.HAS_PASSWORD,
72
73
  DefaultAppRequirements.HAS_FIRST_NAME,
74
+ DefaultAppRequirements.HAS_LAST_NAME,
75
+ DefaultAppRequirements.HAS_JOB_TITLE,
73
76
  DefaultAppRequirements.ACCEPTED_TOS
74
77
  ];
75
78
  var initialContext = {
@@ -115,20 +118,66 @@ var defaultRequirementResolvers = {
115
118
  };
116
119
  function createRequirementGraph(requirements, resolvers, options) {
117
120
  const graph = [];
121
+ const requirementSet = new Set(requirements);
122
+ const resolverBackedRequirements = new Set(
123
+ requirements.filter((requirement) => Boolean(resolvers[requirement]))
124
+ );
118
125
  for (const requirement of requirements) {
119
126
  const resolver = resolvers[requirement];
120
127
  if (!resolver) {
121
128
  continue;
122
129
  }
130
+ const dependsOn = options?.dependencies?.[requirement] ?? [];
131
+ for (const dependency of dependsOn) {
132
+ if (!requirementSet.has(dependency)) {
133
+ throw new Error(
134
+ `Invalid dependency "${String(dependency)}" referenced by requirement "${String(requirement)}".`
135
+ );
136
+ }
137
+ if (!resolverBackedRequirements.has(dependency)) {
138
+ throw new Error(
139
+ `Dependency "${String(dependency)}" referenced by requirement "${String(requirement)}" has no resolver.`
140
+ );
141
+ }
142
+ }
123
143
  graph.push({
124
144
  requirement,
125
145
  step: resolver.step,
126
146
  isMet: resolver.isMet,
127
147
  when: options?.conditions?.[requirement],
128
148
  priority: options?.priorities?.[requirement] ?? 0,
129
- dependsOn: options?.dependencies?.[requirement] ?? []
149
+ dependsOn
130
150
  });
131
151
  }
152
+ const byRequirement = new Map(
153
+ graph.map((node) => [node.requirement, node])
154
+ );
155
+ const visited = /* @__PURE__ */ new Set();
156
+ const visiting = /* @__PURE__ */ new Set();
157
+ const dfs = (requirement, stack) => {
158
+ if (visited.has(requirement)) {
159
+ return;
160
+ }
161
+ if (visiting.has(requirement)) {
162
+ const cycleStart = stack.indexOf(requirement);
163
+ const cyclePath = [...stack.slice(cycleStart), requirement].map((value) => String(value)).join(" -> ");
164
+ throw new Error(`Circular dependency detected in requirement graph: ${cyclePath}`);
165
+ }
166
+ visiting.add(requirement);
167
+ const node = byRequirement.get(requirement);
168
+ if (node?.dependsOn?.length) {
169
+ for (const dep of node.dependsOn) {
170
+ if (byRequirement.has(dep)) {
171
+ dfs(dep, [...stack, requirement]);
172
+ }
173
+ }
174
+ }
175
+ visiting.delete(requirement);
176
+ visited.add(requirement);
177
+ };
178
+ for (const node of graph) {
179
+ dfs(node.requirement, []);
180
+ }
132
181
  return graph;
133
182
  }
134
183
  function createDefaultRequirementGraph(options) {
@@ -144,13 +193,63 @@ function createDefaultRequirementGraph(options) {
144
193
  });
145
194
  }
146
195
  function sortGraph(graph) {
147
- return [...graph].sort((left, right) => {
148
- const byPriority = (right.priority ?? 0) - (left.priority ?? 0);
196
+ const entries = graph.map((node, index) => ({ node, index }));
197
+ const byRequirement = new Map(entries.map((entry) => [entry.node.requirement, entry]));
198
+ const indegree = /* @__PURE__ */ new Map();
199
+ const adjacency = /* @__PURE__ */ new Map();
200
+ for (const entry of entries) {
201
+ indegree.set(entry.node.requirement, 0);
202
+ adjacency.set(entry.node.requirement, []);
203
+ }
204
+ for (const entry of entries) {
205
+ const current = entry.node.requirement;
206
+ for (const dependency of entry.node.dependsOn ?? []) {
207
+ const depEntry = byRequirement.get(dependency);
208
+ if (!depEntry) {
209
+ continue;
210
+ }
211
+ const outgoing = adjacency.get(depEntry.node.requirement);
212
+ if (outgoing) {
213
+ outgoing.push(current);
214
+ }
215
+ indegree.set(current, (indegree.get(current) ?? 0) + 1);
216
+ }
217
+ }
218
+ const compare = (left, right) => {
219
+ const byPriority = (right.node.priority ?? 0) - (left.node.priority ?? 0);
149
220
  if (byPriority !== 0) {
150
221
  return byPriority;
151
222
  }
152
- return 0;
153
- });
223
+ const byRequirementName = String(left.node.requirement).localeCompare(String(right.node.requirement));
224
+ if (byRequirementName !== 0) {
225
+ return byRequirementName;
226
+ }
227
+ return left.index - right.index;
228
+ };
229
+ const ready = entries.filter((entry) => (indegree.get(entry.node.requirement) ?? 0) === 0).sort(compare);
230
+ const ordered = [];
231
+ while (ready.length > 0) {
232
+ const current = ready.shift();
233
+ if (!current) {
234
+ break;
235
+ }
236
+ ordered.push(current.node);
237
+ for (const dependent of adjacency.get(current.node.requirement) ?? []) {
238
+ const next = (indegree.get(dependent) ?? 0) - 1;
239
+ indegree.set(dependent, next);
240
+ if (next === 0) {
241
+ const dependentEntry = byRequirement.get(dependent);
242
+ if (dependentEntry) {
243
+ ready.push(dependentEntry);
244
+ ready.sort(compare);
245
+ }
246
+ }
247
+ }
248
+ }
249
+ if (ordered.length !== graph.length) {
250
+ throw new Error("Unable to topologically sort requirement graph. Check for dependency cycles.");
251
+ }
252
+ return ordered;
154
253
  }
155
254
  async function evaluateNextStep(context, graph, completeStep) {
156
255
  for (const node of sortGraph(graph)) {
@@ -191,6 +290,10 @@ async function getMissingRequirements(context, graph) {
191
290
 
192
291
  // src/AdaptiveFlow.tsx
193
292
  var import_jsx_runtime = require("react/jsx-runtime");
293
+ var defaultOAuthProviders = [
294
+ { id: "google", label: "Continue with Google" },
295
+ { id: "apple", label: "Continue with Apple" }
296
+ ];
194
297
  var defaultStepTitle = {
195
298
  COLLECT_EMAIL: "Enter your email",
196
299
  VERIFY_OTP: "Verify your email",
@@ -199,6 +302,14 @@ var defaultStepTitle = {
199
302
  COLLECT_TOS: "Accept terms",
200
303
  COMPLETE: "Done"
201
304
  };
305
+ var builtInDefaultSteps = /* @__PURE__ */ new Set([
306
+ "COLLECT_EMAIL",
307
+ "VERIFY_OTP",
308
+ "COLLECT_PASSWORD",
309
+ "COLLECT_PROFILE",
310
+ "COLLECT_TOS",
311
+ "COMPLETE"
312
+ ]);
202
313
  var styleSlots = [
203
314
  "shell",
204
315
  "headerRow",
@@ -219,14 +330,24 @@ var styleSlots = [
219
330
  "oauthButton"
220
331
  ];
221
332
  function mergeContext(current, patch) {
222
- return {
223
- ...current,
224
- ...patch,
225
- profile: {
226
- ...current.profile,
227
- ...patch.profile
333
+ const mergeValue = (baseValue, patchValue) => {
334
+ if (Array.isArray(baseValue) || Array.isArray(patchValue)) {
335
+ return patchValue;
336
+ }
337
+ const baseIsObject = Boolean(baseValue) && typeof baseValue === "object";
338
+ const patchIsObject = Boolean(patchValue) && typeof patchValue === "object";
339
+ if (!baseIsObject || !patchIsObject) {
340
+ return patchValue === void 0 ? baseValue : patchValue;
228
341
  }
342
+ const baseObject = baseValue;
343
+ const patchObject = patchValue;
344
+ const result = { ...baseObject };
345
+ for (const key of Object.keys(patchObject)) {
346
+ result[key] = mergeValue(baseObject[key], patchObject[key]);
347
+ }
348
+ return result;
229
349
  };
350
+ return mergeValue(current, patch);
230
351
  }
231
352
  function withDefaults(initialValue) {
232
353
  if (!initialValue) {
@@ -238,7 +359,65 @@ function toError(error) {
238
359
  if (error instanceof Error) {
239
360
  return error;
240
361
  }
241
- return new Error("Unknown error while processing adaptive flow");
362
+ if (typeof error === "string") {
363
+ return new Error(error);
364
+ }
365
+ if (error && typeof error === "object") {
366
+ const maybeError = error;
367
+ const message = typeof maybeError.message === "string" && maybeError.message.trim().length > 0 ? maybeError.message : "Unknown error while processing adaptive flow";
368
+ const normalized = new Error(message);
369
+ if (typeof maybeError.code === "string" && maybeError.code.trim().length > 0) {
370
+ normalized.name = maybeError.code;
371
+ }
372
+ normalized.cause = error;
373
+ return normalized;
374
+ }
375
+ return new Error(`Unknown error while processing adaptive flow: ${String(error)}`);
376
+ }
377
+ function sleep(ms) {
378
+ return new Promise((resolve) => {
379
+ setTimeout(resolve, ms);
380
+ });
381
+ }
382
+ function normalizeDelay(delay, fallback) {
383
+ if (typeof delay !== "number" || Number.isNaN(delay) || delay < 0) {
384
+ return fallback;
385
+ }
386
+ return delay;
387
+ }
388
+ function computeRetryDelay(policy, attempt) {
389
+ if (policy?.delay) {
390
+ return normalizeDelay(policy.delay(attempt), 0);
391
+ }
392
+ const initialDelayMs = normalizeDelay(policy?.initialDelayMs, 250);
393
+ const factor = typeof policy?.factor === "number" && policy.factor > 0 ? policy.factor : 2;
394
+ const maxDelayMs = normalizeDelay(policy?.maxDelayMs, Number.POSITIVE_INFINITY);
395
+ let delay = initialDelayMs * Math.pow(factor, Math.max(0, attempt - 1));
396
+ if (policy?.jitter) {
397
+ delay = delay * (0.5 + Math.random() * 0.5);
398
+ }
399
+ return Math.min(delay, maxDelayMs);
400
+ }
401
+ async function withRetry(operation, retryPolicy) {
402
+ if (!retryPolicy) {
403
+ return operation();
404
+ }
405
+ const maxAttempts = Math.max(1, Math.trunc(retryPolicy.maxAttempts ?? 3));
406
+ let lastError;
407
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
408
+ try {
409
+ return await operation();
410
+ } catch (error) {
411
+ lastError = error;
412
+ const normalized = toError(error);
413
+ const shouldRetry = retryPolicy.shouldRetry?.(normalized, attempt) ?? attempt < maxAttempts;
414
+ if (!shouldRetry || attempt === maxAttempts) {
415
+ throw normalized;
416
+ }
417
+ await sleep(computeRetryDelay(retryPolicy, attempt));
418
+ }
419
+ }
420
+ throw toError(lastError);
242
421
  }
243
422
  function cx(...names) {
244
423
  const value = names.filter(Boolean).join(" ").trim();
@@ -292,10 +471,78 @@ function clearPersistedState(persistence) {
292
471
  }
293
472
  storage.removeItem(persistence.key);
294
473
  }
295
- async function assertValid(result) {
296
- const message = await result;
297
- if (typeof message === "string" && message.trim().length > 0) {
298
- throw new Error(message);
474
+ var FlowValidationError = class extends Error {
475
+ constructor(message, fieldErrors) {
476
+ super(message);
477
+ this.name = "FlowValidationError";
478
+ this.fieldErrors = fieldErrors;
479
+ }
480
+ };
481
+ function toValidationError(issue, fallbackField) {
482
+ const field = issue.field ?? fallbackField;
483
+ if (field) {
484
+ return new FlowValidationError(issue.message, { [field]: issue.message });
485
+ }
486
+ return new FlowValidationError(issue.message, {});
487
+ }
488
+ function normalizeSchemaIssues(error, fallbackField) {
489
+ const fieldErrors = {};
490
+ const issues = error?.issues ?? [];
491
+ for (const issue of issues) {
492
+ const path = issue.path?.length ? issue.path.map(String).join(".") : fallbackField;
493
+ const message = issue.message?.trim() || error?.message || "Validation failed.";
494
+ if (path && !fieldErrors[path]) {
495
+ fieldErrors[path] = message;
496
+ }
497
+ }
498
+ if (Object.keys(fieldErrors).length === 0 && fallbackField) {
499
+ fieldErrors[fallbackField] = error?.message || "Validation failed.";
500
+ }
501
+ return fieldErrors;
502
+ }
503
+ async function assertValid(result, fallbackField) {
504
+ const outcome = await result;
505
+ if (!outcome) {
506
+ return;
507
+ }
508
+ if (typeof outcome === "string") {
509
+ const message = outcome.trim();
510
+ if (message.length > 0) {
511
+ throw new FlowValidationError(message, fallbackField ? { [fallbackField]: message } : {});
512
+ }
513
+ return;
514
+ }
515
+ if (outcome.message.trim().length > 0) {
516
+ throw toValidationError(outcome, fallbackField);
517
+ }
518
+ }
519
+ async function assertSchema(schema, value, fallbackField) {
520
+ if (!schema) {
521
+ return;
522
+ }
523
+ if (schema.safeParse) {
524
+ const result = schema.safeParse(value);
525
+ if (!result.success) {
526
+ const fieldErrors = normalizeSchemaIssues(result.error, fallbackField);
527
+ throw new FlowValidationError(result.error?.message || "Validation failed.", fieldErrors);
528
+ }
529
+ return;
530
+ }
531
+ if (!schema.parse) {
532
+ return;
533
+ }
534
+ try {
535
+ schema.parse(value);
536
+ } catch (error) {
537
+ const normalized = error;
538
+ const fieldErrors = normalizeSchemaIssues(
539
+ {
540
+ message: normalized?.message,
541
+ issues: normalized?.issues
542
+ },
543
+ fallbackField
544
+ );
545
+ throw new FlowValidationError(normalized?.message || "Validation failed.", fieldErrors);
299
546
  }
300
547
  }
301
548
  function resolveStyles(unstyled, styleOverrides) {
@@ -312,26 +559,22 @@ function resolveStyles(unstyled, styleOverrides) {
312
559
  }
313
560
  return resolved;
314
561
  }
315
- function AdaptiveFlow({
562
+ function useAdaptiveFlow({
316
563
  adapter,
317
564
  requirements,
318
565
  requirementGraph,
319
566
  requirementGraphConfig,
320
567
  requirementResolvers,
321
568
  completeStep,
322
- stepTitles,
323
- renderStep,
324
- stepRegistry,
325
569
  initialValue,
326
570
  onComplete,
327
571
  onError,
328
572
  onStepTransition,
329
- className,
330
- classNames,
331
- styles,
332
- unstyled = false,
333
573
  persistence,
334
- validators
574
+ validators,
575
+ schemas,
576
+ oauthProviders,
577
+ retryPolicy
335
578
  }) {
336
579
  const normalizedRequirements = React.useMemo(
337
580
  () => requirements ?? defaultRequirements,
@@ -365,20 +608,68 @@ function AdaptiveFlow({
365
608
  requirementGraphConfig?.dependencies
366
609
  ]
367
610
  );
368
- const uiStyles = React.useMemo(() => resolveStyles(unstyled, styles), [unstyled, styles]);
611
+ const runtimeReducer = (state, action) => {
612
+ switch (action.type) {
613
+ case "evaluated":
614
+ return {
615
+ ...state,
616
+ step: action.step,
617
+ missingRequirements: action.missingRequirements,
618
+ transitions: [...state.transitions, action.transition].slice(-100)
619
+ };
620
+ case "set_busy":
621
+ return { ...state, busy: action.busy };
622
+ case "set_message":
623
+ return { ...state, message: action.message };
624
+ case "set_error":
625
+ return { ...state, errorMessage: action.errorMessage };
626
+ case "set_field_errors":
627
+ return { ...state, fieldErrors: action.fieldErrors };
628
+ case "start_job":
629
+ return { ...state, busy: true, errorMessage: null, fieldErrors: {} };
630
+ case "set_oauth_pending":
631
+ return { ...state, oauthPendingProvider: action.provider };
632
+ case "set_hydrated":
633
+ return { ...state, persistenceHydrated: action.hydrated };
634
+ default:
635
+ return state;
636
+ }
637
+ };
369
638
  const [context, setContext] = React.useState(() => withDefaults(initialValue));
370
- const [step, setStep] = React.useState(normalizedCompleteStep);
371
- const [missingRequirements, setMissingRequirements] = React.useState([]);
372
- const [transitions, setTransitions] = React.useState([]);
373
- const [busy, setBusy] = React.useState(false);
374
- const [message, setMessage] = React.useState(null);
375
- const [errorMessage, setErrorMessage] = React.useState(null);
376
- const [oauthPendingProvider, setOauthPendingProvider] = React.useState(null);
377
- const [persistenceHydrated, setPersistenceHydrated] = React.useState(!persistence);
639
+ const [runtime, dispatch] = React.useReducer(runtimeReducer, {
640
+ step: normalizedCompleteStep,
641
+ missingRequirements: [],
642
+ transitions: [],
643
+ busy: false,
644
+ message: null,
645
+ errorMessage: null,
646
+ fieldErrors: {},
647
+ oauthPendingProvider: null,
648
+ persistenceHydrated: !persistence
649
+ });
650
+ const {
651
+ step,
652
+ missingRequirements,
653
+ transitions,
654
+ busy,
655
+ message,
656
+ errorMessage,
657
+ fieldErrors,
658
+ oauthPendingProvider,
659
+ persistenceHydrated
660
+ } = runtime;
378
661
  const attemptByStepRef = React.useRef({});
379
662
  const previousStepRef = React.useRef(null);
380
663
  const evaluationRef = React.useRef(0);
381
664
  const completed = React.useRef(false);
665
+ const reportPersistenceError = React.useCallback(
666
+ (error, phase) => {
667
+ const normalized = toError(error);
668
+ persistence?.onError?.(normalized, phase);
669
+ onError?.(normalized);
670
+ },
671
+ [onError, persistence]
672
+ );
382
673
  React.useEffect(() => {
383
674
  if (!persistence) {
384
675
  return;
@@ -389,26 +680,24 @@ function AdaptiveFlow({
389
680
  setContext(mergeContext(withDefaults(initialValue), persisted.context));
390
681
  }
391
682
  if (persisted?.oauthPendingProvider) {
392
- setOauthPendingProvider(persisted.oauthPendingProvider);
683
+ dispatch({ type: "set_oauth_pending", provider: persisted.oauthPendingProvider });
393
684
  }
394
- } catch {
685
+ } catch (error) {
686
+ reportPersistenceError(error, "read");
395
687
  } finally {
396
- setPersistenceHydrated(true);
688
+ dispatch({ type: "set_hydrated", hydrated: true });
397
689
  }
398
- }, [initialValue, persistence]);
690
+ }, [initialValue, persistence, reportPersistenceError]);
399
691
  React.useEffect(() => {
400
- let isCancelled = false;
401
692
  const currentEvaluation = ++evaluationRef.current;
402
693
  void (async () => {
403
- const [missing2, next] = await Promise.all([
694
+ const [missing, next] = await Promise.all([
404
695
  getMissingRequirements(context, graph),
405
696
  evaluateNextStep(context, graph, normalizedCompleteStep)
406
697
  ]);
407
- if (isCancelled || currentEvaluation !== evaluationRef.current) {
698
+ if (currentEvaluation !== evaluationRef.current) {
408
699
  return;
409
700
  }
410
- setMissingRequirements(missing2);
411
- setStep(next);
412
701
  const from = previousStepRef.current;
413
702
  const attemptKey = String(next);
414
703
  const nextAttempt = from === next ? (attemptByStepRef.current[attemptKey] ?? 0) + 1 : 1;
@@ -419,20 +708,23 @@ function AdaptiveFlow({
419
708
  at: Date.now(),
420
709
  attempt: nextAttempt
421
710
  };
422
- setTransitions((previous) => [...previous, transition].slice(-100));
711
+ dispatch({
712
+ type: "evaluated",
713
+ missingRequirements: missing,
714
+ step: next,
715
+ transition
716
+ });
423
717
  previousStepRef.current = next;
424
718
  onStepTransition?.(transition, context);
425
719
  })().catch((error) => {
426
- if (isCancelled || currentEvaluation !== evaluationRef.current) {
720
+ if (currentEvaluation !== evaluationRef.current) {
427
721
  return;
428
722
  }
429
723
  const normalized = toError(error);
430
- setErrorMessage(normalized.message);
724
+ dispatch({ type: "set_field_errors", fieldErrors: {} });
725
+ dispatch({ type: "set_error", errorMessage: normalized.message });
431
726
  onError?.(normalized);
432
727
  });
433
- return () => {
434
- isCancelled = true;
435
- };
436
728
  }, [context, graph, normalizedCompleteStep, onError, onStepTransition]);
437
729
  React.useEffect(() => {
438
730
  if (step === normalizedCompleteStep) {
@@ -441,34 +733,46 @@ function AdaptiveFlow({
441
733
  onComplete?.(context);
442
734
  const shouldClearPersistence = persistence?.clearOnComplete ?? true;
443
735
  if (shouldClearPersistence) {
444
- clearPersistedState(persistence);
736
+ try {
737
+ clearPersistedState(persistence);
738
+ } catch (error) {
739
+ reportPersistenceError(error, "clear");
740
+ }
445
741
  }
446
742
  }
447
743
  } else {
448
744
  completed.current = false;
449
745
  }
450
- }, [context, normalizedCompleteStep, onComplete, persistence, step]);
746
+ }, [context, normalizedCompleteStep, onComplete, persistence, reportPersistenceError, step]);
451
747
  React.useEffect(() => {
452
748
  if (!persistence || !persistenceHydrated) {
453
749
  return;
454
750
  }
455
751
  try {
456
752
  writePersistedState(persistence, { context, oauthPendingProvider });
457
- } catch {
753
+ } catch (error) {
754
+ reportPersistenceError(error, "write");
458
755
  }
459
- }, [context, oauthPendingProvider, persistence, persistenceHydrated]);
756
+ }, [context, oauthPendingProvider, persistence, persistenceHydrated, reportPersistenceError]);
460
757
  const run = React.useCallback(
461
758
  async (job) => {
462
- setBusy(true);
463
- setErrorMessage(null);
759
+ dispatch({ type: "start_job" });
464
760
  try {
465
761
  await job();
466
762
  } catch (error) {
467
- const normalized = toError(error);
468
- setErrorMessage(normalized.message);
469
- onError?.(normalized);
763
+ if (error instanceof FlowValidationError) {
764
+ dispatch({ type: "set_field_errors", fieldErrors: error.fieldErrors });
765
+ if (Object.keys(error.fieldErrors).length === 0) {
766
+ dispatch({ type: "set_error", errorMessage: error.message });
767
+ onError?.(error);
768
+ }
769
+ } else {
770
+ const normalized = toError(error);
771
+ dispatch({ type: "set_error", errorMessage: normalized.message });
772
+ onError?.(normalized);
773
+ }
470
774
  } finally {
471
- setBusy(false);
775
+ dispatch({ type: "set_busy", busy: false });
472
776
  }
473
777
  },
474
778
  [onError]
@@ -476,37 +780,35 @@ function AdaptiveFlow({
476
780
  const patchContext = React.useCallback((patch) => {
477
781
  setContext((prev) => mergeContext(prev, patch));
478
782
  }, []);
479
- const patchBaseContext = React.useCallback(
480
- (patch) => {
481
- patchContext(patch);
482
- },
483
- [patchContext]
484
- );
485
783
  React.useEffect(() => {
486
784
  const completeOAuth = adapter?.completeOAuth;
487
785
  if (!oauthPendingProvider || !completeOAuth) {
488
786
  return;
489
787
  }
490
788
  void run(async () => {
491
- const patch = await completeOAuth(oauthPendingProvider, context);
789
+ const patch = await withRetry(
790
+ () => completeOAuth(oauthPendingProvider, context),
791
+ retryPolicy
792
+ );
492
793
  if (patch) {
493
794
  patchContext(patch);
494
795
  }
495
- setOauthPendingProvider(null);
496
- setMessage("OAuth sign-in completed.");
796
+ dispatch({ type: "set_oauth_pending", provider: null });
797
+ dispatch({ type: "set_message", message: "OAuth sign-in completed." });
497
798
  });
498
- }, [adapter, context, oauthPendingProvider, patchContext, run]);
799
+ }, [adapter, context, oauthPendingProvider, patchContext, retryPolicy, run]);
499
800
  const handleEmail = (emailInput) => {
500
801
  const email = emailInput.trim().toLowerCase();
501
802
  if (!email) {
502
803
  return;
503
804
  }
504
805
  void run(async () => {
806
+ await assertSchema(schemas?.email, email, "email");
505
807
  if (validators?.email) {
506
- await assertValid(validators.email(email, { context }));
808
+ await assertValid(validators.email(email, { context }), "email");
507
809
  }
508
- const identity = await adapter?.lookupByEmail?.(email) ?? null;
509
- patchBaseContext({
810
+ const identity = adapter?.lookupByEmail ? await withRetry(() => adapter.lookupByEmail(email), retryPolicy) : null;
811
+ patchContext({
510
812
  email,
511
813
  hasPassword: Boolean(identity?.hasPassword),
512
814
  isVerified: Boolean(identity?.isVerified),
@@ -518,15 +820,23 @@ function AdaptiveFlow({
518
820
  }
519
821
  });
520
822
  if (identity?.accountExists && identity.hasPassword) {
521
- setMessage("Welcome back. Enter your password to continue.");
823
+ dispatch({ type: "set_message", message: "Welcome back. Enter your password to continue." });
522
824
  return;
523
825
  }
524
826
  if (adapter?.requestOtp) {
525
- await adapter.requestOtp(email);
526
- setMessage("We sent a 6-digit code to your inbox.");
827
+ await withRetry(() => adapter.requestOtp(email), retryPolicy);
828
+ dispatch({ type: "set_message", message: "We sent a 6-digit code to your inbox." });
527
829
  } else {
528
- patchBaseContext({ isVerified: true });
529
- setMessage("No OTP adapter configured. Email verification was skipped.");
830
+ const env = globalThis.process?.env?.NODE_ENV;
831
+ const isDev = env !== "production";
832
+ if (!isDev) {
833
+ throw new Error("OTP adapter is required in production. Provide adapter.requestOtp.");
834
+ }
835
+ patchContext({ isVerified: true });
836
+ dispatch({
837
+ type: "set_message",
838
+ message: "No OTP adapter configured. Verification was skipped in development mode."
839
+ });
530
840
  }
531
841
  });
532
842
  };
@@ -535,14 +845,15 @@ function AdaptiveFlow({
535
845
  return;
536
846
  }
537
847
  void run(async () => {
848
+ await assertSchema(schemas?.otp, code, "otp");
538
849
  if (validators?.otp) {
539
- await assertValid(validators.otp(code, { context, email: context.email }));
850
+ await assertValid(validators.otp(code, { context, email: context.email }), "otp");
540
851
  }
541
852
  if (adapter?.verifyOtp) {
542
- await adapter.verifyOtp(context.email, code);
853
+ await withRetry(() => adapter.verifyOtp(context.email, code), retryPolicy);
543
854
  }
544
- patchBaseContext({ isVerified: true });
545
- setMessage("Email verified.");
855
+ patchContext({ isVerified: true });
856
+ dispatch({ type: "set_message", message: "Email verified." });
546
857
  });
547
858
  };
548
859
  const handlePassword = (password) => {
@@ -550,26 +861,34 @@ function AdaptiveFlow({
550
861
  return;
551
862
  }
552
863
  void run(async () => {
864
+ await assertSchema(schemas?.password, password, "password");
553
865
  if (validators?.password) {
554
- await assertValid(validators.password(password, { context, hasPassword: context.hasPassword }));
866
+ await assertValid(
867
+ validators.password(password, { context, hasPassword: context.hasPassword }),
868
+ "password"
869
+ );
555
870
  }
556
871
  if (context.hasPassword) {
557
872
  if (adapter?.signInWithPassword) {
558
- await adapter.signInWithPassword(context.email, password);
873
+ await withRetry(
874
+ () => adapter.signInWithPassword(context.email, password),
875
+ retryPolicy
876
+ );
559
877
  }
560
878
  } else {
561
879
  if (adapter?.createPassword) {
562
- await adapter.createPassword(password);
880
+ await withRetry(() => adapter.createPassword(password), retryPolicy);
563
881
  }
564
- patchBaseContext({ hasPassword: true });
882
+ patchContext({ hasPassword: true });
565
883
  }
566
- setMessage("Password step complete.");
884
+ dispatch({ type: "set_message", message: "Password step complete." });
567
885
  });
568
886
  };
569
887
  const handleProfile = (profile) => {
570
888
  void run(async () => {
889
+ await assertSchema(schemas?.profile, profile, "profile");
571
890
  if (validators?.profile) {
572
- await assertValid(validators.profile(profile, { context }));
891
+ await assertValid(validators.profile(profile, { context }), "profile");
573
892
  }
574
893
  const next = mergeContext(context, {
575
894
  profile: {
@@ -579,23 +898,24 @@ function AdaptiveFlow({
579
898
  }
580
899
  });
581
900
  if (adapter?.saveProfile) {
582
- await adapter.saveProfile(next);
901
+ await withRetry(() => adapter.saveProfile(next), retryPolicy);
583
902
  }
584
903
  patchContext({ profile: next.profile });
585
- setMessage("Profile saved.");
904
+ dispatch({ type: "set_message", message: "Profile saved." });
586
905
  });
587
906
  };
588
907
  const handleTos = () => {
589
908
  void run(async () => {
909
+ await assertSchema(schemas?.tos, true, "tos");
590
910
  if (validators?.tos) {
591
- await assertValid(validators.tos(true, { context }));
911
+ await assertValid(validators.tos(true, { context }), "tos");
592
912
  }
593
913
  const next = mergeContext(context, { agreedToTos: true });
594
914
  if (adapter?.acceptTos) {
595
- await adapter.acceptTos(next);
915
+ await withRetry(() => adapter.acceptTos(next), retryPolicy);
596
916
  }
597
- patchBaseContext({ agreedToTos: true });
598
- setMessage("Terms accepted.");
917
+ patchContext({ agreedToTos: true });
918
+ dispatch({ type: "set_message", message: "Terms accepted." });
599
919
  });
600
920
  };
601
921
  const handleOAuth = (provider) => {
@@ -604,12 +924,97 @@ function AdaptiveFlow({
604
924
  return;
605
925
  }
606
926
  void run(async () => {
607
- setOauthPendingProvider(provider);
608
- setMessage(`Starting ${provider} sign-in...`);
609
- await startOAuth(provider, context);
927
+ dispatch({ type: "set_oauth_pending", provider });
928
+ dispatch({ type: "set_message", message: `Starting ${provider} sign-in...` });
929
+ await withRetry(() => startOAuth(provider, context), retryPolicy);
610
930
  });
611
931
  };
612
- const missing = missingRequirements;
932
+ return {
933
+ context,
934
+ step,
935
+ completeStep: normalizedCompleteStep,
936
+ requirements: normalizedRequirements,
937
+ missingRequirements,
938
+ transitions,
939
+ busy,
940
+ message,
941
+ errorMessage,
942
+ fieldErrors,
943
+ setContextPatch: patchContext,
944
+ run,
945
+ handleEmail,
946
+ handleOtp,
947
+ handlePassword,
948
+ handleProfile,
949
+ handleTos,
950
+ handleOAuth
951
+ };
952
+ }
953
+ function AdaptiveFlow({
954
+ adapter,
955
+ requirements,
956
+ requirementGraph,
957
+ requirementGraphConfig,
958
+ requirementResolvers,
959
+ completeStep,
960
+ stepTitles,
961
+ renderStep,
962
+ stepRegistry,
963
+ initialValue,
964
+ onComplete,
965
+ onError,
966
+ onStepTransition,
967
+ className,
968
+ classNames,
969
+ styles,
970
+ unstyled = false,
971
+ persistence,
972
+ validators,
973
+ schemas,
974
+ oauthProviders,
975
+ retryPolicy
976
+ }) {
977
+ const uiStyles = React.useMemo(() => resolveStyles(unstyled, styles), [unstyled, styles]);
978
+ const {
979
+ context,
980
+ step,
981
+ completeStep: normalizedCompleteStep,
982
+ requirements: normalizedRequirements,
983
+ missingRequirements: missing,
984
+ transitions,
985
+ busy,
986
+ message,
987
+ errorMessage,
988
+ fieldErrors,
989
+ setContextPatch: patchContext,
990
+ run,
991
+ handleEmail,
992
+ handleOtp,
993
+ handlePassword,
994
+ handleProfile,
995
+ handleTos,
996
+ handleOAuth
997
+ } = useAdaptiveFlow({
998
+ adapter,
999
+ requirements,
1000
+ requirementGraph,
1001
+ requirementGraphConfig,
1002
+ requirementResolvers,
1003
+ completeStep,
1004
+ initialValue,
1005
+ onComplete,
1006
+ onError,
1007
+ onStepTransition,
1008
+ persistence,
1009
+ validators,
1010
+ schemas,
1011
+ oauthProviders,
1012
+ retryPolicy
1013
+ });
1014
+ const normalizedOAuthProviders = React.useMemo(
1015
+ () => oauthProviders && oauthProviders.length > 0 ? oauthProviders : defaultOAuthProviders,
1016
+ [oauthProviders]
1017
+ );
613
1018
  const needsJobTitle = normalizedRequirements.includes("has_job_title");
614
1019
  const stepLabel = stepTitles?.[step] ?? defaultStepTitle[step] ?? step;
615
1020
  const defaultView = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
@@ -618,6 +1023,7 @@ function AdaptiveFlow({
618
1023
  {
619
1024
  onSubmit: handleEmail,
620
1025
  disabled: busy,
1026
+ error: fieldErrors.email,
621
1027
  styles: uiStyles,
622
1028
  classNames
623
1029
  }
@@ -628,6 +1034,7 @@ function AdaptiveFlow({
628
1034
  onSubmit: handleOtp,
629
1035
  email: context.email ?? "your email",
630
1036
  disabled: busy,
1037
+ error: fieldErrors.otp,
631
1038
  styles: uiStyles,
632
1039
  classNames
633
1040
  }
@@ -638,6 +1045,7 @@ function AdaptiveFlow({
638
1045
  onSubmit: handlePassword,
639
1046
  disabled: busy,
640
1047
  hasPassword: context.hasPassword,
1048
+ error: fieldErrors.password,
641
1049
  styles: uiStyles,
642
1050
  classNames
643
1051
  }
@@ -649,6 +1057,7 @@ function AdaptiveFlow({
649
1057
  requireJobTitle: needsJobTitle,
650
1058
  onSubmit: handleProfile,
651
1059
  disabled: busy,
1060
+ errors: fieldErrors,
652
1061
  styles: uiStyles,
653
1062
  classNames
654
1063
  }
@@ -658,12 +1067,13 @@ function AdaptiveFlow({
658
1067
  {
659
1068
  onSubmit: handleTos,
660
1069
  disabled: busy,
1070
+ error: fieldErrors.tos,
661
1071
  styles: uiStyles,
662
1072
  classNames
663
1073
  }
664
1074
  ) : null,
665
1075
  step === normalizedCompleteStep ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CompleteBlock, { styles: uiStyles, classNames }) : null,
666
- step !== "COLLECT_EMAIL" && step !== "VERIFY_OTP" && step !== "COLLECT_PASSWORD" && step !== "COLLECT_PROFILE" && step !== "COLLECT_TOS" && step !== normalizedCompleteStep ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: classNames?.info, style: uiStyles.info, children: [
1076
+ !builtInDefaultSteps.has(String(step)) && step !== normalizedCompleteStep ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: classNames?.info, style: uiStyles.info, children: [
667
1077
  'No default renderer for step "',
668
1078
  step,
669
1079
  '". Provide renderStep to handle custom steps.'
@@ -675,6 +1085,7 @@ function AdaptiveFlow({
675
1085
  busy,
676
1086
  message,
677
1087
  errorMessage,
1088
+ fieldErrors,
678
1089
  missingRequirements: missing,
679
1090
  requirements: normalizedRequirements,
680
1091
  defaultView,
@@ -689,6 +1100,7 @@ function AdaptiveFlow({
689
1100
  busy,
690
1101
  message,
691
1102
  errorMessage,
1103
+ fieldErrors,
692
1104
  missingRequirements: missing,
693
1105
  requirements: normalizedRequirements,
694
1106
  setContextPatch: patchContext,
@@ -711,38 +1123,31 @@ function AdaptiveFlow({
711
1123
  message ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: classNames?.success, style: uiStyles.success, children: message }) : null,
712
1124
  errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: classNames?.error, style: uiStyles.error, children: errorMessage }) : null,
713
1125
  customView ?? registryView ?? defaultView,
714
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: classNames?.footer, style: uiStyles.footer, children: [
715
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
716
- "button",
717
- {
718
- type: "button",
719
- className: classNames?.oauthButton,
720
- style: uiStyles.oauthButton,
721
- disabled: busy || !adapter?.startOAuth,
722
- onClick: () => {
723
- handleOAuth("google");
724
- },
725
- children: "Continue with Google"
726
- }
727
- ),
728
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
729
- "button",
730
- {
731
- type: "button",
732
- className: classNames?.oauthButton,
733
- style: uiStyles.oauthButton,
734
- disabled: busy || !adapter?.startOAuth,
735
- onClick: () => {
736
- handleOAuth("apple");
737
- },
738
- children: "Continue with Apple"
739
- }
740
- )
741
- ] })
1126
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: classNames?.footer, style: uiStyles.footer, children: normalizedOAuthProviders.map((provider) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1127
+ "button",
1128
+ {
1129
+ type: "button",
1130
+ className: classNames?.oauthButton,
1131
+ style: uiStyles.oauthButton,
1132
+ disabled: busy || !adapter?.startOAuth,
1133
+ onClick: () => {
1134
+ handleOAuth(provider.id);
1135
+ },
1136
+ children: provider.label
1137
+ },
1138
+ provider.id
1139
+ )) })
742
1140
  ] });
743
1141
  }
744
- function EmailBlock({ onSubmit, disabled, styles, classNames }) {
1142
+ function EmailBlock({
1143
+ onSubmit,
1144
+ disabled,
1145
+ error,
1146
+ styles,
1147
+ classNames
1148
+ }) {
745
1149
  const [email, setEmail] = React.useState("");
1150
+ const errorId = "adaptive-flow-email-error";
746
1151
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
747
1152
  "form",
748
1153
  {
@@ -763,10 +1168,13 @@ function EmailBlock({ onSubmit, disabled, styles, classNames }) {
763
1168
  placeholder: "Enter your email",
764
1169
  value: email,
765
1170
  onChange: (event) => setEmail(event.target.value),
1171
+ "aria-invalid": Boolean(error),
1172
+ "aria-describedby": error ? errorId : void 0,
766
1173
  required: true
767
1174
  }
768
1175
  ),
769
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: classNames?.button, style: styles.button, disabled, type: "submit", children: "Continue" })
1176
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: classNames?.button, style: styles.button, disabled, type: "submit", children: "Continue" }),
1177
+ error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { id: errorId, className: classNames?.error, style: styles.error, children: error }) : null
770
1178
  ]
771
1179
  }
772
1180
  );
@@ -775,10 +1183,12 @@ function OtpBlock({
775
1183
  onSubmit,
776
1184
  disabled,
777
1185
  email,
1186
+ error,
778
1187
  styles,
779
1188
  classNames
780
1189
  }) {
781
1190
  const [code, setCode] = React.useState("");
1191
+ const errorId = "adaptive-flow-otp-error";
782
1192
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
783
1193
  "form",
784
1194
  {
@@ -804,6 +1214,8 @@ function OtpBlock({
804
1214
  placeholder: "Enter 6-digit code",
805
1215
  value: code,
806
1216
  onChange: (event) => setCode(event.target.value.replace(/\D/g, "").slice(0, 6)),
1217
+ "aria-invalid": Boolean(error),
1218
+ "aria-describedby": error ? errorId : void 0,
807
1219
  required: true,
808
1220
  maxLength: 6,
809
1221
  pattern: "[0-9]{6}"
@@ -818,7 +1230,8 @@ function OtpBlock({
818
1230
  type: "submit",
819
1231
  children: "Verify"
820
1232
  }
821
- )
1233
+ ),
1234
+ error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { id: errorId, className: classNames?.error, style: styles.error, children: error }) : null
822
1235
  ] })
823
1236
  ]
824
1237
  }
@@ -828,10 +1241,12 @@ function PasswordBlock({
828
1241
  onSubmit,
829
1242
  disabled,
830
1243
  hasPassword,
1244
+ error,
831
1245
  styles,
832
1246
  classNames
833
1247
  }) {
834
1248
  const [password, setPassword] = React.useState("");
1249
+ const errorId = "adaptive-flow-password-error";
835
1250
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
836
1251
  "form",
837
1252
  {
@@ -852,11 +1267,14 @@ function PasswordBlock({
852
1267
  placeholder: hasPassword ? "Enter your password" : "Create a password",
853
1268
  value: password,
854
1269
  onChange: (event) => setPassword(event.target.value),
1270
+ "aria-invalid": Boolean(error),
1271
+ "aria-describedby": error ? errorId : void 0,
855
1272
  required: true,
856
1273
  minLength: 8
857
1274
  }
858
1275
  ),
859
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: classNames?.button, style: styles.button, disabled, type: "submit", children: "Continue" })
1276
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: classNames?.button, style: styles.button, disabled, type: "submit", children: "Continue" }),
1277
+ error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { id: errorId, className: classNames?.error, style: styles.error, children: error }) : null
860
1278
  ]
861
1279
  }
862
1280
  );
@@ -866,12 +1284,17 @@ function ProfileBlock({
866
1284
  disabled,
867
1285
  defaultValue,
868
1286
  requireJobTitle,
1287
+ errors,
869
1288
  styles,
870
1289
  classNames
871
1290
  }) {
872
1291
  const [firstName, setFirstName] = React.useState(defaultValue.firstName ?? "");
873
1292
  const [lastName, setLastName] = React.useState(defaultValue.lastName ?? "");
874
1293
  const [jobTitle, setJobTitle] = React.useState(defaultValue.jobTitle ?? "");
1294
+ const firstNameError = errors?.firstName ?? errors?.["profile.firstName"];
1295
+ const lastNameError = errors?.lastName ?? errors?.["profile.lastName"];
1296
+ const jobTitleError = errors?.jobTitle ?? errors?.["profile.jobTitle"];
1297
+ const profileError = errors?.profile;
875
1298
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
876
1299
  "form",
877
1300
  {
@@ -897,6 +1320,7 @@ function ProfileBlock({
897
1320
  placeholder: "First name",
898
1321
  value: firstName,
899
1322
  onChange: (event) => setFirstName(event.target.value),
1323
+ "aria-invalid": Boolean(firstNameError),
900
1324
  required: true
901
1325
  }
902
1326
  ),
@@ -910,23 +1334,31 @@ function ProfileBlock({
910
1334
  placeholder: "Last name",
911
1335
  value: lastName,
912
1336
  onChange: (event) => setLastName(event.target.value),
1337
+ "aria-invalid": Boolean(lastNameError),
913
1338
  required: true
914
1339
  }
915
1340
  )
916
1341
  ] }),
917
- requireJobTitle ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
918
- "input",
919
- {
920
- className: classNames?.input,
921
- style: styles.input,
922
- type: "text",
923
- autoComplete: "organization-title",
924
- placeholder: "Job title",
925
- value: jobTitle,
926
- onChange: (event) => setJobTitle(event.target.value),
927
- required: true
928
- }
929
- ) : null,
1342
+ firstNameError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: classNames?.error, style: styles.error, children: firstNameError }) : null,
1343
+ lastNameError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: classNames?.error, style: styles.error, children: lastNameError }) : null,
1344
+ requireJobTitle ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1345
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1346
+ "input",
1347
+ {
1348
+ className: classNames?.input,
1349
+ style: styles.input,
1350
+ type: "text",
1351
+ autoComplete: "organization-title",
1352
+ placeholder: "Job title",
1353
+ value: jobTitle,
1354
+ onChange: (event) => setJobTitle(event.target.value),
1355
+ "aria-invalid": Boolean(jobTitleError),
1356
+ required: true
1357
+ }
1358
+ ),
1359
+ jobTitleError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: classNames?.error, style: styles.error, children: jobTitleError }) : null
1360
+ ] }) : null,
1361
+ profileError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: classNames?.error, style: styles.error, children: profileError }) : null,
930
1362
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: classNames?.button, style: styles.button, disabled, type: "submit", children: "Continue" })
931
1363
  ]
932
1364
  }
@@ -935,6 +1367,7 @@ function ProfileBlock({
935
1367
  function TosBlock({
936
1368
  onSubmit,
937
1369
  disabled,
1370
+ error,
938
1371
  styles,
939
1372
  classNames
940
1373
  }) {
@@ -952,9 +1385,18 @@ function TosBlock({
952
1385
  },
953
1386
  children: [
954
1387
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: classNames?.checkboxRow, style: styles.checkboxRow, children: [
955
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked, onChange: (event) => setChecked(event.target.checked) }),
1388
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1389
+ "input",
1390
+ {
1391
+ type: "checkbox",
1392
+ checked,
1393
+ onChange: (event) => setChecked(event.target.checked),
1394
+ "aria-invalid": Boolean(error)
1395
+ }
1396
+ ),
956
1397
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "I agree to the Terms of Service and Privacy Policy." })
957
1398
  ] }),
1399
+ error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: classNames?.error, style: styles.error, children: error }) : null,
958
1400
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
959
1401
  "button",
960
1402
  {
@@ -974,7 +1416,7 @@ function CompleteBlock({
974
1416
  classNames
975
1417
  }) {
976
1418
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: classNames?.complete, style: styles.complete, children: [
977
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "You are fully authenticated." }),
1419
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "You are all set." }),
978
1420
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: classNames?.caption, style: styles.caption, children: "All requirements are complete." })
979
1421
  ] });
980
1422
  }
@@ -1113,6 +1555,7 @@ var defaultStyles = {
1113
1555
  defaultRequirements,
1114
1556
  evaluateNextStep,
1115
1557
  getMissingRequirements,
1116
- initialContext
1558
+ initialContext,
1559
+ useAdaptiveFlow
1117
1560
  });
1118
1561
  //# sourceMappingURL=index.js.map