@secmia/openui-flow 3.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/README.md +804 -0
- package/dist/index.d.mts +178 -0
- package/dist/index.d.ts +178 -0
- package/dist/index.js +1118 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1073 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +39 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1118 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
|
|
31
|
+
// src/index.ts
|
|
32
|
+
var index_exports = {};
|
|
33
|
+
__export(index_exports, {
|
|
34
|
+
AdaptiveFlow: () => AdaptiveFlow,
|
|
35
|
+
DefaultAdaptiveSteps: () => DefaultAdaptiveSteps,
|
|
36
|
+
DefaultAppRequirements: () => DefaultAppRequirements,
|
|
37
|
+
createDefaultRequirementGraph: () => createDefaultRequirementGraph,
|
|
38
|
+
createRequirementGraph: () => createRequirementGraph,
|
|
39
|
+
defaultRequirementResolvers: () => defaultRequirementResolvers,
|
|
40
|
+
defaultRequirements: () => defaultRequirements,
|
|
41
|
+
evaluateNextStep: () => evaluateNextStep,
|
|
42
|
+
getMissingRequirements: () => getMissingRequirements,
|
|
43
|
+
initialContext: () => initialContext
|
|
44
|
+
});
|
|
45
|
+
module.exports = __toCommonJS(index_exports);
|
|
46
|
+
|
|
47
|
+
// src/AdaptiveFlow.tsx
|
|
48
|
+
var React = __toESM(require("react"));
|
|
49
|
+
|
|
50
|
+
// src/engine.ts
|
|
51
|
+
var DefaultAppRequirements = {
|
|
52
|
+
HAS_EMAIL: "has_email",
|
|
53
|
+
EMAIL_VERIFIED: "email_verified",
|
|
54
|
+
HAS_PASSWORD: "has_password",
|
|
55
|
+
HAS_FIRST_NAME: "has_first_name",
|
|
56
|
+
HAS_LAST_NAME: "has_last_name",
|
|
57
|
+
ACCEPTED_TOS: "accepted_tos",
|
|
58
|
+
HAS_JOB_TITLE: "has_job_title"
|
|
59
|
+
};
|
|
60
|
+
var DefaultAdaptiveSteps = {
|
|
61
|
+
COLLECT_EMAIL: "COLLECT_EMAIL",
|
|
62
|
+
VERIFY_OTP: "VERIFY_OTP",
|
|
63
|
+
COLLECT_PASSWORD: "COLLECT_PASSWORD",
|
|
64
|
+
COLLECT_PROFILE: "COLLECT_PROFILE",
|
|
65
|
+
COLLECT_TOS: "COLLECT_TOS",
|
|
66
|
+
COMPLETE: "COMPLETE"
|
|
67
|
+
};
|
|
68
|
+
var defaultRequirements = [
|
|
69
|
+
DefaultAppRequirements.HAS_EMAIL,
|
|
70
|
+
DefaultAppRequirements.EMAIL_VERIFIED,
|
|
71
|
+
DefaultAppRequirements.HAS_PASSWORD,
|
|
72
|
+
DefaultAppRequirements.HAS_FIRST_NAME,
|
|
73
|
+
DefaultAppRequirements.ACCEPTED_TOS
|
|
74
|
+
];
|
|
75
|
+
var initialContext = {
|
|
76
|
+
email: null,
|
|
77
|
+
isVerified: false,
|
|
78
|
+
hasPassword: false,
|
|
79
|
+
profile: {
|
|
80
|
+
firstName: null,
|
|
81
|
+
lastName: null,
|
|
82
|
+
jobTitle: null
|
|
83
|
+
},
|
|
84
|
+
agreedToTos: false
|
|
85
|
+
};
|
|
86
|
+
var defaultRequirementResolvers = {
|
|
87
|
+
has_email: {
|
|
88
|
+
isMet: (context) => Boolean(context.email),
|
|
89
|
+
step: DefaultAdaptiveSteps.COLLECT_EMAIL
|
|
90
|
+
},
|
|
91
|
+
email_verified: {
|
|
92
|
+
isMet: (context) => context.isVerified,
|
|
93
|
+
step: DefaultAdaptiveSteps.VERIFY_OTP
|
|
94
|
+
},
|
|
95
|
+
has_password: {
|
|
96
|
+
isMet: (context) => context.hasPassword,
|
|
97
|
+
step: DefaultAdaptiveSteps.COLLECT_PASSWORD
|
|
98
|
+
},
|
|
99
|
+
has_first_name: {
|
|
100
|
+
isMet: (context) => Boolean(context.profile.firstName),
|
|
101
|
+
step: DefaultAdaptiveSteps.COLLECT_PROFILE
|
|
102
|
+
},
|
|
103
|
+
has_last_name: {
|
|
104
|
+
isMet: (context) => Boolean(context.profile.lastName),
|
|
105
|
+
step: DefaultAdaptiveSteps.COLLECT_PROFILE
|
|
106
|
+
},
|
|
107
|
+
accepted_tos: {
|
|
108
|
+
isMet: (context) => context.agreedToTos,
|
|
109
|
+
step: DefaultAdaptiveSteps.COLLECT_TOS
|
|
110
|
+
},
|
|
111
|
+
has_job_title: {
|
|
112
|
+
isMet: (context) => Boolean(context.profile.jobTitle),
|
|
113
|
+
step: DefaultAdaptiveSteps.COLLECT_PROFILE
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
function createRequirementGraph(requirements, resolvers, options) {
|
|
117
|
+
const graph = [];
|
|
118
|
+
for (const requirement of requirements) {
|
|
119
|
+
const resolver = resolvers[requirement];
|
|
120
|
+
if (!resolver) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
graph.push({
|
|
124
|
+
requirement,
|
|
125
|
+
step: resolver.step,
|
|
126
|
+
isMet: resolver.isMet,
|
|
127
|
+
when: options?.conditions?.[requirement],
|
|
128
|
+
priority: options?.priorities?.[requirement] ?? 0,
|
|
129
|
+
dependsOn: options?.dependencies?.[requirement] ?? []
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return graph;
|
|
133
|
+
}
|
|
134
|
+
function createDefaultRequirementGraph(options) {
|
|
135
|
+
const requirements = options?.requirements ?? defaultRequirements;
|
|
136
|
+
const resolvers = {
|
|
137
|
+
...defaultRequirementResolvers,
|
|
138
|
+
...options?.resolvers ?? {}
|
|
139
|
+
};
|
|
140
|
+
return createRequirementGraph(requirements, resolvers, {
|
|
141
|
+
priorities: options?.priorities,
|
|
142
|
+
conditions: options?.conditions,
|
|
143
|
+
dependencies: options?.dependencies
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
function sortGraph(graph) {
|
|
147
|
+
return [...graph].sort((left, right) => {
|
|
148
|
+
const byPriority = (right.priority ?? 0) - (left.priority ?? 0);
|
|
149
|
+
if (byPriority !== 0) {
|
|
150
|
+
return byPriority;
|
|
151
|
+
}
|
|
152
|
+
return 0;
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
async function evaluateNextStep(context, graph, completeStep) {
|
|
156
|
+
for (const node of sortGraph(graph)) {
|
|
157
|
+
if (node.when && !await node.when(context)) {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (node.dependsOn && node.dependsOn.length > 0) {
|
|
161
|
+
const prerequisiteNodes = graph.filter(
|
|
162
|
+
(candidate) => node.dependsOn?.includes(candidate.requirement)
|
|
163
|
+
);
|
|
164
|
+
if (prerequisiteNodes.length > 0) {
|
|
165
|
+
const prerequisitesMet = await Promise.all(
|
|
166
|
+
prerequisiteNodes.map(async (candidate) => candidate.isMet(context))
|
|
167
|
+
);
|
|
168
|
+
if (prerequisitesMet.includes(false)) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (!await node.isMet(context)) {
|
|
174
|
+
return node.step;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return completeStep;
|
|
178
|
+
}
|
|
179
|
+
async function getMissingRequirements(context, graph) {
|
|
180
|
+
const missing = [];
|
|
181
|
+
for (const node of sortGraph(graph)) {
|
|
182
|
+
if (node.when && !await node.when(context)) {
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (!await node.isMet(context)) {
|
|
186
|
+
missing.push(node.requirement);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return missing;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// src/AdaptiveFlow.tsx
|
|
193
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
194
|
+
var defaultStepTitle = {
|
|
195
|
+
COLLECT_EMAIL: "Enter your email",
|
|
196
|
+
VERIFY_OTP: "Verify your email",
|
|
197
|
+
COLLECT_PASSWORD: "Set up your password",
|
|
198
|
+
COLLECT_PROFILE: "Complete your profile",
|
|
199
|
+
COLLECT_TOS: "Accept terms",
|
|
200
|
+
COMPLETE: "Done"
|
|
201
|
+
};
|
|
202
|
+
var styleSlots = [
|
|
203
|
+
"shell",
|
|
204
|
+
"headerRow",
|
|
205
|
+
"eyebrow",
|
|
206
|
+
"title",
|
|
207
|
+
"badge",
|
|
208
|
+
"success",
|
|
209
|
+
"error",
|
|
210
|
+
"info",
|
|
211
|
+
"caption",
|
|
212
|
+
"formRow",
|
|
213
|
+
"formColumn",
|
|
214
|
+
"input",
|
|
215
|
+
"button",
|
|
216
|
+
"checkboxRow",
|
|
217
|
+
"complete",
|
|
218
|
+
"footer",
|
|
219
|
+
"oauthButton"
|
|
220
|
+
];
|
|
221
|
+
function mergeContext(current, patch) {
|
|
222
|
+
return {
|
|
223
|
+
...current,
|
|
224
|
+
...patch,
|
|
225
|
+
profile: {
|
|
226
|
+
...current.profile,
|
|
227
|
+
...patch.profile
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function withDefaults(initialValue) {
|
|
232
|
+
if (!initialValue) {
|
|
233
|
+
return initialContext;
|
|
234
|
+
}
|
|
235
|
+
return mergeContext(initialContext, initialValue);
|
|
236
|
+
}
|
|
237
|
+
function toError(error) {
|
|
238
|
+
if (error instanceof Error) {
|
|
239
|
+
return error;
|
|
240
|
+
}
|
|
241
|
+
return new Error("Unknown error while processing adaptive flow");
|
|
242
|
+
}
|
|
243
|
+
function cx(...names) {
|
|
244
|
+
const value = names.filter(Boolean).join(" ").trim();
|
|
245
|
+
return value.length > 0 ? value : void 0;
|
|
246
|
+
}
|
|
247
|
+
function pickStorage(storage) {
|
|
248
|
+
if (typeof window === "undefined") {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
if (!storage || storage === "session") {
|
|
252
|
+
return window.sessionStorage;
|
|
253
|
+
}
|
|
254
|
+
if (storage === "local") {
|
|
255
|
+
return window.localStorage;
|
|
256
|
+
}
|
|
257
|
+
return storage;
|
|
258
|
+
}
|
|
259
|
+
function readPersistedState(persistence) {
|
|
260
|
+
if (!persistence) {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
const storage = pickStorage(persistence.storage);
|
|
264
|
+
if (!storage) {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
const raw = storage.getItem(persistence.key);
|
|
268
|
+
if (!raw) {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
const deserialize = persistence.deserialize ?? ((value) => JSON.parse(value));
|
|
272
|
+
return deserialize(raw);
|
|
273
|
+
}
|
|
274
|
+
function writePersistedState(persistence, state) {
|
|
275
|
+
if (!persistence) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const storage = pickStorage(persistence.storage);
|
|
279
|
+
if (!storage) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const serialize = persistence.serialize ?? ((value) => JSON.stringify(value));
|
|
283
|
+
storage.setItem(persistence.key, serialize(state));
|
|
284
|
+
}
|
|
285
|
+
function clearPersistedState(persistence) {
|
|
286
|
+
if (!persistence) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const storage = pickStorage(persistence.storage);
|
|
290
|
+
if (!storage) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
storage.removeItem(persistence.key);
|
|
294
|
+
}
|
|
295
|
+
async function assertValid(result) {
|
|
296
|
+
const message = await result;
|
|
297
|
+
if (typeof message === "string" && message.trim().length > 0) {
|
|
298
|
+
throw new Error(message);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
function resolveStyles(unstyled, styleOverrides) {
|
|
302
|
+
const resolved = {};
|
|
303
|
+
for (const slot of styleSlots) {
|
|
304
|
+
if (unstyled) {
|
|
305
|
+
resolved[slot] = styleOverrides?.[slot];
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
resolved[slot] = {
|
|
309
|
+
...defaultStyles[slot],
|
|
310
|
+
...styleOverrides?.[slot] ?? {}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
return resolved;
|
|
314
|
+
}
|
|
315
|
+
function AdaptiveFlow({
|
|
316
|
+
adapter,
|
|
317
|
+
requirements,
|
|
318
|
+
requirementGraph,
|
|
319
|
+
requirementGraphConfig,
|
|
320
|
+
requirementResolvers,
|
|
321
|
+
completeStep,
|
|
322
|
+
stepTitles,
|
|
323
|
+
renderStep,
|
|
324
|
+
stepRegistry,
|
|
325
|
+
initialValue,
|
|
326
|
+
onComplete,
|
|
327
|
+
onError,
|
|
328
|
+
onStepTransition,
|
|
329
|
+
className,
|
|
330
|
+
classNames,
|
|
331
|
+
styles,
|
|
332
|
+
unstyled = false,
|
|
333
|
+
persistence,
|
|
334
|
+
validators
|
|
335
|
+
}) {
|
|
336
|
+
const normalizedRequirements = React.useMemo(
|
|
337
|
+
() => requirements ?? defaultRequirements,
|
|
338
|
+
[requirements]
|
|
339
|
+
);
|
|
340
|
+
const normalizedCompleteStep = React.useMemo(
|
|
341
|
+
() => completeStep ?? "COMPLETE",
|
|
342
|
+
[completeStep]
|
|
343
|
+
);
|
|
344
|
+
const resolvers = React.useMemo(
|
|
345
|
+
() => ({
|
|
346
|
+
...defaultRequirementResolvers,
|
|
347
|
+
...requirementResolvers ?? {}
|
|
348
|
+
}),
|
|
349
|
+
[requirementResolvers]
|
|
350
|
+
);
|
|
351
|
+
const graph = React.useMemo(
|
|
352
|
+
() => requirementGraph ?? createDefaultRequirementGraph({
|
|
353
|
+
requirements: normalizedRequirements,
|
|
354
|
+
resolvers,
|
|
355
|
+
priorities: requirementGraphConfig?.priorities,
|
|
356
|
+
conditions: requirementGraphConfig?.conditions,
|
|
357
|
+
dependencies: requirementGraphConfig?.dependencies
|
|
358
|
+
}),
|
|
359
|
+
[
|
|
360
|
+
requirementGraph,
|
|
361
|
+
normalizedRequirements,
|
|
362
|
+
resolvers,
|
|
363
|
+
requirementGraphConfig?.priorities,
|
|
364
|
+
requirementGraphConfig?.conditions,
|
|
365
|
+
requirementGraphConfig?.dependencies
|
|
366
|
+
]
|
|
367
|
+
);
|
|
368
|
+
const uiStyles = React.useMemo(() => resolveStyles(unstyled, styles), [unstyled, styles]);
|
|
369
|
+
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);
|
|
378
|
+
const attemptByStepRef = React.useRef({});
|
|
379
|
+
const previousStepRef = React.useRef(null);
|
|
380
|
+
const evaluationRef = React.useRef(0);
|
|
381
|
+
const completed = React.useRef(false);
|
|
382
|
+
React.useEffect(() => {
|
|
383
|
+
if (!persistence) {
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
try {
|
|
387
|
+
const persisted = readPersistedState(persistence);
|
|
388
|
+
if (persisted?.context) {
|
|
389
|
+
setContext(mergeContext(withDefaults(initialValue), persisted.context));
|
|
390
|
+
}
|
|
391
|
+
if (persisted?.oauthPendingProvider) {
|
|
392
|
+
setOauthPendingProvider(persisted.oauthPendingProvider);
|
|
393
|
+
}
|
|
394
|
+
} catch {
|
|
395
|
+
} finally {
|
|
396
|
+
setPersistenceHydrated(true);
|
|
397
|
+
}
|
|
398
|
+
}, [initialValue, persistence]);
|
|
399
|
+
React.useEffect(() => {
|
|
400
|
+
let isCancelled = false;
|
|
401
|
+
const currentEvaluation = ++evaluationRef.current;
|
|
402
|
+
void (async () => {
|
|
403
|
+
const [missing2, next] = await Promise.all([
|
|
404
|
+
getMissingRequirements(context, graph),
|
|
405
|
+
evaluateNextStep(context, graph, normalizedCompleteStep)
|
|
406
|
+
]);
|
|
407
|
+
if (isCancelled || currentEvaluation !== evaluationRef.current) {
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
setMissingRequirements(missing2);
|
|
411
|
+
setStep(next);
|
|
412
|
+
const from = previousStepRef.current;
|
|
413
|
+
const attemptKey = String(next);
|
|
414
|
+
const nextAttempt = from === next ? (attemptByStepRef.current[attemptKey] ?? 0) + 1 : 1;
|
|
415
|
+
attemptByStepRef.current[attemptKey] = nextAttempt;
|
|
416
|
+
const transition = {
|
|
417
|
+
from,
|
|
418
|
+
to: next,
|
|
419
|
+
at: Date.now(),
|
|
420
|
+
attempt: nextAttempt
|
|
421
|
+
};
|
|
422
|
+
setTransitions((previous) => [...previous, transition].slice(-100));
|
|
423
|
+
previousStepRef.current = next;
|
|
424
|
+
onStepTransition?.(transition, context);
|
|
425
|
+
})().catch((error) => {
|
|
426
|
+
if (isCancelled || currentEvaluation !== evaluationRef.current) {
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
const normalized = toError(error);
|
|
430
|
+
setErrorMessage(normalized.message);
|
|
431
|
+
onError?.(normalized);
|
|
432
|
+
});
|
|
433
|
+
return () => {
|
|
434
|
+
isCancelled = true;
|
|
435
|
+
};
|
|
436
|
+
}, [context, graph, normalizedCompleteStep, onError, onStepTransition]);
|
|
437
|
+
React.useEffect(() => {
|
|
438
|
+
if (step === normalizedCompleteStep) {
|
|
439
|
+
if (!completed.current) {
|
|
440
|
+
completed.current = true;
|
|
441
|
+
onComplete?.(context);
|
|
442
|
+
const shouldClearPersistence = persistence?.clearOnComplete ?? true;
|
|
443
|
+
if (shouldClearPersistence) {
|
|
444
|
+
clearPersistedState(persistence);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
} else {
|
|
448
|
+
completed.current = false;
|
|
449
|
+
}
|
|
450
|
+
}, [context, normalizedCompleteStep, onComplete, persistence, step]);
|
|
451
|
+
React.useEffect(() => {
|
|
452
|
+
if (!persistence || !persistenceHydrated) {
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
try {
|
|
456
|
+
writePersistedState(persistence, { context, oauthPendingProvider });
|
|
457
|
+
} catch {
|
|
458
|
+
}
|
|
459
|
+
}, [context, oauthPendingProvider, persistence, persistenceHydrated]);
|
|
460
|
+
const run = React.useCallback(
|
|
461
|
+
async (job) => {
|
|
462
|
+
setBusy(true);
|
|
463
|
+
setErrorMessage(null);
|
|
464
|
+
try {
|
|
465
|
+
await job();
|
|
466
|
+
} catch (error) {
|
|
467
|
+
const normalized = toError(error);
|
|
468
|
+
setErrorMessage(normalized.message);
|
|
469
|
+
onError?.(normalized);
|
|
470
|
+
} finally {
|
|
471
|
+
setBusy(false);
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
[onError]
|
|
475
|
+
);
|
|
476
|
+
const patchContext = React.useCallback((patch) => {
|
|
477
|
+
setContext((prev) => mergeContext(prev, patch));
|
|
478
|
+
}, []);
|
|
479
|
+
const patchBaseContext = React.useCallback(
|
|
480
|
+
(patch) => {
|
|
481
|
+
patchContext(patch);
|
|
482
|
+
},
|
|
483
|
+
[patchContext]
|
|
484
|
+
);
|
|
485
|
+
React.useEffect(() => {
|
|
486
|
+
const completeOAuth = adapter?.completeOAuth;
|
|
487
|
+
if (!oauthPendingProvider || !completeOAuth) {
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
void run(async () => {
|
|
491
|
+
const patch = await completeOAuth(oauthPendingProvider, context);
|
|
492
|
+
if (patch) {
|
|
493
|
+
patchContext(patch);
|
|
494
|
+
}
|
|
495
|
+
setOauthPendingProvider(null);
|
|
496
|
+
setMessage("OAuth sign-in completed.");
|
|
497
|
+
});
|
|
498
|
+
}, [adapter, context, oauthPendingProvider, patchContext, run]);
|
|
499
|
+
const handleEmail = (emailInput) => {
|
|
500
|
+
const email = emailInput.trim().toLowerCase();
|
|
501
|
+
if (!email) {
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
void run(async () => {
|
|
505
|
+
if (validators?.email) {
|
|
506
|
+
await assertValid(validators.email(email, { context }));
|
|
507
|
+
}
|
|
508
|
+
const identity = await adapter?.lookupByEmail?.(email) ?? null;
|
|
509
|
+
patchBaseContext({
|
|
510
|
+
email,
|
|
511
|
+
hasPassword: Boolean(identity?.hasPassword),
|
|
512
|
+
isVerified: Boolean(identity?.isVerified),
|
|
513
|
+
agreedToTos: Boolean(identity?.agreedToTos),
|
|
514
|
+
profile: {
|
|
515
|
+
firstName: identity?.profile?.firstName ?? null,
|
|
516
|
+
lastName: identity?.profile?.lastName ?? null,
|
|
517
|
+
jobTitle: identity?.profile?.jobTitle ?? null
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
if (identity?.accountExists && identity.hasPassword) {
|
|
521
|
+
setMessage("Welcome back. Enter your password to continue.");
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
if (adapter?.requestOtp) {
|
|
525
|
+
await adapter.requestOtp(email);
|
|
526
|
+
setMessage("We sent a 6-digit code to your inbox.");
|
|
527
|
+
} else {
|
|
528
|
+
patchBaseContext({ isVerified: true });
|
|
529
|
+
setMessage("No OTP adapter configured. Email verification was skipped.");
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
};
|
|
533
|
+
const handleOtp = (code) => {
|
|
534
|
+
if (!context.email) {
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
void run(async () => {
|
|
538
|
+
if (validators?.otp) {
|
|
539
|
+
await assertValid(validators.otp(code, { context, email: context.email }));
|
|
540
|
+
}
|
|
541
|
+
if (adapter?.verifyOtp) {
|
|
542
|
+
await adapter.verifyOtp(context.email, code);
|
|
543
|
+
}
|
|
544
|
+
patchBaseContext({ isVerified: true });
|
|
545
|
+
setMessage("Email verified.");
|
|
546
|
+
});
|
|
547
|
+
};
|
|
548
|
+
const handlePassword = (password) => {
|
|
549
|
+
if (!context.email) {
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
void run(async () => {
|
|
553
|
+
if (validators?.password) {
|
|
554
|
+
await assertValid(validators.password(password, { context, hasPassword: context.hasPassword }));
|
|
555
|
+
}
|
|
556
|
+
if (context.hasPassword) {
|
|
557
|
+
if (adapter?.signInWithPassword) {
|
|
558
|
+
await adapter.signInWithPassword(context.email, password);
|
|
559
|
+
}
|
|
560
|
+
} else {
|
|
561
|
+
if (adapter?.createPassword) {
|
|
562
|
+
await adapter.createPassword(password);
|
|
563
|
+
}
|
|
564
|
+
patchBaseContext({ hasPassword: true });
|
|
565
|
+
}
|
|
566
|
+
setMessage("Password step complete.");
|
|
567
|
+
});
|
|
568
|
+
};
|
|
569
|
+
const handleProfile = (profile) => {
|
|
570
|
+
void run(async () => {
|
|
571
|
+
if (validators?.profile) {
|
|
572
|
+
await assertValid(validators.profile(profile, { context }));
|
|
573
|
+
}
|
|
574
|
+
const next = mergeContext(context, {
|
|
575
|
+
profile: {
|
|
576
|
+
firstName: profile.firstName || null,
|
|
577
|
+
lastName: profile.lastName || null,
|
|
578
|
+
jobTitle: profile.jobTitle || null
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
if (adapter?.saveProfile) {
|
|
582
|
+
await adapter.saveProfile(next);
|
|
583
|
+
}
|
|
584
|
+
patchContext({ profile: next.profile });
|
|
585
|
+
setMessage("Profile saved.");
|
|
586
|
+
});
|
|
587
|
+
};
|
|
588
|
+
const handleTos = () => {
|
|
589
|
+
void run(async () => {
|
|
590
|
+
if (validators?.tos) {
|
|
591
|
+
await assertValid(validators.tos(true, { context }));
|
|
592
|
+
}
|
|
593
|
+
const next = mergeContext(context, { agreedToTos: true });
|
|
594
|
+
if (adapter?.acceptTos) {
|
|
595
|
+
await adapter.acceptTos(next);
|
|
596
|
+
}
|
|
597
|
+
patchBaseContext({ agreedToTos: true });
|
|
598
|
+
setMessage("Terms accepted.");
|
|
599
|
+
});
|
|
600
|
+
};
|
|
601
|
+
const handleOAuth = (provider) => {
|
|
602
|
+
const startOAuth = adapter?.startOAuth;
|
|
603
|
+
if (!startOAuth) {
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
void run(async () => {
|
|
607
|
+
setOauthPendingProvider(provider);
|
|
608
|
+
setMessage(`Starting ${provider} sign-in...`);
|
|
609
|
+
await startOAuth(provider, context);
|
|
610
|
+
});
|
|
611
|
+
};
|
|
612
|
+
const missing = missingRequirements;
|
|
613
|
+
const needsJobTitle = normalizedRequirements.includes("has_job_title");
|
|
614
|
+
const stepLabel = stepTitles?.[step] ?? defaultStepTitle[step] ?? step;
|
|
615
|
+
const defaultView = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
616
|
+
step === "COLLECT_EMAIL" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
617
|
+
EmailBlock,
|
|
618
|
+
{
|
|
619
|
+
onSubmit: handleEmail,
|
|
620
|
+
disabled: busy,
|
|
621
|
+
styles: uiStyles,
|
|
622
|
+
classNames
|
|
623
|
+
}
|
|
624
|
+
) : null,
|
|
625
|
+
step === "VERIFY_OTP" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
626
|
+
OtpBlock,
|
|
627
|
+
{
|
|
628
|
+
onSubmit: handleOtp,
|
|
629
|
+
email: context.email ?? "your email",
|
|
630
|
+
disabled: busy,
|
|
631
|
+
styles: uiStyles,
|
|
632
|
+
classNames
|
|
633
|
+
}
|
|
634
|
+
) : null,
|
|
635
|
+
step === "COLLECT_PASSWORD" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
636
|
+
PasswordBlock,
|
|
637
|
+
{
|
|
638
|
+
onSubmit: handlePassword,
|
|
639
|
+
disabled: busy,
|
|
640
|
+
hasPassword: context.hasPassword,
|
|
641
|
+
styles: uiStyles,
|
|
642
|
+
classNames
|
|
643
|
+
}
|
|
644
|
+
) : null,
|
|
645
|
+
step === "COLLECT_PROFILE" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
646
|
+
ProfileBlock,
|
|
647
|
+
{
|
|
648
|
+
defaultValue: context.profile,
|
|
649
|
+
requireJobTitle: needsJobTitle,
|
|
650
|
+
onSubmit: handleProfile,
|
|
651
|
+
disabled: busy,
|
|
652
|
+
styles: uiStyles,
|
|
653
|
+
classNames
|
|
654
|
+
}
|
|
655
|
+
) : null,
|
|
656
|
+
step === "COLLECT_TOS" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
657
|
+
TosBlock,
|
|
658
|
+
{
|
|
659
|
+
onSubmit: handleTos,
|
|
660
|
+
disabled: busy,
|
|
661
|
+
styles: uiStyles,
|
|
662
|
+
classNames
|
|
663
|
+
}
|
|
664
|
+
) : null,
|
|
665
|
+
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: [
|
|
667
|
+
'No default renderer for step "',
|
|
668
|
+
step,
|
|
669
|
+
'". Provide renderStep to handle custom steps.'
|
|
670
|
+
] }) : null
|
|
671
|
+
] });
|
|
672
|
+
const customView = renderStep ? renderStep({
|
|
673
|
+
step,
|
|
674
|
+
context,
|
|
675
|
+
busy,
|
|
676
|
+
message,
|
|
677
|
+
errorMessage,
|
|
678
|
+
missingRequirements: missing,
|
|
679
|
+
requirements: normalizedRequirements,
|
|
680
|
+
defaultView,
|
|
681
|
+
setContextPatch: patchContext,
|
|
682
|
+
run,
|
|
683
|
+
adapter,
|
|
684
|
+
transitions
|
|
685
|
+
}) : null;
|
|
686
|
+
const registryView = stepRegistry?.[step] ? stepRegistry[step]?.({
|
|
687
|
+
step,
|
|
688
|
+
context,
|
|
689
|
+
busy,
|
|
690
|
+
message,
|
|
691
|
+
errorMessage,
|
|
692
|
+
missingRequirements: missing,
|
|
693
|
+
requirements: normalizedRequirements,
|
|
694
|
+
setContextPatch: patchContext,
|
|
695
|
+
run,
|
|
696
|
+
adapter,
|
|
697
|
+
transitions
|
|
698
|
+
}) : null;
|
|
699
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: cx(className, classNames?.shell), style: uiStyles.shell, children: [
|
|
700
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: classNames?.headerRow, style: uiStyles.headerRow, children: [
|
|
701
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
702
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: classNames?.eyebrow, style: uiStyles.eyebrow, children: "Adaptive flow" }),
|
|
703
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: classNames?.title, style: uiStyles.title, children: stepLabel })
|
|
704
|
+
] }),
|
|
705
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: classNames?.badge, style: uiStyles.badge, children: [
|
|
706
|
+
normalizedRequirements.length - missing.length,
|
|
707
|
+
"/",
|
|
708
|
+
normalizedRequirements.length
|
|
709
|
+
] })
|
|
710
|
+
] }),
|
|
711
|
+
message ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: classNames?.success, style: uiStyles.success, children: message }) : null,
|
|
712
|
+
errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: classNames?.error, style: uiStyles.error, children: errorMessage }) : null,
|
|
713
|
+
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
|
+
] })
|
|
742
|
+
] });
|
|
743
|
+
}
|
|
744
|
+
function EmailBlock({ onSubmit, disabled, styles, classNames }) {
|
|
745
|
+
const [email, setEmail] = React.useState("");
|
|
746
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
747
|
+
"form",
|
|
748
|
+
{
|
|
749
|
+
className: classNames?.formRow,
|
|
750
|
+
style: styles.formRow,
|
|
751
|
+
onSubmit: (event) => {
|
|
752
|
+
event.preventDefault();
|
|
753
|
+
onSubmit(email);
|
|
754
|
+
},
|
|
755
|
+
children: [
|
|
756
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
757
|
+
"input",
|
|
758
|
+
{
|
|
759
|
+
className: classNames?.input,
|
|
760
|
+
style: styles.input,
|
|
761
|
+
type: "email",
|
|
762
|
+
autoComplete: "email",
|
|
763
|
+
placeholder: "Enter your email",
|
|
764
|
+
value: email,
|
|
765
|
+
onChange: (event) => setEmail(event.target.value),
|
|
766
|
+
required: true
|
|
767
|
+
}
|
|
768
|
+
),
|
|
769
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: classNames?.button, style: styles.button, disabled, type: "submit", children: "Continue" })
|
|
770
|
+
]
|
|
771
|
+
}
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
function OtpBlock({
|
|
775
|
+
onSubmit,
|
|
776
|
+
disabled,
|
|
777
|
+
email,
|
|
778
|
+
styles,
|
|
779
|
+
classNames
|
|
780
|
+
}) {
|
|
781
|
+
const [code, setCode] = React.useState("");
|
|
782
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
783
|
+
"form",
|
|
784
|
+
{
|
|
785
|
+
className: classNames?.formColumn,
|
|
786
|
+
style: styles.formColumn,
|
|
787
|
+
onSubmit: (event) => {
|
|
788
|
+
event.preventDefault();
|
|
789
|
+
onSubmit(code);
|
|
790
|
+
},
|
|
791
|
+
children: [
|
|
792
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: classNames?.caption, style: styles.caption, children: [
|
|
793
|
+
"Use the verification code sent to ",
|
|
794
|
+
email,
|
|
795
|
+
"."
|
|
796
|
+
] }),
|
|
797
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: classNames?.formRow, style: styles.formRow, children: [
|
|
798
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
799
|
+
"input",
|
|
800
|
+
{
|
|
801
|
+
className: classNames?.input,
|
|
802
|
+
style: styles.input,
|
|
803
|
+
inputMode: "numeric",
|
|
804
|
+
placeholder: "Enter 6-digit code",
|
|
805
|
+
value: code,
|
|
806
|
+
onChange: (event) => setCode(event.target.value.replace(/\D/g, "").slice(0, 6)),
|
|
807
|
+
required: true,
|
|
808
|
+
maxLength: 6,
|
|
809
|
+
pattern: "[0-9]{6}"
|
|
810
|
+
}
|
|
811
|
+
),
|
|
812
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
813
|
+
"button",
|
|
814
|
+
{
|
|
815
|
+
className: classNames?.button,
|
|
816
|
+
style: styles.button,
|
|
817
|
+
disabled: disabled || code.length !== 6,
|
|
818
|
+
type: "submit",
|
|
819
|
+
children: "Verify"
|
|
820
|
+
}
|
|
821
|
+
)
|
|
822
|
+
] })
|
|
823
|
+
]
|
|
824
|
+
}
|
|
825
|
+
);
|
|
826
|
+
}
|
|
827
|
+
function PasswordBlock({
|
|
828
|
+
onSubmit,
|
|
829
|
+
disabled,
|
|
830
|
+
hasPassword,
|
|
831
|
+
styles,
|
|
832
|
+
classNames
|
|
833
|
+
}) {
|
|
834
|
+
const [password, setPassword] = React.useState("");
|
|
835
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
836
|
+
"form",
|
|
837
|
+
{
|
|
838
|
+
className: classNames?.formRow,
|
|
839
|
+
style: styles.formRow,
|
|
840
|
+
onSubmit: (event) => {
|
|
841
|
+
event.preventDefault();
|
|
842
|
+
onSubmit(password);
|
|
843
|
+
},
|
|
844
|
+
children: [
|
|
845
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
846
|
+
"input",
|
|
847
|
+
{
|
|
848
|
+
className: classNames?.input,
|
|
849
|
+
style: styles.input,
|
|
850
|
+
type: "password",
|
|
851
|
+
autoComplete: hasPassword ? "current-password" : "new-password",
|
|
852
|
+
placeholder: hasPassword ? "Enter your password" : "Create a password",
|
|
853
|
+
value: password,
|
|
854
|
+
onChange: (event) => setPassword(event.target.value),
|
|
855
|
+
required: true,
|
|
856
|
+
minLength: 8
|
|
857
|
+
}
|
|
858
|
+
),
|
|
859
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: classNames?.button, style: styles.button, disabled, type: "submit", children: "Continue" })
|
|
860
|
+
]
|
|
861
|
+
}
|
|
862
|
+
);
|
|
863
|
+
}
|
|
864
|
+
function ProfileBlock({
|
|
865
|
+
onSubmit,
|
|
866
|
+
disabled,
|
|
867
|
+
defaultValue,
|
|
868
|
+
requireJobTitle,
|
|
869
|
+
styles,
|
|
870
|
+
classNames
|
|
871
|
+
}) {
|
|
872
|
+
const [firstName, setFirstName] = React.useState(defaultValue.firstName ?? "");
|
|
873
|
+
const [lastName, setLastName] = React.useState(defaultValue.lastName ?? "");
|
|
874
|
+
const [jobTitle, setJobTitle] = React.useState(defaultValue.jobTitle ?? "");
|
|
875
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
876
|
+
"form",
|
|
877
|
+
{
|
|
878
|
+
className: classNames?.formColumn,
|
|
879
|
+
style: styles.formColumn,
|
|
880
|
+
onSubmit: (event) => {
|
|
881
|
+
event.preventDefault();
|
|
882
|
+
onSubmit({
|
|
883
|
+
firstName: firstName || null,
|
|
884
|
+
lastName: lastName || null,
|
|
885
|
+
jobTitle: jobTitle || null
|
|
886
|
+
});
|
|
887
|
+
},
|
|
888
|
+
children: [
|
|
889
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: classNames?.formRow, style: styles.formRow, children: [
|
|
890
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
891
|
+
"input",
|
|
892
|
+
{
|
|
893
|
+
className: classNames?.input,
|
|
894
|
+
style: styles.input,
|
|
895
|
+
type: "text",
|
|
896
|
+
autoComplete: "given-name",
|
|
897
|
+
placeholder: "First name",
|
|
898
|
+
value: firstName,
|
|
899
|
+
onChange: (event) => setFirstName(event.target.value),
|
|
900
|
+
required: true
|
|
901
|
+
}
|
|
902
|
+
),
|
|
903
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
904
|
+
"input",
|
|
905
|
+
{
|
|
906
|
+
className: classNames?.input,
|
|
907
|
+
style: styles.input,
|
|
908
|
+
type: "text",
|
|
909
|
+
autoComplete: "family-name",
|
|
910
|
+
placeholder: "Last name",
|
|
911
|
+
value: lastName,
|
|
912
|
+
onChange: (event) => setLastName(event.target.value),
|
|
913
|
+
required: true
|
|
914
|
+
}
|
|
915
|
+
)
|
|
916
|
+
] }),
|
|
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,
|
|
930
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: classNames?.button, style: styles.button, disabled, type: "submit", children: "Continue" })
|
|
931
|
+
]
|
|
932
|
+
}
|
|
933
|
+
);
|
|
934
|
+
}
|
|
935
|
+
function TosBlock({
|
|
936
|
+
onSubmit,
|
|
937
|
+
disabled,
|
|
938
|
+
styles,
|
|
939
|
+
classNames
|
|
940
|
+
}) {
|
|
941
|
+
const [checked, setChecked] = React.useState(false);
|
|
942
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
943
|
+
"form",
|
|
944
|
+
{
|
|
945
|
+
className: classNames?.formColumn,
|
|
946
|
+
style: styles.formColumn,
|
|
947
|
+
onSubmit: (event) => {
|
|
948
|
+
event.preventDefault();
|
|
949
|
+
if (checked) {
|
|
950
|
+
onSubmit();
|
|
951
|
+
}
|
|
952
|
+
},
|
|
953
|
+
children: [
|
|
954
|
+
/* @__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) }),
|
|
956
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "I agree to the Terms of Service and Privacy Policy." })
|
|
957
|
+
] }),
|
|
958
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
959
|
+
"button",
|
|
960
|
+
{
|
|
961
|
+
className: classNames?.button,
|
|
962
|
+
style: styles.button,
|
|
963
|
+
disabled: disabled || !checked,
|
|
964
|
+
type: "submit",
|
|
965
|
+
children: "Accept and Continue"
|
|
966
|
+
}
|
|
967
|
+
)
|
|
968
|
+
]
|
|
969
|
+
}
|
|
970
|
+
);
|
|
971
|
+
}
|
|
972
|
+
function CompleteBlock({
|
|
973
|
+
styles,
|
|
974
|
+
classNames
|
|
975
|
+
}) {
|
|
976
|
+
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." }),
|
|
978
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: classNames?.caption, style: styles.caption, children: "All requirements are complete." })
|
|
979
|
+
] });
|
|
980
|
+
}
|
|
981
|
+
var defaultStyles = {
|
|
982
|
+
shell: {
|
|
983
|
+
display: "flex",
|
|
984
|
+
flexDirection: "column",
|
|
985
|
+
gap: 12,
|
|
986
|
+
width: "100%",
|
|
987
|
+
maxWidth: 560,
|
|
988
|
+
border: "1px solid #e5e7eb",
|
|
989
|
+
borderRadius: 14,
|
|
990
|
+
padding: 16,
|
|
991
|
+
background: "#ffffff",
|
|
992
|
+
fontFamily: "system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
|
|
993
|
+
},
|
|
994
|
+
headerRow: {
|
|
995
|
+
display: "flex",
|
|
996
|
+
justifyContent: "space-between",
|
|
997
|
+
alignItems: "center",
|
|
998
|
+
gap: 12
|
|
999
|
+
},
|
|
1000
|
+
eyebrow: {
|
|
1001
|
+
fontSize: 12,
|
|
1002
|
+
textTransform: "uppercase",
|
|
1003
|
+
letterSpacing: 1.2,
|
|
1004
|
+
color: "#6b7280",
|
|
1005
|
+
marginBottom: 4
|
|
1006
|
+
},
|
|
1007
|
+
title: {
|
|
1008
|
+
margin: 0,
|
|
1009
|
+
fontSize: 22,
|
|
1010
|
+
lineHeight: "28px"
|
|
1011
|
+
},
|
|
1012
|
+
badge: {
|
|
1013
|
+
border: "1px solid #d1d5db",
|
|
1014
|
+
borderRadius: 999,
|
|
1015
|
+
padding: "4px 10px",
|
|
1016
|
+
fontSize: 12,
|
|
1017
|
+
fontWeight: 600,
|
|
1018
|
+
color: "#374151"
|
|
1019
|
+
},
|
|
1020
|
+
success: {
|
|
1021
|
+
border: "1px solid #bbf7d0",
|
|
1022
|
+
background: "#f0fdf4",
|
|
1023
|
+
color: "#166534",
|
|
1024
|
+
borderRadius: 10,
|
|
1025
|
+
padding: "8px 10px",
|
|
1026
|
+
fontSize: 14
|
|
1027
|
+
},
|
|
1028
|
+
error: {
|
|
1029
|
+
border: "1px solid #fecaca",
|
|
1030
|
+
background: "#fef2f2",
|
|
1031
|
+
color: "#991b1b",
|
|
1032
|
+
borderRadius: 10,
|
|
1033
|
+
padding: "8px 10px",
|
|
1034
|
+
fontSize: 14
|
|
1035
|
+
},
|
|
1036
|
+
info: {
|
|
1037
|
+
border: "1px solid #bfdbfe",
|
|
1038
|
+
background: "#eff6ff",
|
|
1039
|
+
color: "#1e3a8a",
|
|
1040
|
+
borderRadius: 10,
|
|
1041
|
+
padding: "8px 10px",
|
|
1042
|
+
fontSize: 14
|
|
1043
|
+
},
|
|
1044
|
+
caption: {
|
|
1045
|
+
margin: 0,
|
|
1046
|
+
color: "#4b5563",
|
|
1047
|
+
fontSize: 14
|
|
1048
|
+
},
|
|
1049
|
+
formRow: {
|
|
1050
|
+
display: "flex",
|
|
1051
|
+
gap: 8,
|
|
1052
|
+
alignItems: "center"
|
|
1053
|
+
},
|
|
1054
|
+
formColumn: {
|
|
1055
|
+
display: "flex",
|
|
1056
|
+
flexDirection: "column",
|
|
1057
|
+
gap: 10
|
|
1058
|
+
},
|
|
1059
|
+
input: {
|
|
1060
|
+
width: "100%",
|
|
1061
|
+
border: "1px solid #d1d5db",
|
|
1062
|
+
borderRadius: 8,
|
|
1063
|
+
height: 40,
|
|
1064
|
+
padding: "0 12px",
|
|
1065
|
+
fontSize: 14
|
|
1066
|
+
},
|
|
1067
|
+
button: {
|
|
1068
|
+
border: "1px solid #d1d5db",
|
|
1069
|
+
borderRadius: 8,
|
|
1070
|
+
height: 40,
|
|
1071
|
+
padding: "0 14px",
|
|
1072
|
+
fontWeight: 600,
|
|
1073
|
+
background: "#ffffff",
|
|
1074
|
+
whiteSpace: "nowrap",
|
|
1075
|
+
cursor: "pointer"
|
|
1076
|
+
},
|
|
1077
|
+
checkboxRow: {
|
|
1078
|
+
display: "flex",
|
|
1079
|
+
gap: 8,
|
|
1080
|
+
alignItems: "flex-start",
|
|
1081
|
+
fontSize: 14,
|
|
1082
|
+
color: "#374151"
|
|
1083
|
+
},
|
|
1084
|
+
complete: {
|
|
1085
|
+
border: "1px solid #bbf7d0",
|
|
1086
|
+
background: "#f0fdf4",
|
|
1087
|
+
color: "#166534",
|
|
1088
|
+
borderRadius: 12,
|
|
1089
|
+
padding: 12
|
|
1090
|
+
},
|
|
1091
|
+
footer: {
|
|
1092
|
+
display: "flex",
|
|
1093
|
+
gap: 8,
|
|
1094
|
+
marginTop: 4
|
|
1095
|
+
},
|
|
1096
|
+
oauthButton: {
|
|
1097
|
+
flex: 1,
|
|
1098
|
+
border: "1px solid #d1d5db",
|
|
1099
|
+
borderRadius: 8,
|
|
1100
|
+
padding: "10px 12px",
|
|
1101
|
+
background: "#f9fafb",
|
|
1102
|
+
cursor: "pointer"
|
|
1103
|
+
}
|
|
1104
|
+
};
|
|
1105
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1106
|
+
0 && (module.exports = {
|
|
1107
|
+
AdaptiveFlow,
|
|
1108
|
+
DefaultAdaptiveSteps,
|
|
1109
|
+
DefaultAppRequirements,
|
|
1110
|
+
createDefaultRequirementGraph,
|
|
1111
|
+
createRequirementGraph,
|
|
1112
|
+
defaultRequirementResolvers,
|
|
1113
|
+
defaultRequirements,
|
|
1114
|
+
evaluateNextStep,
|
|
1115
|
+
getMissingRequirements,
|
|
1116
|
+
initialContext
|
|
1117
|
+
});
|
|
1118
|
+
//# sourceMappingURL=index.js.map
|