@ory/elements-react 1.0.0-next.14 → 1.0.0-next.15

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.mjs CHANGED
@@ -1,8 +1,8 @@
1
- import { UiNodeGroupEnum, isUiNodeInputAttributes, isUiNodeAnchorAttributes, isUiNodeImageAttributes, isUiNodeScriptAttributes, FlowType, isUiNodeTextAttributes, UiNodeInputAttributesTypeEnum, handleFlowError, loginUrl, handleContinueWith, registrationUrl, verificationUrl, recoveryUrl, settingsUrl, isResponseError, Configuration, FrontendApi } from '@ory/client-fetch';
2
- import { createContext, useContext, useState, useMemo, useRef, useEffect } from 'react';
1
+ import { UiNodeGroupEnum, isUiNodeInputAttributes, isUiNodeAnchorAttributes, isUiNodeImageAttributes, isUiNodeScriptAttributes, isUiNodeTextAttributes, UiNodeInputAttributesTypeEnum, FlowType, Configuration, FrontendApi, handleContinueWith, settingsUrl, handleFlowError, isResponseError, loginUrl, recoveryUrl, verificationUrl, registrationUrl } from '@ory/client-fetch';
2
+ import { createContext, useContext, useRef, useEffect, useState, useReducer, useMemo } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { useIntl, IntlProvider as IntlProvider$1 } from 'react-intl';
5
- import { useFormContext, useForm, FormProvider } from 'react-hook-form';
5
+ import { useForm, FormProvider, useFormContext } from 'react-hook-form';
6
6
 
7
7
  // src/context/component.tsx
8
8
  var ComponentContext = createContext({
@@ -83,6 +83,71 @@ function OryComponentProvider({
83
83
  }
84
84
  );
85
85
  }
86
+ function isChoosingMethod(uiNodes) {
87
+ return uiNodes.some(
88
+ (node) => "name" in node.attributes && node.attributes.name === "screen" && "value" in node.attributes && node.attributes.value === "previous"
89
+ ) || uiNodes.some(
90
+ (node) => node.group === UiNodeGroupEnum.IdentifierFirst && "name" in node.attributes && node.attributes.name === "identifier" && node.attributes.type === "hidden"
91
+ );
92
+ }
93
+ function filterZeroStepGroups(nodes) {
94
+ return nodes.filter((node) => node.group !== UiNodeGroupEnum.Oidc);
95
+ }
96
+ function getFinalNodes(uniqueGroups, selectedGroup) {
97
+ var _a, _b, _c;
98
+ const selectedNodes = selectedGroup ? (_a = uniqueGroups[selectedGroup]) != null ? _a : [] : [];
99
+ return [
100
+ ...(_b = uniqueGroups == null ? void 0 : uniqueGroups.identifier_first) != null ? _b : [],
101
+ ...(_c = uniqueGroups == null ? void 0 : uniqueGroups.default) != null ? _c : []
102
+ ].flat().filter(
103
+ (node) => "type" in node.attributes && node.attributes.type === "hidden"
104
+ ).concat(selectedNodes);
105
+ }
106
+
107
+ // src/context/form-state.ts
108
+ function parseStateFromFlow(flow) {
109
+ switch (flow.flowType) {
110
+ case FlowType.Registration:
111
+ case FlowType.Login:
112
+ if (flow.flow.active == "link_recovery") {
113
+ return { current: "method_active", method: "link" };
114
+ } else if (flow.flow.active == "code_recovery") {
115
+ return { current: "method_active", method: "code" };
116
+ } else if (isChoosingMethod(flow.flow.ui.nodes)) {
117
+ return { current: "select_method" };
118
+ } else if (flow.flow.active) {
119
+ return { current: "method_active", method: flow.flow.active };
120
+ }
121
+ return { current: "provide_identifier" };
122
+ case FlowType.Recovery:
123
+ case FlowType.Verification:
124
+ if (flow.flow.active === "code" || flow.flow.active === "link") {
125
+ if (flow.flow.state === "choose_method") {
126
+ return { current: "provide_identifier" };
127
+ }
128
+ return { current: "method_active", method: flow.flow.active };
129
+ }
130
+ break;
131
+ case FlowType.Settings:
132
+ return { current: "settings" };
133
+ }
134
+ console.warn(
135
+ `[Ory/Elements React] Encountered an unknown form state on ${flow.flowType} flow with ID ${flow.flow.id}`
136
+ );
137
+ throw new Error("Unknown form state");
138
+ }
139
+ function formStateReducer(state, action) {
140
+ switch (action.type) {
141
+ case "action_flow_update":
142
+ return parseStateFromFlow(action.flow);
143
+ case "action_select_method":
144
+ return { current: "method_active", method: action.method };
145
+ }
146
+ return state;
147
+ }
148
+ function useFormStateReducer(flow) {
149
+ return useReducer(formStateReducer, parseStateFromFlow(flow));
150
+ }
86
151
  function useOryFlow() {
87
152
  const ctx = useContext(OryFlowContext);
88
153
  if (!ctx) {
@@ -96,19 +161,21 @@ function OryFlowProvider({
96
161
  ...container
97
162
  }) {
98
163
  const [flowContainer, setFlowContainer] = useState(container);
164
+ const [formState, dispatchFormState] = useFormStateReducer(container);
99
165
  return /* @__PURE__ */ jsx(
100
166
  OryFlowContext.Provider,
101
167
  {
102
168
  value: {
103
169
  ...flowContainer,
104
- setFlowContainer: (updatedContainer) => {
105
- setFlowContainer(
106
- (container2) => ({
107
- ...container2,
108
- ...updatedContainer
109
- })
110
- );
111
- }
170
+ setFlowContainer: (flowContainer2) => {
171
+ setFlowContainer(flowContainer2);
172
+ dispatchFormState({
173
+ type: "action_flow_update",
174
+ flow: flowContainer2
175
+ });
176
+ },
177
+ formState,
178
+ dispatchFormState
112
179
  },
113
180
  children
114
181
  }
@@ -357,7 +424,8 @@ var en_default = {
357
424
  "settings.webauthn.info": "Hardware Tokens are used for second-factor authentication or as first-factor with Passkeys",
358
425
  "settings.passkey.title": "Manage Passkeys",
359
426
  "settings.passkey.description": "Manage your passkey settings",
360
- "settings.passkey.info": "Manage your passkey settings"
427
+ "settings.passkey.info": "Manage your passkey settings",
428
+ "card.footer.select-another-method": "Select another method"
361
429
  };
362
430
 
363
431
  // src/locales/de.json
@@ -602,7 +670,8 @@ var de_default = {
602
670
  "settings.title-profile": "Profileinstellungen",
603
671
  "settings.title-totp": "Verwalten Sie die 2FA TOTP Authenticator-App",
604
672
  "settings.title-webauthn": "Hardware-Token verwalten",
605
- "settings.webauthn.info": "Hardware-Tokens werden f\xFCr die Zweitfaktor-Authentifizierung oder als Erstfaktor-Authentifizierung mit Passkeys verwendet"
673
+ "settings.webauthn.info": "Hardware-Tokens werden f\xFCr die Zweitfaktor-Authentifizierung oder als Erstfaktor-Authentifizierung mit Passkeys verwendet",
674
+ "card.footer.select-another-method": "Eine andere Methode verwenden"
606
675
  };
607
676
 
608
677
  // src/locales/es.json
@@ -847,7 +916,8 @@ var es_default = {
847
916
  "settings.title-profile": "",
848
917
  "settings.title-totp": "",
849
918
  "settings.title-webauthn": "",
850
- "settings.webauthn.info": ""
919
+ "settings.webauthn.info": "",
920
+ "card.footer.select-another-method": ""
851
921
  };
852
922
 
853
923
  // src/locales/fr.json
@@ -1092,7 +1162,8 @@ var fr_default = {
1092
1162
  "settings.title-webauthn": "",
1093
1163
  "settings.webauthn.description": "",
1094
1164
  "settings.webauthn.info": "",
1095
- "settings.webauthn.title": ""
1165
+ "settings.webauthn.title": "",
1166
+ "card.footer.select-another-method": ""
1096
1167
  };
1097
1168
 
1098
1169
  // src/locales/nl.json
@@ -1337,7 +1408,8 @@ var nl_default = {
1337
1408
  "settings.title-webauthn": "",
1338
1409
  "settings.webauthn.description": "",
1339
1410
  "settings.webauthn.info": "",
1340
- "settings.webauthn.title": ""
1411
+ "settings.webauthn.title": "",
1412
+ "card.footer.select-another-method": ""
1341
1413
  };
1342
1414
 
1343
1415
  // src/locales/pl.json
@@ -1582,7 +1654,8 @@ var pl_default = {
1582
1654
  "settings.title-webauthn": "",
1583
1655
  "settings.webauthn.description": "",
1584
1656
  "settings.webauthn.info": "",
1585
- "settings.webauthn.title": ""
1657
+ "settings.webauthn.title": "",
1658
+ "card.footer.select-another-method": ""
1586
1659
  };
1587
1660
 
1588
1661
  // src/locales/pt.json
@@ -1827,7 +1900,8 @@ var pt_default = {
1827
1900
  "settings.title-webauthn": "",
1828
1901
  "settings.webauthn.description": "",
1829
1902
  "settings.webauthn.info": "",
1830
- "settings.webauthn.title": ""
1903
+ "settings.webauthn.title": "",
1904
+ "card.footer.select-another-method": ""
1831
1905
  };
1832
1906
 
1833
1907
  // src/locales/sv.json
@@ -2072,7 +2146,8 @@ var sv_default = {
2072
2146
  "settings.title-webauthn": "Hantera maskinvarutokens",
2073
2147
  "settings.webauthn.description": "Hantera inst\xE4llningarna f\xF6r din maskinvarutoken",
2074
2148
  "settings.webauthn.info": "H\xE5rdvarutokens anv\xE4nds f\xF6r andrafaktorsautentisering eller som f\xF6rstafaktor med l\xF6senordsnycklar",
2075
- "settings.webauthn.title": "Hantera maskinvarutokens"
2149
+ "settings.webauthn.title": "Hantera maskinvarutokens",
2150
+ "card.footer.select-another-method": "V\xE4lj en annan metod"
2076
2151
  };
2077
2152
 
2078
2153
  // src/locales/index.ts
@@ -2131,131 +2206,374 @@ function OryCardHeader() {
2131
2206
  const { Card } = useComponents();
2132
2207
  return /* @__PURE__ */ jsx(Card.Header, {});
2133
2208
  }
2134
- function triggerToWindowCall(trigger) {
2135
- if (!trigger) {
2136
- return;
2137
- }
2138
- const fn = triggerToFunction(trigger);
2139
- if (fn) {
2140
- fn();
2141
- return;
2142
- }
2143
- let i = 0;
2144
- const ms = 250;
2145
- const interval = setInterval(() => {
2146
- i++;
2147
- if (i > 20) {
2148
- clearInterval(interval);
2149
- throw new Error(
2150
- "Unable to load Ory's WebAuthn script. Is it being blocked or otherwise failing to load? If you are running an old version of Ory Elements, please upgrade. For more information, please check your browser's developer console."
2151
- );
2152
- }
2153
- const fn2 = triggerToFunction(trigger);
2154
- if (fn2) {
2155
- clearInterval(interval);
2156
- return fn2();
2209
+ function frontendClient(sdkUrl, opts = {}) {
2210
+ const config = new Configuration({
2211
+ ...opts,
2212
+ basePath: sdkUrl,
2213
+ headers: {
2214
+ Accept: "application/json",
2215
+ ...opts.headers
2157
2216
  }
2158
- }, ms);
2159
- return;
2217
+ });
2218
+ return new FrontendApi(config);
2160
2219
  }
2161
- function triggerToFunction(trigger) {
2162
- if (typeof window === "undefined") {
2163
- console.error(
2164
- "The Ory SDK is missing a required function: window is undefined."
2220
+
2221
+ // src/util/onSubmitLogin.ts
2222
+ async function onSubmitLogin({ config, flow }, {
2223
+ setFlowContainer,
2224
+ body,
2225
+ onRedirect
2226
+ }) {
2227
+ var _a;
2228
+ if (!config.sdk.url) {
2229
+ throw new Error(
2230
+ `Please supply your Ory Network SDK url to the Ory Elements configuration.`
2165
2231
  );
2166
- return void 0;
2167
- }
2168
- const typedWindow = window;
2169
- if (!(trigger in typedWindow) || !typedWindow[trigger]) {
2170
- console.error(`The Ory SDK is missing a required function: ${trigger}.`);
2171
- return void 0;
2172
2232
  }
2173
- const triggerFn = typedWindow[trigger];
2174
- if (typeof triggerFn !== "function") {
2175
- console.error(
2176
- `The Ory SDK is missing a required function: ${trigger}. It is not a function.`
2233
+ await frontendClient(config.sdk.url, (_a = config.sdk.options) != null ? _a : {}).updateLoginFlowRaw({
2234
+ flow: flow.id,
2235
+ updateLoginFlowBody: body
2236
+ }).then(() => {
2237
+ var _a2;
2238
+ window.location.href = (_a2 = flow.return_to) != null ? _a2 : config.sdk.url + "/self-service/login/browser";
2239
+ }).catch(
2240
+ handleFlowError({
2241
+ onRestartFlow: () => {
2242
+ onRedirect(loginUrl(config), true);
2243
+ },
2244
+ onValidationError: (body2) => {
2245
+ setFlowContainer({
2246
+ config,
2247
+ flow: body2,
2248
+ flowType: FlowType.Login
2249
+ });
2250
+ },
2251
+ onRedirect
2252
+ })
2253
+ );
2254
+ }
2255
+ async function onSubmitRecovery({ config, flow }, {
2256
+ setFlowContainer,
2257
+ body,
2258
+ onRedirect
2259
+ }) {
2260
+ var _a;
2261
+ if (!config.sdk.url) {
2262
+ throw new Error(
2263
+ `Please supply your Ory Network SDK url to the Ory Elements configuration.`
2177
2264
  );
2178
- return void 0;
2179
2265
  }
2180
- return triggerFn;
2181
- }
2182
- function useNodesGroups(nodes) {
2183
- const groupSorter = useGroupSorter();
2184
- const groups = useMemo(() => {
2185
- var _a;
2186
- const groups2 = {};
2187
- for (const node of nodes) {
2188
- const groupNodes = (_a = groups2[node.group]) != null ? _a : [];
2189
- groupNodes.push(node);
2190
- groups2[node.group] = groupNodes;
2266
+ await frontendClient(config.sdk.url, (_a = config.sdk.options) != null ? _a : {}).updateRecoveryFlowRaw({
2267
+ flow: flow.id,
2268
+ updateRecoveryFlowBody: body
2269
+ }).then(async (res) => {
2270
+ const flow2 = await res.value();
2271
+ const didContinueWith = handleContinueWith(flow2.continue_with, {
2272
+ onRedirect
2273
+ });
2274
+ if (didContinueWith) {
2275
+ return;
2191
2276
  }
2192
- return groups2;
2193
- }, [nodes]);
2194
- const entries = useMemo(
2195
- () => Object.entries(groups).sort(([a], [b]) => groupSorter(a, b)),
2196
- [groups, groupSorter]
2277
+ setFlowContainer({
2278
+ flow: flow2,
2279
+ flowType: FlowType.Recovery,
2280
+ config
2281
+ });
2282
+ }).catch(
2283
+ handleFlowError({
2284
+ onRestartFlow: () => {
2285
+ onRedirect(recoveryUrl(config), true);
2286
+ },
2287
+ onValidationError: (body2) => {
2288
+ setFlowContainer({
2289
+ flow: body2,
2290
+ flowType: FlowType.Recovery,
2291
+ config
2292
+ });
2293
+ },
2294
+ onRedirect
2295
+ })
2197
2296
  );
2198
- return {
2199
- groups,
2200
- entries
2201
- };
2202
2297
  }
2203
- var NodeInput = ({
2204
- node,
2205
- attributes
2206
- }) => {
2298
+ async function onSubmitRegistration({ config, flow }, {
2299
+ setFlowContainer,
2300
+ body,
2301
+ onRedirect
2302
+ }) {
2207
2303
  var _a;
2208
- const { Node: Node2 } = useComponents();
2209
- const { setValue } = useFormContext();
2210
- const nodeType = attributes.type;
2211
- const {
2212
- onloadTrigger,
2213
- onclickTrigger,
2214
- // These properties do not exist on input fields so we remove them (as we already have handled them).
2215
- onclick: _ignoredOnclick,
2216
- onload: _ignoredOnload,
2217
- //
2218
- ...attrs
2219
- } = attributes;
2220
- const setFormValue = () => {
2221
- if (attrs.value) {
2222
- setValue(attrs.name, attrs.value);
2304
+ if (!config.sdk.url) {
2305
+ throw new Error(
2306
+ `Please supply your Ory Network SDK url to the Ory Elements configuration.`
2307
+ );
2308
+ }
2309
+ const client = frontendClient(config.sdk.url, (_a = config.sdk.options) != null ? _a : {});
2310
+ await client.updateRegistrationFlowRaw({
2311
+ flow: flow.id,
2312
+ updateRegistrationFlowBody: body
2313
+ }).then(async (res) => {
2314
+ const body2 = await res.value();
2315
+ const didContinueWith = handleContinueWith(body2.continue_with, {
2316
+ onRedirect
2317
+ });
2318
+ if (didContinueWith) {
2319
+ return;
2223
2320
  }
2224
- };
2225
- const hasRun = useRef(false);
2226
- useEffect(
2227
- () => {
2228
- setFormValue();
2229
- if (!hasRun.current && onloadTrigger) {
2230
- hasRun.current = true;
2231
- triggerToWindowCall(onloadTrigger);
2232
- }
2233
- },
2234
- // TODO(jonas): make sure onloadTrigger is stable
2235
- // eslint-disable-next-line react-hooks/exhaustive-deps -- ignore onloadTrigger for now, until we make sure this is stable
2236
- []
2321
+ onRedirect(registrationUrl(config), true);
2322
+ }).catch(
2323
+ handleFlowError({
2324
+ onRestartFlow: () => {
2325
+ onRedirect(registrationUrl(config), true);
2326
+ },
2327
+ onValidationError: (body2) => {
2328
+ setFlowContainer({
2329
+ flow: body2,
2330
+ flowType: FlowType.Registration,
2331
+ config
2332
+ });
2333
+ },
2334
+ onRedirect
2335
+ })
2237
2336
  );
2238
- const handleClick = () => {
2239
- setFormValue();
2240
- if (onclickTrigger) {
2241
- triggerToWindowCall(onclickTrigger);
2242
- }
2243
- };
2244
- const isSocial = (attrs.name === "provider" || attrs.name === "link") && node.group === "oidc";
2245
- const isPinCodeInput = attrs.name === "code" && node.group === "code" || attrs.name === "totp_code" && node.group === "totp";
2246
- const isResend = ((_a = node.meta.label) == null ? void 0 : _a.id) === 1070008;
2247
- switch (nodeType) {
2248
- case UiNodeInputAttributesTypeEnum.Submit:
2249
- case UiNodeInputAttributesTypeEnum.Button:
2250
- if (isSocial) {
2251
- return /* @__PURE__ */ jsx(Node2.OidcButton, { attributes: attrs, node });
2252
- }
2253
- if (isResend) {
2254
- return null;
2255
- }
2256
- return /* @__PURE__ */ jsx(Node2.Button, { attributes: attrs, node, onClick: handleClick });
2257
- case UiNodeInputAttributesTypeEnum.DatetimeLocal:
2258
- throw new Error("Not implemented");
2337
+ }
2338
+ async function onSubmitSettings({ config, flow }, {
2339
+ setFlowContainer,
2340
+ body,
2341
+ onRedirect
2342
+ }) {
2343
+ var _a;
2344
+ if (!config.sdk.url) {
2345
+ throw new Error(
2346
+ `Please supply your Ory Network SDK url to the Ory Elements configuration.`
2347
+ );
2348
+ }
2349
+ const client = frontendClient(config.sdk.url, (_a = config.sdk.options) != null ? _a : {});
2350
+ await client.updateSettingsFlowRaw({
2351
+ flow: flow.id,
2352
+ updateSettingsFlowBody: body
2353
+ }).then(async (res) => {
2354
+ const body2 = await res.value();
2355
+ const didContinueWith = handleContinueWith(body2.continue_with, {
2356
+ onRedirect
2357
+ });
2358
+ if (didContinueWith) {
2359
+ return;
2360
+ }
2361
+ onRedirect(settingsUrl(config), true);
2362
+ }).catch(
2363
+ handleFlowError({
2364
+ onRestartFlow: () => {
2365
+ onRedirect(settingsUrl(config), true);
2366
+ },
2367
+ onValidationError: (body2) => {
2368
+ setFlowContainer({
2369
+ flow: body2,
2370
+ flowType: FlowType.Settings,
2371
+ config
2372
+ });
2373
+ },
2374
+ onRedirect
2375
+ })
2376
+ ).catch((err) => {
2377
+ if (isResponseError(err)) {
2378
+ if (err.response.status === 401) {
2379
+ return onRedirect(
2380
+ loginUrl(config) + "?return_to=" + settingsUrl(config),
2381
+ true
2382
+ );
2383
+ }
2384
+ throw err;
2385
+ }
2386
+ });
2387
+ }
2388
+ async function onSubmitVerification({ config, flow }, {
2389
+ setFlowContainer,
2390
+ body,
2391
+ onRedirect
2392
+ }) {
2393
+ var _a;
2394
+ if (!config.sdk.url) {
2395
+ throw new Error(
2396
+ `Please supply your Ory Network SDK URL to the Ory Elements configuration.`
2397
+ );
2398
+ }
2399
+ await frontendClient(config.sdk.url, (_a = config.sdk.options) != null ? _a : {}).updateVerificationFlowRaw({
2400
+ flow: flow.id,
2401
+ updateVerificationFlowBody: body
2402
+ }).then(
2403
+ async (res) => setFlowContainer({
2404
+ flow: await res.value(),
2405
+ flowType: FlowType.Verification,
2406
+ config
2407
+ })
2408
+ ).catch(
2409
+ handleFlowError({
2410
+ onRestartFlow: () => {
2411
+ onRedirect(verificationUrl(config), true);
2412
+ },
2413
+ onValidationError: (body2) => {
2414
+ setFlowContainer({
2415
+ flow: body2,
2416
+ flowType: FlowType.Verification,
2417
+ config
2418
+ });
2419
+ },
2420
+ onRedirect
2421
+ })
2422
+ );
2423
+ }
2424
+ function computeDefaultValues(nodes) {
2425
+ return nodes.reduce((acc, node) => {
2426
+ const attrs = node.attributes;
2427
+ if (isUiNodeInputAttributes(attrs)) {
2428
+ if (attrs.name === "method" || attrs.type === "submit" || typeof attrs.value === "undefined")
2429
+ return acc;
2430
+ const unrolled = unrollTrait({
2431
+ name: attrs.name,
2432
+ value: attrs.value
2433
+ });
2434
+ Object.assign(acc, unrolled != null ? unrolled : { [attrs.name]: attrs.value });
2435
+ }
2436
+ return acc;
2437
+ }, {});
2438
+ }
2439
+ function unrollTrait(input, output = {}) {
2440
+ const keys = input.name.split(".");
2441
+ if (!keys.length) return void 0;
2442
+ let current = output;
2443
+ keys.forEach((key, index) => {
2444
+ if (!key) return;
2445
+ current = current[key] = index === keys.length - 1 ? input.value : current[key] || {};
2446
+ });
2447
+ return output;
2448
+ }
2449
+ function triggerToWindowCall(trigger) {
2450
+ if (!trigger) {
2451
+ return;
2452
+ }
2453
+ const fn = triggerToFunction(trigger);
2454
+ if (fn) {
2455
+ fn();
2456
+ return;
2457
+ }
2458
+ let i = 0;
2459
+ const ms = 100;
2460
+ const interval = setInterval(() => {
2461
+ i++;
2462
+ if (i > 100) {
2463
+ clearInterval(interval);
2464
+ throw new Error(
2465
+ "Unable to load Ory's WebAuthn script. Is it being blocked or otherwise failing to load? If you are running an old version of Ory Elements, please upgrade. For more information, please check your browser's developer console."
2466
+ );
2467
+ }
2468
+ const fn2 = triggerToFunction(trigger);
2469
+ if (fn2) {
2470
+ clearInterval(interval);
2471
+ return fn2();
2472
+ }
2473
+ }, ms);
2474
+ return;
2475
+ }
2476
+ function triggerToFunction(trigger) {
2477
+ if (typeof window === "undefined") {
2478
+ console.error(
2479
+ "The Ory SDK is missing a required function: window is undefined."
2480
+ );
2481
+ return void 0;
2482
+ }
2483
+ const typedWindow = window;
2484
+ if (!(trigger in typedWindow) || !typedWindow[trigger]) {
2485
+ console.error(`The Ory SDK is missing a required function: ${trigger}.`);
2486
+ return void 0;
2487
+ }
2488
+ const triggerFn = typedWindow[trigger];
2489
+ if (typeof triggerFn !== "function") {
2490
+ console.error(
2491
+ `The Ory SDK is missing a required function: ${trigger}. It is not a function.`
2492
+ );
2493
+ return void 0;
2494
+ }
2495
+ return triggerFn;
2496
+ }
2497
+ function useNodesGroups(nodes) {
2498
+ const groupSorter = useGroupSorter();
2499
+ const groups = useMemo(() => {
2500
+ var _a;
2501
+ const groups2 = {};
2502
+ for (const node of nodes) {
2503
+ if (node.type === "script") {
2504
+ continue;
2505
+ }
2506
+ const groupNodes = (_a = groups2[node.group]) != null ? _a : [];
2507
+ groupNodes.push(node);
2508
+ groups2[node.group] = groupNodes;
2509
+ }
2510
+ return groups2;
2511
+ }, [nodes]);
2512
+ const entries = useMemo(
2513
+ () => Object.entries(groups).sort(([a], [b]) => groupSorter(a, b)),
2514
+ [groups, groupSorter]
2515
+ );
2516
+ return {
2517
+ groups,
2518
+ entries
2519
+ };
2520
+ }
2521
+ var NodeInput = ({
2522
+ node,
2523
+ attributes
2524
+ }) => {
2525
+ var _a;
2526
+ const { Node: Node2 } = useComponents();
2527
+ const { setValue } = useFormContext();
2528
+ const {
2529
+ onloadTrigger,
2530
+ onclickTrigger,
2531
+ // These properties do not exist on input fields so we remove them (as we already have handled them).
2532
+ onclick: _ignoredOnclick,
2533
+ onload: _ignoredOnload,
2534
+ //
2535
+ ...attrs
2536
+ } = attributes;
2537
+ const setFormValue = () => {
2538
+ if (attrs.value) {
2539
+ setValue(attrs.name, attrs.value);
2540
+ }
2541
+ };
2542
+ const hasRun = useRef(false);
2543
+ useEffect(
2544
+ () => {
2545
+ setFormValue();
2546
+ if (!hasRun.current && onloadTrigger) {
2547
+ hasRun.current = true;
2548
+ triggerToWindowCall(onloadTrigger);
2549
+ }
2550
+ },
2551
+ // TODO(jonas): make sure onloadTrigger is stable
2552
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- ignore onloadTrigger for now, until we make sure this is stable
2553
+ []
2554
+ );
2555
+ const handleClick = () => {
2556
+ setFormValue();
2557
+ if (onclickTrigger) {
2558
+ triggerToWindowCall(onclickTrigger);
2559
+ }
2560
+ };
2561
+ const isSocial = (attrs.name === "provider" || attrs.name === "link") && node.group === "oidc";
2562
+ const isPinCodeInput = attrs.name === "code" && node.group === "code" || attrs.name === "totp_code" && node.group === "totp";
2563
+ const isResendNode = ((_a = node.meta.label) == null ? void 0 : _a.id) === 1070008;
2564
+ const isScreenSelectionNode = "name" in node.attributes && node.attributes.name === "screen";
2565
+ switch (attributes.type) {
2566
+ case UiNodeInputAttributesTypeEnum.Submit:
2567
+ case UiNodeInputAttributesTypeEnum.Button:
2568
+ if (isSocial) {
2569
+ return /* @__PURE__ */ jsx(Node2.OidcButton, { attributes: attrs, node });
2570
+ }
2571
+ if (isResendNode || isScreenSelectionNode) {
2572
+ return null;
2573
+ }
2574
+ return /* @__PURE__ */ jsx(Node2.Button, { attributes: attrs, node, onClick: handleClick });
2575
+ case UiNodeInputAttributesTypeEnum.DatetimeLocal:
2576
+ throw new Error("Not implemented");
2259
2577
  case UiNodeInputAttributesTypeEnum.Checkbox:
2260
2578
  return /* @__PURE__ */ jsx(Node2.Checkbox, { attributes: attrs, node, onClick: handleClick });
2261
2579
  case UiNodeInputAttributesTypeEnum.Hidden:
@@ -2362,245 +2680,11 @@ function OryFormSocialButtonsForm() {
2362
2680
  }
2363
2681
  return /* @__PURE__ */ jsx(OryForm, { children: /* @__PURE__ */ jsx(OryFormOidcButtons, {}) });
2364
2682
  }
2365
- function computeDefaultValues(nodes) {
2366
- return nodes.reduce((acc, node) => {
2367
- var _a;
2368
- if (isUiNodeInputAttributes(node.attributes)) {
2369
- if (node.attributes.name === "method") {
2370
- return acc;
2371
- }
2372
- if (node.attributes.type === "submit") {
2373
- return acc;
2374
- }
2375
- acc[node.attributes.name] = (_a = node.attributes.value) != null ? _a : "";
2376
- }
2377
- return acc;
2378
- }, {});
2379
- }
2380
- function frontendClient(sdkUrl, opts = {}) {
2381
- const config = new Configuration({
2382
- ...opts,
2383
- basePath: sdkUrl,
2384
- headers: {
2385
- Accept: "application/json",
2386
- ...opts.headers
2387
- }
2388
- });
2389
- return new FrontendApi(config);
2390
- }
2391
-
2392
- // src/util/onSubmitLogin.ts
2393
- async function onSubmitLogin({ config, flow }, {
2394
- setFlowContainer,
2395
- body,
2396
- onRedirect
2397
- }) {
2398
- var _a;
2399
- if (!config.sdk.url) {
2400
- throw new Error(
2401
- `Please supply your Ory Network SDK url to the Ory Elements configuration.`
2402
- );
2403
- }
2404
- await frontendClient(config.sdk.url, (_a = config.sdk.options) != null ? _a : {}).updateLoginFlowRaw({
2405
- flow: flow.id,
2406
- updateLoginFlowBody: body
2407
- }).then(() => {
2408
- var _a2;
2409
- window.location.href = (_a2 = flow.return_to) != null ? _a2 : config.sdk.url + "/self-service/login/browser";
2410
- }).catch(
2411
- handleFlowError({
2412
- onRestartFlow: () => {
2413
- onRedirect(loginUrl(config), true);
2414
- },
2415
- onValidationError: (body2) => {
2416
- setFlowContainer({
2417
- config,
2418
- flow: body2,
2419
- flowType: FlowType.Login
2420
- });
2421
- },
2422
- onRedirect
2423
- })
2424
- );
2425
- }
2426
- async function onSubmitRegistration({ config, flow }, {
2427
- setFlowContainer,
2428
- body,
2429
- onRedirect
2430
- }) {
2431
- var _a;
2432
- if (!config.sdk.url) {
2433
- throw new Error(
2434
- `Please supply your Ory Network SDK url to the Ory Elements configuration.`
2435
- );
2436
- }
2437
- const client = frontendClient(config.sdk.url, (_a = config.sdk.options) != null ? _a : {});
2438
- await client.updateRegistrationFlowRaw({
2439
- flow: flow.id,
2440
- updateRegistrationFlowBody: body
2441
- }).then(async (res) => {
2442
- const body2 = await res.value();
2443
- const didContinueWith = handleContinueWith(body2.continue_with, {
2444
- onRedirect
2445
- });
2446
- if (didContinueWith) {
2447
- return;
2448
- }
2449
- onRedirect(registrationUrl(config), true);
2450
- }).catch(
2451
- handleFlowError({
2452
- onRestartFlow: () => {
2453
- onRedirect(registrationUrl(config), true);
2454
- },
2455
- onValidationError: (body2) => {
2456
- setFlowContainer({
2457
- flow: body2,
2458
- flowType: FlowType.Registration,
2459
- config
2460
- });
2461
- },
2462
- onRedirect
2463
- })
2464
- );
2465
- }
2466
- async function onSubmitVerification({ config, flow }, {
2467
- setFlowContainer,
2468
- body,
2469
- onRedirect
2470
- }) {
2471
- var _a;
2472
- if (!config.sdk.url) {
2473
- throw new Error(
2474
- `Please supply your Ory Network SDK URL to the Ory Elements configuration.`
2475
- );
2476
- }
2477
- await frontendClient(config.sdk.url, (_a = config.sdk.options) != null ? _a : {}).updateVerificationFlowRaw({
2478
- flow: flow.id,
2479
- updateVerificationFlowBody: body
2480
- }).then(
2481
- async (res) => setFlowContainer({
2482
- flow: await res.value(),
2483
- flowType: FlowType.Verification,
2484
- config
2485
- })
2486
- ).catch(
2487
- handleFlowError({
2488
- onRestartFlow: () => {
2489
- onRedirect(verificationUrl(config), true);
2490
- },
2491
- onValidationError: (body2) => {
2492
- setFlowContainer({
2493
- flow: body2,
2494
- flowType: FlowType.Verification,
2495
- config
2496
- });
2497
- },
2498
- onRedirect
2499
- })
2500
- );
2501
- }
2502
- async function onSubmitRecovery({ config, flow }, {
2503
- setFlowContainer,
2504
- body,
2505
- onRedirect
2506
- }) {
2507
- var _a;
2508
- if (!config.sdk.url) {
2509
- throw new Error(
2510
- `Please supply your Ory Network SDK url to the Ory Elements configuration.`
2511
- );
2512
- }
2513
- await frontendClient(config.sdk.url, (_a = config.sdk.options) != null ? _a : {}).updateRecoveryFlowRaw({
2514
- flow: flow.id,
2515
- updateRecoveryFlowBody: body
2516
- }).then(async (res) => {
2517
- const flow2 = await res.value();
2518
- const didContinueWith = handleContinueWith(flow2.continue_with, {
2519
- onRedirect
2520
- });
2521
- if (didContinueWith) {
2522
- return;
2523
- }
2524
- setFlowContainer({
2525
- flow: flow2,
2526
- flowType: FlowType.Recovery,
2527
- config
2528
- });
2529
- }).catch(
2530
- handleFlowError({
2531
- onRestartFlow: () => {
2532
- onRedirect(recoveryUrl(config), true);
2533
- },
2534
- onValidationError: (body2) => {
2535
- setFlowContainer({
2536
- flow: body2,
2537
- flowType: FlowType.Recovery,
2538
- config
2539
- });
2540
- },
2541
- onRedirect
2542
- })
2543
- );
2544
- }
2545
- async function onSubmitSettings({ config, flow }, {
2546
- setFlowContainer,
2547
- body,
2548
- onRedirect
2549
- }) {
2550
- var _a;
2551
- if (!config.sdk.url) {
2552
- throw new Error(
2553
- `Please supply your Ory Network SDK url to the Ory Elements configuration.`
2554
- );
2555
- }
2556
- const client = frontendClient(config.sdk.url, (_a = config.sdk.options) != null ? _a : {});
2557
- await client.updateSettingsFlowRaw({
2558
- flow: flow.id,
2559
- updateSettingsFlowBody: body
2560
- }).then(async (res) => {
2561
- const body2 = await res.value();
2562
- const didContinueWith = handleContinueWith(body2.continue_with, {
2563
- onRedirect
2564
- });
2565
- if (didContinueWith) {
2566
- return;
2567
- }
2568
- onRedirect(settingsUrl(config), true);
2569
- }).catch(
2570
- handleFlowError({
2571
- onRestartFlow: () => {
2572
- onRedirect(settingsUrl(config), true);
2573
- },
2574
- onValidationError: (body2) => {
2575
- setFlowContainer({
2576
- flow: body2,
2577
- flowType: FlowType.Settings,
2578
- config
2579
- });
2580
- },
2581
- onRedirect
2582
- })
2583
- ).catch((err) => {
2584
- if (isResponseError(err)) {
2585
- if (err.response.status === 401) {
2586
- return onRedirect(
2587
- loginUrl(config) + "?return_to=" + settingsUrl(config),
2588
- true
2589
- );
2590
- }
2591
- throw err;
2592
- }
2593
- });
2594
- }
2595
- function OryForm({ children, onAfterSubmit, nodes }) {
2683
+ function OryForm({ children, onAfterSubmit }) {
2596
2684
  var _a;
2597
2685
  const { Form } = useComponents();
2598
2686
  const flowContainer = useOryFlow();
2599
- const defaultNodes = nodes ? flowContainer.flow.ui.nodes.filter((node) => node.group === UiNodeGroupEnum.Default).concat(nodes) : flowContainer.flow.ui.nodes;
2600
- const methods = useForm({
2601
- // TODO: Generify this, so we have typesafety in the submit handler.
2602
- defaultValues: computeDefaultValues(defaultNodes)
2603
- });
2687
+ const methods = useFormContext();
2604
2688
  const intl = useIntl();
2605
2689
  const onRedirect = (url, external) => {
2606
2690
  if (external) {
@@ -2713,7 +2797,7 @@ function OryForm({ children, onAfterSubmit, nodes }) {
2713
2797
  defaultMessage: "No authentication methods are available for this request. Please contact the site or app owner."
2714
2798
  });
2715
2799
  }
2716
- return /* @__PURE__ */ jsx(FormProvider, { ...methods, children: /* @__PURE__ */ jsx(
2800
+ return /* @__PURE__ */ jsx(
2717
2801
  Form.Root,
2718
2802
  {
2719
2803
  action: flowContainer.flow.ui.action,
@@ -2736,9 +2820,9 @@ function OryForm({ children, onAfterSubmit, nodes }) {
2736
2820
  )
2737
2821
  ] })
2738
2822
  }
2739
- ) });
2823
+ );
2740
2824
  }
2741
- var messageIdsToHide = [1040009];
2825
+ var messageIdsToHide = [1040009, 1060003, 1080003, 1010014, 1040005];
2742
2826
  function OryCardValidationMessages({ ...props }) {
2743
2827
  var _a;
2744
2828
  const { flow } = useOryFlow();
@@ -2751,9 +2835,21 @@ function OryCardValidationMessages({ ...props }) {
2751
2835
  }
2752
2836
  return /* @__PURE__ */ jsx(Message.Root, { ...props, children: messages == null ? void 0 : messages.map((message) => /* @__PURE__ */ jsx(Message.Content, { message }, message.id)) });
2753
2837
  }
2838
+ function OryFormProvider({
2839
+ children,
2840
+ nodes
2841
+ }) {
2842
+ const flowContainer = useOryFlow();
2843
+ const defaultNodes = nodes ? flowContainer.flow.ui.nodes.filter((node) => node.group === UiNodeGroupEnum.Default).concat(nodes) : flowContainer.flow.ui.nodes;
2844
+ const methods = useForm({
2845
+ // TODO: Generify this, so we have typesafety in the submit handler.
2846
+ defaultValues: computeDefaultValues(defaultNodes)
2847
+ });
2848
+ return /* @__PURE__ */ jsx(FormProvider, { ...methods, children });
2849
+ }
2754
2850
  function OryFormSection({ children, nodes }) {
2755
2851
  const { Card } = useComponents();
2756
- return /* @__PURE__ */ jsx(OryForm, { nodes, children: /* @__PURE__ */ jsx(Card.SettingsSection, { children }) });
2852
+ return /* @__PURE__ */ jsx(OryFormProvider, { nodes, children: /* @__PURE__ */ jsx(OryForm, { children: /* @__PURE__ */ jsx(Card.SettingsSection, { children }) }) });
2757
2853
  }
2758
2854
  function OryCardContent({ children }) {
2759
2855
  const { Card } = useComponents();
@@ -2785,38 +2881,18 @@ function OryCardContent({ children }) {
2785
2881
  function OryCard({ children }) {
2786
2882
  const { Card } = useComponents();
2787
2883
  if (children) {
2788
- return /* @__PURE__ */ jsx(Card.Root, { children });
2884
+ return /* @__PURE__ */ jsx(Card.Root, { children: /* @__PURE__ */ jsx(OryFormProvider, { children }) });
2789
2885
  }
2790
- return /* @__PURE__ */ jsxs(Card.Root, { children: [
2886
+ return /* @__PURE__ */ jsx(Card.Root, { children: /* @__PURE__ */ jsxs(OryFormProvider, { children: [
2791
2887
  /* @__PURE__ */ jsx(OryCardHeader, {}),
2792
2888
  /* @__PURE__ */ jsx(OryCardContent, {}),
2793
2889
  /* @__PURE__ */ jsx(OryCardFooter, {})
2794
- ] });
2890
+ ] }) });
2795
2891
  }
2796
2892
  function OryCardFooter() {
2797
2893
  const { Card } = useComponents();
2798
2894
  return /* @__PURE__ */ jsx(Card.Footer, {});
2799
2895
  }
2800
- function isChoosingMethod(uiNodes) {
2801
- return uiNodes.some(
2802
- (node) => "name" in node.attributes && node.attributes.name === "screen" && "value" in node.attributes && node.attributes.value === "previous"
2803
- ) || uiNodes.some(
2804
- (node) => node.group === UiNodeGroupEnum.IdentifierFirst && "name" in node.attributes && node.attributes.name === "identifier" && node.attributes.type === "hidden"
2805
- );
2806
- }
2807
- function filterZeroStepGroups(nodes) {
2808
- return nodes.filter((node) => node.group !== UiNodeGroupEnum.Oidc);
2809
- }
2810
- function getFinalNodes(uniqueGroups, selectedGroup) {
2811
- var _a, _b, _c;
2812
- const selectedNodes = selectedGroup ? (_a = uniqueGroups[selectedGroup]) != null ? _a : [] : [];
2813
- return [
2814
- ...(_b = uniqueGroups == null ? void 0 : uniqueGroups.identifier_first) != null ? _b : [],
2815
- ...(_c = uniqueGroups == null ? void 0 : uniqueGroups.default) != null ? _c : []
2816
- ].flat().filter(
2817
- (node) => "type" in node.attributes && node.attributes.type === "hidden"
2818
- ).concat(selectedNodes);
2819
- }
2820
2896
 
2821
2897
  // src/theme/default/utils/form.ts
2822
2898
  function isGroupImmediateSubmit(group) {
@@ -2825,13 +2901,10 @@ function isGroupImmediateSubmit(group) {
2825
2901
  function OryTwoStepCard() {
2826
2902
  var _a;
2827
2903
  const {
2828
- flow: { ui },
2829
- config
2904
+ flow: { ui }
2830
2905
  } = useOryFlow();
2831
- const choosingMethod = isChoosingMethod(ui.nodes);
2832
- const [selectedGroup, setSelectedGroup] = useState();
2833
2906
  const { Form } = useComponents();
2834
- const { flowType } = useOryFlow();
2907
+ const { flowType, formState, dispatchFormState } = useOryFlow();
2835
2908
  const nodeSorter = useNodeSorter();
2836
2909
  const sortNodes = (a, b) => nodeSorter(a, b, { flowType });
2837
2910
  const uniqueGroups = useNodesGroups(ui.nodes);
@@ -2848,38 +2921,42 @@ function OryTwoStepCard() {
2848
2921
  );
2849
2922
  const hasOidc = Boolean((_a = uniqueGroups.groups[UiNodeGroupEnum.Oidc]) == null ? void 0 : _a.length);
2850
2923
  const zeroStepGroups = filterZeroStepGroups(ui.nodes);
2851
- const finalNodes = getFinalNodes(uniqueGroups.groups, selectedGroup);
2852
- const step = selectedGroup ? 2 /* ExecuteAuthMethod */ : choosingMethod ? 1 /* ChooseAuthMethod */ : 0 /* ProvideIdentifier */;
2924
+ const finalNodes = formState.current === "method_active" ? getFinalNodes(uniqueGroups.groups, formState.method) : [];
2853
2925
  return /* @__PURE__ */ jsxs(OryCard, { children: [
2854
2926
  /* @__PURE__ */ jsx(OryCardHeader, {}),
2855
2927
  /* @__PURE__ */ jsxs(OryCardContent, { children: [
2856
2928
  /* @__PURE__ */ jsx(OryCardValidationMessages, {}),
2857
- step === 0 /* ProvideIdentifier */ && hasOidc && /* @__PURE__ */ jsx(OryFormSocialButtonsForm, {}),
2858
- /* @__PURE__ */ jsx(
2929
+ formState.current === "provide_identifier" && hasOidc && /* @__PURE__ */ jsx(OryFormSocialButtonsForm, {}),
2930
+ /* @__PURE__ */ jsxs(
2859
2931
  OryForm,
2860
2932
  {
2861
- onAfterSubmit: (method) => isGroupImmediateSubmit(method + "") ? setSelectedGroup(method) : void 0,
2862
- children: /* @__PURE__ */ jsxs(Form.Group, { children: [
2863
- step === 0 /* ProvideIdentifier */ && zeroStepGroups.sort(sortNodes).map((node, k) => /* @__PURE__ */ jsx(Node, { node }, k)),
2864
- step === 1 /* ChooseAuthMethod */ && /* @__PURE__ */ jsxs(Fragment, { children: [
2865
- flowType === FlowType.Login && /* @__PURE__ */ jsx(BackButton, { href: config.project.login_ui_url }),
2866
- /* @__PURE__ */ jsx(
2933
+ onAfterSubmit: (method) => isGroupImmediateSubmit(method + "") ? dispatchFormState({
2934
+ type: "action_select_method",
2935
+ method
2936
+ }) : void 0,
2937
+ children: [
2938
+ /* @__PURE__ */ jsxs(Form.Group, { children: [
2939
+ formState.current === "provide_identifier" && zeroStepGroups.sort(sortNodes).map((node, k) => /* @__PURE__ */ jsx(Node, { node }, k)),
2940
+ formState.current === "select_method" && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
2867
2941
  AuthMethodList,
2868
2942
  {
2869
2943
  options,
2870
- setSelectedGroup
2944
+ setSelectedGroup: (group) => dispatchFormState({
2945
+ type: "action_select_method",
2946
+ method: group
2947
+ })
2871
2948
  }
2872
- )
2949
+ ) }),
2950
+ formState.current === "method_active" && /* @__PURE__ */ jsxs(Fragment, { children: [
2951
+ ui.nodes.filter((n) => n.type === "script").map((node, k) => /* @__PURE__ */ jsx(Node, { node }, k)),
2952
+ finalNodes.sort(sortNodes).map((node, k) => /* @__PURE__ */ jsx(Node, { node }, k))
2953
+ ] })
2873
2954
  ] }),
2874
- step === 2 /* ExecuteAuthMethod */ && /* @__PURE__ */ jsxs(Fragment, { children: [
2875
- /* @__PURE__ */ jsx(BackButton, { onClick: () => setSelectedGroup(void 0) }),
2876
- finalNodes.sort(sortNodes).map((node, k) => /* @__PURE__ */ jsx(Node, { node }, k))
2877
- ] })
2878
- ] })
2955
+ /* @__PURE__ */ jsx(OryCardFooter, {})
2956
+ ]
2879
2957
  }
2880
2958
  )
2881
- ] }),
2882
- /* @__PURE__ */ jsx(OryCardFooter, {})
2959
+ ] })
2883
2960
  ] });
2884
2961
  }
2885
2962
  function AuthMethodList({ options, setSelectedGroup }) {
@@ -2901,32 +2978,6 @@ function AuthMethodList({ options, setSelectedGroup }) {
2901
2978
  option
2902
2979
  ));
2903
2980
  }
2904
- var BackButton = ({ onClick, href }) => {
2905
- const {
2906
- flow: { ui }
2907
- } = useOryFlow();
2908
- const { Node: Node2 } = useComponents();
2909
- const nodeBackButton = ui.nodes.find(
2910
- (node) => (
2911
- // ("value" in node.attributes &&
2912
- // node.attributes.value === "profile:back") ||
2913
- "name" in node.attributes && node.attributes.name === "identifier" && node.group === "identifier_first"
2914
- )
2915
- );
2916
- if (!nodeBackButton) {
2917
- return null;
2918
- }
2919
- return /* @__PURE__ */ jsx(
2920
- Node2.CurrentIdentifierButton,
2921
- {
2922
- node: nodeBackButton,
2923
- attributes: nodeBackButton.attributes,
2924
- onClick,
2925
- type: onClick ? "button" : void 0,
2926
- href
2927
- }
2928
- );
2929
- };
2930
2981
  function OryFormGroupDivider() {
2931
2982
  const { Card } = useComponents();
2932
2983
  const {