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

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,5 +1,5 @@
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, FlowType, handleFlowError, loginUrl, handleContinueWith, recoveryUrl, registrationUrl, settingsUrl, isResponseError, verificationUrl, UiNodeInputAttributesTypeEnum, Configuration, FrontendApi } from '@ory/client-fetch';
2
+ import { createContext, useContext, useState, useMemo, useReducer, useRef, useEffect } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { useIntl, IntlProvider as IntlProvider$1 } from 'react-intl';
5
5
  import { useFormContext, useForm, FormProvider } from 'react-hook-form';
@@ -83,6 +83,82 @@ 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 findMethodWithMessage(nodes) {
109
+ var _a;
110
+ return (_a = nodes == null ? void 0 : nodes.filter((n) => !["default", "identifier_first"].includes(n.group))) == null ? void 0 : _a.find((node) => {
111
+ var _a2;
112
+ return ((_a2 = node.messages) == null ? void 0 : _a2.length) > 0;
113
+ });
114
+ }
115
+ function parseStateFromFlow(flow) {
116
+ switch (flow.flowType) {
117
+ case FlowType.Registration:
118
+ case FlowType.Login: {
119
+ const methodWithMessage = findMethodWithMessage(flow.flow.ui.nodes);
120
+ if (flow.flow.active == "link_recovery") {
121
+ return { current: "method_active", method: "link" };
122
+ } else if (flow.flow.active == "code_recovery") {
123
+ return { current: "method_active", method: "code" };
124
+ } else if (methodWithMessage) {
125
+ return { current: "method_active", method: methodWithMessage.group };
126
+ } else if (flow.flow.active && !["default", "identifier_first"].includes(flow.flow.active)) {
127
+ return { current: "method_active", method: flow.flow.active };
128
+ } else if (isChoosingMethod(flow.flow.ui.nodes)) {
129
+ return { current: "select_method" };
130
+ }
131
+ return { current: "provide_identifier" };
132
+ }
133
+ case FlowType.Recovery:
134
+ case FlowType.Verification:
135
+ if (flow.flow.active === "code" || flow.flow.active === "link") {
136
+ if (flow.flow.state === "choose_method") {
137
+ return { current: "provide_identifier" };
138
+ }
139
+ return { current: "method_active", method: flow.flow.active };
140
+ }
141
+ break;
142
+ case FlowType.Settings:
143
+ return { current: "settings" };
144
+ }
145
+ console.warn(
146
+ `[Ory/Elements React] Encountered an unknown form state on ${flow.flowType} flow with ID ${flow.flow.id}`
147
+ );
148
+ throw new Error("Unknown form state");
149
+ }
150
+ function formStateReducer(state, action) {
151
+ switch (action.type) {
152
+ case "action_flow_update":
153
+ return parseStateFromFlow(action.flow);
154
+ case "action_select_method":
155
+ return { current: "method_active", method: action.method };
156
+ }
157
+ return state;
158
+ }
159
+ function useFormStateReducer(flow) {
160
+ return useReducer(formStateReducer, parseStateFromFlow(flow));
161
+ }
86
162
  function useOryFlow() {
87
163
  const ctx = useContext(OryFlowContext);
88
164
  if (!ctx) {
@@ -96,19 +172,21 @@ function OryFlowProvider({
96
172
  ...container
97
173
  }) {
98
174
  const [flowContainer, setFlowContainer] = useState(container);
175
+ const [formState, dispatchFormState] = useFormStateReducer(container);
99
176
  return /* @__PURE__ */ jsx(
100
177
  OryFlowContext.Provider,
101
178
  {
102
179
  value: {
103
180
  ...flowContainer,
104
- setFlowContainer: (updatedContainer) => {
105
- setFlowContainer(
106
- (container2) => ({
107
- ...container2,
108
- ...updatedContainer
109
- })
110
- );
111
- }
181
+ setFlowContainer: (flowContainer2) => {
182
+ setFlowContainer(flowContainer2);
183
+ dispatchFormState({
184
+ type: "action_flow_update",
185
+ flow: flowContainer2
186
+ });
187
+ },
188
+ formState,
189
+ dispatchFormState
112
190
  },
113
191
  children
114
192
  }
@@ -357,7 +435,8 @@ var en_default = {
357
435
  "settings.webauthn.info": "Hardware Tokens are used for second-factor authentication or as first-factor with Passkeys",
358
436
  "settings.passkey.title": "Manage Passkeys",
359
437
  "settings.passkey.description": "Manage your passkey settings",
360
- "settings.passkey.info": "Manage your passkey settings"
438
+ "settings.passkey.info": "Manage your passkey settings",
439
+ "card.footer.select-another-method": "Select another method"
361
440
  };
362
441
 
363
442
  // src/locales/de.json
@@ -602,7 +681,8 @@ var de_default = {
602
681
  "settings.title-profile": "Profileinstellungen",
603
682
  "settings.title-totp": "Verwalten Sie die 2FA TOTP Authenticator-App",
604
683
  "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"
684
+ "settings.webauthn.info": "Hardware-Tokens werden f\xFCr die Zweitfaktor-Authentifizierung oder als Erstfaktor-Authentifizierung mit Passkeys verwendet",
685
+ "card.footer.select-another-method": "Eine andere Methode verwenden"
606
686
  };
607
687
 
608
688
  // src/locales/es.json
@@ -847,7 +927,8 @@ var es_default = {
847
927
  "settings.title-profile": "",
848
928
  "settings.title-totp": "",
849
929
  "settings.title-webauthn": "",
850
- "settings.webauthn.info": ""
930
+ "settings.webauthn.info": "",
931
+ "card.footer.select-another-method": ""
851
932
  };
852
933
 
853
934
  // src/locales/fr.json
@@ -1092,7 +1173,8 @@ var fr_default = {
1092
1173
  "settings.title-webauthn": "",
1093
1174
  "settings.webauthn.description": "",
1094
1175
  "settings.webauthn.info": "",
1095
- "settings.webauthn.title": ""
1176
+ "settings.webauthn.title": "",
1177
+ "card.footer.select-another-method": ""
1096
1178
  };
1097
1179
 
1098
1180
  // src/locales/nl.json
@@ -1337,7 +1419,8 @@ var nl_default = {
1337
1419
  "settings.title-webauthn": "",
1338
1420
  "settings.webauthn.description": "",
1339
1421
  "settings.webauthn.info": "",
1340
- "settings.webauthn.title": ""
1422
+ "settings.webauthn.title": "",
1423
+ "card.footer.select-another-method": ""
1341
1424
  };
1342
1425
 
1343
1426
  // src/locales/pl.json
@@ -1582,7 +1665,8 @@ var pl_default = {
1582
1665
  "settings.title-webauthn": "",
1583
1666
  "settings.webauthn.description": "",
1584
1667
  "settings.webauthn.info": "",
1585
- "settings.webauthn.title": ""
1668
+ "settings.webauthn.title": "",
1669
+ "card.footer.select-another-method": ""
1586
1670
  };
1587
1671
 
1588
1672
  // src/locales/pt.json
@@ -1827,7 +1911,8 @@ var pt_default = {
1827
1911
  "settings.title-webauthn": "",
1828
1912
  "settings.webauthn.description": "",
1829
1913
  "settings.webauthn.info": "",
1830
- "settings.webauthn.title": ""
1914
+ "settings.webauthn.title": "",
1915
+ "card.footer.select-another-method": ""
1831
1916
  };
1832
1917
 
1833
1918
  // src/locales/sv.json
@@ -2072,7 +2157,8 @@ var sv_default = {
2072
2157
  "settings.title-webauthn": "Hantera maskinvarutokens",
2073
2158
  "settings.webauthn.description": "Hantera inst\xE4llningarna f\xF6r din maskinvarutoken",
2074
2159
  "settings.webauthn.info": "H\xE5rdvarutokens anv\xE4nds f\xF6r andrafaktorsautentisering eller som f\xF6rstafaktor med l\xF6senordsnycklar",
2075
- "settings.webauthn.title": "Hantera maskinvarutokens"
2160
+ "settings.webauthn.title": "Hantera maskinvarutokens",
2161
+ "card.footer.select-another-method": "V\xE4lj en annan metod"
2076
2162
  };
2077
2163
 
2078
2164
  // src/locales/index.ts
@@ -2131,126 +2217,369 @@ function OryCardHeader() {
2131
2217
  const { Card } = useComponents();
2132
2218
  return /* @__PURE__ */ jsx(Card.Header, {});
2133
2219
  }
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();
2220
+ function frontendClient(sdkUrl, opts = {}) {
2221
+ const config = new Configuration({
2222
+ ...opts,
2223
+ basePath: sdkUrl,
2224
+ headers: {
2225
+ Accept: "application/json",
2226
+ ...opts.headers
2157
2227
  }
2158
- }, ms);
2159
- return;
2228
+ });
2229
+ return new FrontendApi(config);
2160
2230
  }
2161
- function triggerToFunction(trigger) {
2162
- if (typeof window === "undefined") {
2163
- console.error(
2164
- "The Ory SDK is missing a required function: window is undefined."
2231
+
2232
+ // src/util/onSubmitLogin.ts
2233
+ async function onSubmitLogin({ config, flow }, {
2234
+ setFlowContainer,
2235
+ body,
2236
+ onRedirect
2237
+ }) {
2238
+ var _a;
2239
+ if (!config.sdk.url) {
2240
+ throw new Error(
2241
+ `Please supply your Ory Network SDK url to the Ory Elements configuration.`
2165
2242
  );
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
2243
  }
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.`
2244
+ await frontendClient(config.sdk.url, (_a = config.sdk.options) != null ? _a : {}).updateLoginFlowRaw({
2245
+ flow: flow.id,
2246
+ updateLoginFlowBody: body
2247
+ }).then(() => {
2248
+ var _a2;
2249
+ window.location.href = (_a2 = flow.return_to) != null ? _a2 : config.sdk.url + "/self-service/login/browser";
2250
+ }).catch(
2251
+ handleFlowError({
2252
+ onRestartFlow: () => {
2253
+ onRedirect(loginUrl(config), true);
2254
+ },
2255
+ onValidationError: (body2) => {
2256
+ setFlowContainer({
2257
+ config,
2258
+ flow: body2,
2259
+ flowType: FlowType.Login
2260
+ });
2261
+ },
2262
+ onRedirect
2263
+ })
2264
+ );
2265
+ }
2266
+ async function onSubmitRecovery({ config, flow }, {
2267
+ setFlowContainer,
2268
+ body,
2269
+ onRedirect
2270
+ }) {
2271
+ var _a;
2272
+ if (!config.sdk.url) {
2273
+ throw new Error(
2274
+ `Please supply your Ory Network SDK url to the Ory Elements configuration.`
2177
2275
  );
2178
- return void 0;
2179
2276
  }
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;
2277
+ await frontendClient(config.sdk.url, (_a = config.sdk.options) != null ? _a : {}).updateRecoveryFlowRaw({
2278
+ flow: flow.id,
2279
+ updateRecoveryFlowBody: body
2280
+ }).then(async (res) => {
2281
+ const flow2 = await res.value();
2282
+ const didContinueWith = handleContinueWith(flow2.continue_with, {
2283
+ onRedirect
2284
+ });
2285
+ if (didContinueWith) {
2286
+ return;
2191
2287
  }
2192
- return groups2;
2193
- }, [nodes]);
2194
- const entries = useMemo(
2195
- () => Object.entries(groups).sort(([a], [b]) => groupSorter(a, b)),
2196
- [groups, groupSorter]
2288
+ setFlowContainer({
2289
+ flow: flow2,
2290
+ flowType: FlowType.Recovery,
2291
+ config
2292
+ });
2293
+ }).catch(
2294
+ handleFlowError({
2295
+ onRestartFlow: () => {
2296
+ onRedirect(recoveryUrl(config), true);
2297
+ },
2298
+ onValidationError: (body2) => {
2299
+ setFlowContainer({
2300
+ flow: body2,
2301
+ flowType: FlowType.Recovery,
2302
+ config
2303
+ });
2304
+ },
2305
+ onRedirect
2306
+ })
2197
2307
  );
2198
- return {
2199
- groups,
2200
- entries
2201
- };
2202
2308
  }
2203
- var NodeInput = ({
2204
- node,
2205
- attributes
2206
- }) => {
2309
+ async function onSubmitRegistration({ config, flow }, {
2310
+ setFlowContainer,
2311
+ body,
2312
+ onRedirect
2313
+ }) {
2207
2314
  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);
2315
+ if (!config.sdk.url) {
2316
+ throw new Error(
2317
+ `Please supply your Ory Network SDK url to the Ory Elements configuration.`
2318
+ );
2319
+ }
2320
+ const client = frontendClient(config.sdk.url, (_a = config.sdk.options) != null ? _a : {});
2321
+ await client.updateRegistrationFlowRaw({
2322
+ flow: flow.id,
2323
+ updateRegistrationFlowBody: body
2324
+ }).then(async (res) => {
2325
+ const body2 = await res.value();
2326
+ const didContinueWith = handleContinueWith(body2.continue_with, {
2327
+ onRedirect
2328
+ });
2329
+ if (didContinueWith) {
2330
+ return;
2223
2331
  }
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
- []
2332
+ onRedirect(registrationUrl(config), true);
2333
+ }).catch(
2334
+ handleFlowError({
2335
+ onRestartFlow: () => {
2336
+ onRedirect(registrationUrl(config), true);
2337
+ },
2338
+ onValidationError: (body2) => {
2339
+ setFlowContainer({
2340
+ flow: body2,
2341
+ flowType: FlowType.Registration,
2342
+ config
2343
+ });
2344
+ },
2345
+ onRedirect
2346
+ })
2237
2347
  );
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) {
2348
+ }
2349
+ async function onSubmitSettings({ config, flow }, {
2350
+ setFlowContainer,
2351
+ body,
2352
+ onRedirect
2353
+ }) {
2354
+ var _a;
2355
+ if (!config.sdk.url) {
2356
+ throw new Error(
2357
+ `Please supply your Ory Network SDK url to the Ory Elements configuration.`
2358
+ );
2359
+ }
2360
+ const client = frontendClient(config.sdk.url, (_a = config.sdk.options) != null ? _a : {});
2361
+ await client.updateSettingsFlowRaw({
2362
+ flow: flow.id,
2363
+ updateSettingsFlowBody: body
2364
+ }).then(async (res) => {
2365
+ const body2 = await res.value();
2366
+ const didContinueWith = handleContinueWith(body2.continue_with, {
2367
+ onRedirect
2368
+ });
2369
+ if (didContinueWith) {
2370
+ return;
2371
+ }
2372
+ onRedirect(settingsUrl(config), true);
2373
+ }).catch(
2374
+ handleFlowError({
2375
+ onRestartFlow: () => {
2376
+ onRedirect(settingsUrl(config), true);
2377
+ },
2378
+ onValidationError: (body2) => {
2379
+ setFlowContainer({
2380
+ flow: body2,
2381
+ flowType: FlowType.Settings,
2382
+ config
2383
+ });
2384
+ },
2385
+ onRedirect
2386
+ })
2387
+ ).catch((err) => {
2388
+ if (isResponseError(err)) {
2389
+ if (err.response.status === 401) {
2390
+ return onRedirect(
2391
+ loginUrl(config) + "?return_to=" + settingsUrl(config),
2392
+ true
2393
+ );
2394
+ }
2395
+ throw err;
2396
+ }
2397
+ });
2398
+ }
2399
+ async function onSubmitVerification({ config, flow }, {
2400
+ setFlowContainer,
2401
+ body,
2402
+ onRedirect
2403
+ }) {
2404
+ var _a;
2405
+ if (!config.sdk.url) {
2406
+ throw new Error(
2407
+ `Please supply your Ory Network SDK URL to the Ory Elements configuration.`
2408
+ );
2409
+ }
2410
+ await frontendClient(config.sdk.url, (_a = config.sdk.options) != null ? _a : {}).updateVerificationFlowRaw({
2411
+ flow: flow.id,
2412
+ updateVerificationFlowBody: body
2413
+ }).then(
2414
+ async (res) => setFlowContainer({
2415
+ flow: await res.value(),
2416
+ flowType: FlowType.Verification,
2417
+ config
2418
+ })
2419
+ ).catch(
2420
+ handleFlowError({
2421
+ onRestartFlow: () => {
2422
+ onRedirect(verificationUrl(config), true);
2423
+ },
2424
+ onValidationError: (body2) => {
2425
+ setFlowContainer({
2426
+ flow: body2,
2427
+ flowType: FlowType.Verification,
2428
+ config
2429
+ });
2430
+ },
2431
+ onRedirect
2432
+ })
2433
+ );
2434
+ }
2435
+ function computeDefaultValues(nodes) {
2436
+ return nodes.reduce((acc, node) => {
2437
+ const attrs = node.attributes;
2438
+ if (isUiNodeInputAttributes(attrs)) {
2439
+ if (attrs.name === "method" || attrs.type === "submit" || typeof attrs.value === "undefined")
2440
+ return acc;
2441
+ const unrolled = unrollTrait({
2442
+ name: attrs.name,
2443
+ value: attrs.value
2444
+ });
2445
+ Object.assign(acc, unrolled != null ? unrolled : { [attrs.name]: attrs.value });
2446
+ }
2447
+ return acc;
2448
+ }, {});
2449
+ }
2450
+ function unrollTrait(input, output = {}) {
2451
+ const keys = input.name.split(".");
2452
+ if (!keys.length) return void 0;
2453
+ let current = output;
2454
+ keys.forEach((key, index) => {
2455
+ if (!key) return;
2456
+ current = current[key] = index === keys.length - 1 ? input.value : current[key] || {};
2457
+ });
2458
+ return output;
2459
+ }
2460
+ function triggerToWindowCall(trigger) {
2461
+ if (!trigger) {
2462
+ return;
2463
+ }
2464
+ const fn = triggerToFunction(trigger);
2465
+ if (fn) {
2466
+ fn();
2467
+ return;
2468
+ }
2469
+ let i = 0;
2470
+ const ms = 100;
2471
+ const interval = setInterval(() => {
2472
+ i++;
2473
+ if (i > 100) {
2474
+ clearInterval(interval);
2475
+ throw new Error(
2476
+ "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."
2477
+ );
2478
+ }
2479
+ const fn2 = triggerToFunction(trigger);
2480
+ if (fn2) {
2481
+ clearInterval(interval);
2482
+ return fn2();
2483
+ }
2484
+ }, ms);
2485
+ return;
2486
+ }
2487
+ function triggerToFunction(trigger) {
2488
+ if (typeof window === "undefined") {
2489
+ console.error(
2490
+ "The Ory SDK is missing a required function: window is undefined."
2491
+ );
2492
+ return void 0;
2493
+ }
2494
+ const typedWindow = window;
2495
+ if (!(trigger in typedWindow) || !typedWindow[trigger]) {
2496
+ console.error(`The Ory SDK is missing a required function: ${trigger}.`);
2497
+ return void 0;
2498
+ }
2499
+ const triggerFn = typedWindow[trigger];
2500
+ if (typeof triggerFn !== "function") {
2501
+ console.error(
2502
+ `The Ory SDK is missing a required function: ${trigger}. It is not a function.`
2503
+ );
2504
+ return void 0;
2505
+ }
2506
+ return triggerFn;
2507
+ }
2508
+ function useNodesGroups(nodes) {
2509
+ const groupSorter = useGroupSorter();
2510
+ const groups = useMemo(() => {
2511
+ var _a;
2512
+ const groups2 = {};
2513
+ for (const node of nodes) {
2514
+ if (node.type === "script") {
2515
+ continue;
2516
+ }
2517
+ const groupNodes = (_a = groups2[node.group]) != null ? _a : [];
2518
+ groupNodes.push(node);
2519
+ groups2[node.group] = groupNodes;
2520
+ }
2521
+ return groups2;
2522
+ }, [nodes]);
2523
+ const entries = useMemo(
2524
+ () => Object.entries(groups).sort(([a], [b]) => groupSorter(a, b)),
2525
+ [groups, groupSorter]
2526
+ );
2527
+ return {
2528
+ groups,
2529
+ entries
2530
+ };
2531
+ }
2532
+ var NodeInput = ({
2533
+ node,
2534
+ attributes
2535
+ }) => {
2536
+ var _a;
2537
+ const { Node: Node2 } = useComponents();
2538
+ const { setValue } = useFormContext();
2539
+ const {
2540
+ onloadTrigger,
2541
+ onclickTrigger,
2542
+ // These properties do not exist on input fields so we remove them (as we already have handled them).
2543
+ onclick: _ignoredOnclick,
2544
+ onload: _ignoredOnload,
2545
+ //
2546
+ ...attrs
2547
+ } = attributes;
2548
+ const setFormValue = () => {
2549
+ if (attrs.value) {
2550
+ setValue(attrs.name, attrs.value);
2551
+ }
2552
+ };
2553
+ const hasRun = useRef(false);
2554
+ useEffect(
2555
+ () => {
2556
+ setFormValue();
2557
+ if (!hasRun.current && onloadTrigger) {
2558
+ hasRun.current = true;
2559
+ triggerToWindowCall(onloadTrigger);
2560
+ }
2561
+ },
2562
+ // TODO(jonas): make sure onloadTrigger is stable
2563
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- ignore onloadTrigger for now, until we make sure this is stable
2564
+ []
2565
+ );
2566
+ const handleClick = () => {
2567
+ setFormValue();
2568
+ if (onclickTrigger) {
2569
+ triggerToWindowCall(onclickTrigger);
2570
+ }
2571
+ };
2572
+ const isSocial = (attrs.name === "provider" || attrs.name === "link") && node.group === "oidc";
2573
+ const isPinCodeInput = attrs.name === "code" && node.group === "code" || attrs.name === "totp_code" && node.group === "totp";
2574
+ const isResendNode = ((_a = node.meta.label) == null ? void 0 : _a.id) === 1070008;
2575
+ const isScreenSelectionNode = "name" in node.attributes && node.attributes.name === "screen";
2576
+ switch (attributes.type) {
2577
+ case UiNodeInputAttributesTypeEnum.Submit:
2578
+ case UiNodeInputAttributesTypeEnum.Button:
2579
+ if (isSocial) {
2580
+ return /* @__PURE__ */ jsx(Node2.OidcButton, { attributes: attrs, node });
2581
+ }
2582
+ if (isResendNode || isScreenSelectionNode) {
2254
2583
  return null;
2255
2584
  }
2256
2585
  return /* @__PURE__ */ jsx(Node2.Button, { attributes: attrs, node, onClick: handleClick });
@@ -2362,245 +2691,11 @@ function OryFormSocialButtonsForm() {
2362
2691
  }
2363
2692
  return /* @__PURE__ */ jsx(OryForm, { children: /* @__PURE__ */ jsx(OryFormOidcButtons, {}) });
2364
2693
  }
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 }) {
2694
+ function OryForm({ children, onAfterSubmit }) {
2596
2695
  var _a;
2597
2696
  const { Form } = useComponents();
2598
2697
  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
- });
2698
+ const methods = useFormContext();
2604
2699
  const intl = useIntl();
2605
2700
  const onRedirect = (url, external) => {
2606
2701
  if (external) {
@@ -2693,6 +2788,12 @@ function OryForm({ children, onAfterSubmit, nodes }) {
2693
2788
  break;
2694
2789
  }
2695
2790
  }
2791
+ if ("password" in data) {
2792
+ methods.setValue("password", "");
2793
+ }
2794
+ if ("code" in data) {
2795
+ methods.setValue("code", "");
2796
+ }
2696
2797
  onAfterSubmit == null ? void 0 : onAfterSubmit(data.method);
2697
2798
  };
2698
2799
  const hasMethods = flowContainer.flow.ui.nodes.filter((node) => {
@@ -2713,7 +2814,7 @@ function OryForm({ children, onAfterSubmit, nodes }) {
2713
2814
  defaultMessage: "No authentication methods are available for this request. Please contact the site or app owner."
2714
2815
  });
2715
2816
  }
2716
- return /* @__PURE__ */ jsx(FormProvider, { ...methods, children: /* @__PURE__ */ jsx(
2817
+ return /* @__PURE__ */ jsx(
2717
2818
  Form.Root,
2718
2819
  {
2719
2820
  action: flowContainer.flow.ui.action,
@@ -2736,9 +2837,9 @@ function OryForm({ children, onAfterSubmit, nodes }) {
2736
2837
  )
2737
2838
  ] })
2738
2839
  }
2739
- ) });
2840
+ );
2740
2841
  }
2741
- var messageIdsToHide = [1040009];
2842
+ var messageIdsToHide = [1040009, 1060003, 1080003, 1010014, 1040005];
2742
2843
  function OryCardValidationMessages({ ...props }) {
2743
2844
  var _a;
2744
2845
  const { flow } = useOryFlow();
@@ -2751,9 +2852,21 @@ function OryCardValidationMessages({ ...props }) {
2751
2852
  }
2752
2853
  return /* @__PURE__ */ jsx(Message.Root, { ...props, children: messages == null ? void 0 : messages.map((message) => /* @__PURE__ */ jsx(Message.Content, { message }, message.id)) });
2753
2854
  }
2855
+ function OryFormProvider({
2856
+ children,
2857
+ nodes
2858
+ }) {
2859
+ const flowContainer = useOryFlow();
2860
+ const defaultNodes = nodes ? flowContainer.flow.ui.nodes.filter((node) => node.group === UiNodeGroupEnum.Default).concat(nodes) : flowContainer.flow.ui.nodes;
2861
+ const methods = useForm({
2862
+ // TODO: Generify this, so we have typesafety in the submit handler.
2863
+ defaultValues: computeDefaultValues(defaultNodes)
2864
+ });
2865
+ return /* @__PURE__ */ jsx(FormProvider, { ...methods, children });
2866
+ }
2754
2867
  function OryFormSection({ children, nodes }) {
2755
2868
  const { Card } = useComponents();
2756
- return /* @__PURE__ */ jsx(OryForm, { nodes, children: /* @__PURE__ */ jsx(Card.SettingsSection, { children }) });
2869
+ return /* @__PURE__ */ jsx(OryFormProvider, { nodes, children: /* @__PURE__ */ jsx(OryForm, { children: /* @__PURE__ */ jsx(Card.SettingsSection, { children }) }) });
2757
2870
  }
2758
2871
  function OryCardContent({ children }) {
2759
2872
  const { Card } = useComponents();
@@ -2785,38 +2898,18 @@ function OryCardContent({ children }) {
2785
2898
  function OryCard({ children }) {
2786
2899
  const { Card } = useComponents();
2787
2900
  if (children) {
2788
- return /* @__PURE__ */ jsx(Card.Root, { children });
2901
+ return /* @__PURE__ */ jsx(Card.Root, { children: /* @__PURE__ */ jsx(OryFormProvider, { children }) });
2789
2902
  }
2790
- return /* @__PURE__ */ jsxs(Card.Root, { children: [
2903
+ return /* @__PURE__ */ jsx(Card.Root, { children: /* @__PURE__ */ jsxs(OryFormProvider, { children: [
2791
2904
  /* @__PURE__ */ jsx(OryCardHeader, {}),
2792
2905
  /* @__PURE__ */ jsx(OryCardContent, {}),
2793
2906
  /* @__PURE__ */ jsx(OryCardFooter, {})
2794
- ] });
2907
+ ] }) });
2795
2908
  }
2796
2909
  function OryCardFooter() {
2797
2910
  const { Card } = useComponents();
2798
2911
  return /* @__PURE__ */ jsx(Card.Footer, {});
2799
2912
  }
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
2913
 
2821
2914
  // src/theme/default/utils/form.ts
2822
2915
  function isGroupImmediateSubmit(group) {
@@ -2825,13 +2918,10 @@ function isGroupImmediateSubmit(group) {
2825
2918
  function OryTwoStepCard() {
2826
2919
  var _a;
2827
2920
  const {
2828
- flow: { ui },
2829
- config
2921
+ flow: { ui }
2830
2922
  } = useOryFlow();
2831
- const choosingMethod = isChoosingMethod(ui.nodes);
2832
- const [selectedGroup, setSelectedGroup] = useState();
2833
2923
  const { Form } = useComponents();
2834
- const { flowType } = useOryFlow();
2924
+ const { flowType, formState, dispatchFormState } = useOryFlow();
2835
2925
  const nodeSorter = useNodeSorter();
2836
2926
  const sortNodes = (a, b) => nodeSorter(a, b, { flowType });
2837
2927
  const uniqueGroups = useNodesGroups(ui.nodes);
@@ -2848,38 +2938,42 @@ function OryTwoStepCard() {
2848
2938
  );
2849
2939
  const hasOidc = Boolean((_a = uniqueGroups.groups[UiNodeGroupEnum.Oidc]) == null ? void 0 : _a.length);
2850
2940
  const zeroStepGroups = filterZeroStepGroups(ui.nodes);
2851
- const finalNodes = getFinalNodes(uniqueGroups.groups, selectedGroup);
2852
- const step = selectedGroup ? 2 /* ExecuteAuthMethod */ : choosingMethod ? 1 /* ChooseAuthMethod */ : 0 /* ProvideIdentifier */;
2941
+ const finalNodes = formState.current === "method_active" ? getFinalNodes(uniqueGroups.groups, formState.method) : [];
2853
2942
  return /* @__PURE__ */ jsxs(OryCard, { children: [
2854
2943
  /* @__PURE__ */ jsx(OryCardHeader, {}),
2855
2944
  /* @__PURE__ */ jsxs(OryCardContent, { children: [
2856
2945
  /* @__PURE__ */ jsx(OryCardValidationMessages, {}),
2857
- step === 0 /* ProvideIdentifier */ && hasOidc && /* @__PURE__ */ jsx(OryFormSocialButtonsForm, {}),
2858
- /* @__PURE__ */ jsx(
2946
+ formState.current === "provide_identifier" && hasOidc && /* @__PURE__ */ jsx(OryFormSocialButtonsForm, {}),
2947
+ /* @__PURE__ */ jsxs(
2859
2948
  OryForm,
2860
2949
  {
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(
2950
+ onAfterSubmit: (method) => isGroupImmediateSubmit(method + "") ? dispatchFormState({
2951
+ type: "action_select_method",
2952
+ method
2953
+ }) : void 0,
2954
+ children: [
2955
+ /* @__PURE__ */ jsxs(Form.Group, { children: [
2956
+ formState.current === "provide_identifier" && zeroStepGroups.sort(sortNodes).map((node, k) => /* @__PURE__ */ jsx(Node, { node }, k)),
2957
+ formState.current === "select_method" && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
2867
2958
  AuthMethodList,
2868
2959
  {
2869
2960
  options,
2870
- setSelectedGroup
2961
+ setSelectedGroup: (group) => dispatchFormState({
2962
+ type: "action_select_method",
2963
+ method: group
2964
+ })
2871
2965
  }
2872
- )
2966
+ ) }),
2967
+ formState.current === "method_active" && /* @__PURE__ */ jsxs(Fragment, { children: [
2968
+ ui.nodes.filter((n) => n.type === "script").map((node, k) => /* @__PURE__ */ jsx(Node, { node }, k)),
2969
+ finalNodes.sort(sortNodes).map((node, k) => /* @__PURE__ */ jsx(Node, { node }, k))
2970
+ ] })
2873
2971
  ] }),
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
- ] })
2972
+ /* @__PURE__ */ jsx(OryCardFooter, {})
2973
+ ]
2879
2974
  }
2880
2975
  )
2881
- ] }),
2882
- /* @__PURE__ */ jsx(OryCardFooter, {})
2976
+ ] })
2883
2977
  ] });
2884
2978
  }
2885
2979
  function AuthMethodList({ options, setSelectedGroup }) {
@@ -2901,32 +2995,6 @@ function AuthMethodList({ options, setSelectedGroup }) {
2901
2995
  option
2902
2996
  ));
2903
2997
  }
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
2998
  function OryFormGroupDivider() {
2931
2999
  const { Card } = useComponents();
2932
3000
  const {