@ory/elements-react 1.0.0-next.19 → 1.0.0-next.20
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/CHANGELOG.md +16 -0
- package/dist/index.js +170 -92
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +170 -92
- package/dist/index.mjs.map +1 -1
- package/dist/theme/default/index.js +64 -40
- package/dist/theme/default/index.js.map +1 -1
- package/dist/theme/default/index.mjs +64 -40
- package/dist/theme/default/index.mjs.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
## 1.0.0-next.20 (2025-01-16)
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- handle state transition edge cases ([f2e4023](https://github.com/ory/elements/commit/f2e4023))
|
|
6
|
+
- user experience improvements and e2e test coverage ([f68744c](https://github.com/ory/elements/commit/f68744c))
|
|
7
|
+
- do not show two-step selector if only one method exists ([6453673](https://github.com/ory/elements/commit/6453673))
|
|
8
|
+
|
|
9
|
+
### 🩹 Fixes
|
|
10
|
+
|
|
11
|
+
- better validation for code method ([b0d8e2c](https://github.com/ory/elements/commit/b0d8e2c))
|
|
12
|
+
|
|
13
|
+
### ❤️ Thank You
|
|
14
|
+
|
|
15
|
+
- aeneasr @aeneasr
|
|
16
|
+
|
|
1
17
|
## 1.0.0-next.19 (2024-12-31)
|
|
2
18
|
|
|
3
19
|
### 🩹 Fixes
|
package/dist/index.js
CHANGED
|
@@ -105,6 +105,101 @@ function getFinalNodes(uniqueGroups, selectedGroup) {
|
|
|
105
105
|
(node) => "type" in node.attributes && node.attributes.type === "hidden"
|
|
106
106
|
).concat(selectedNodes);
|
|
107
107
|
}
|
|
108
|
+
function triggerToWindowCall(trigger) {
|
|
109
|
+
if (!trigger) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const fn = triggerToFunction(trigger);
|
|
113
|
+
if (fn) {
|
|
114
|
+
fn();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
let i = 0;
|
|
118
|
+
const ms = 100;
|
|
119
|
+
const interval = setInterval(() => {
|
|
120
|
+
i++;
|
|
121
|
+
if (i > 100) {
|
|
122
|
+
clearInterval(interval);
|
|
123
|
+
throw new Error(
|
|
124
|
+
"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."
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
const fn2 = triggerToFunction(trigger);
|
|
128
|
+
if (fn2) {
|
|
129
|
+
clearInterval(interval);
|
|
130
|
+
return fn2();
|
|
131
|
+
}
|
|
132
|
+
}, ms);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
function triggerToFunction(trigger) {
|
|
136
|
+
if (typeof window === "undefined") {
|
|
137
|
+
console.debug(
|
|
138
|
+
"The Ory SDK is missing a required function: window is undefined."
|
|
139
|
+
);
|
|
140
|
+
return void 0;
|
|
141
|
+
}
|
|
142
|
+
const typedWindow = window;
|
|
143
|
+
if (!(trigger in typedWindow) || !typedWindow[trigger]) {
|
|
144
|
+
console.debug(`The Ory SDK is missing a required function: ${trigger}.`);
|
|
145
|
+
return void 0;
|
|
146
|
+
}
|
|
147
|
+
const triggerFn = typedWindow[trigger];
|
|
148
|
+
if (typeof triggerFn !== "function") {
|
|
149
|
+
console.debug(
|
|
150
|
+
`The Ory SDK is missing a required function: ${trigger}. It is not a function.`
|
|
151
|
+
);
|
|
152
|
+
return void 0;
|
|
153
|
+
}
|
|
154
|
+
return triggerFn;
|
|
155
|
+
}
|
|
156
|
+
function nodesToAuthMethodGroups(nodes, excludeAuthMethods = [clientFetch.UiNodeGroupEnum.Oidc]) {
|
|
157
|
+
var _a;
|
|
158
|
+
const groups = {};
|
|
159
|
+
for (const node of nodes) {
|
|
160
|
+
if (node.type === "script") {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const groupNodes = (_a = groups[node.group]) != null ? _a : [];
|
|
164
|
+
groupNodes.push(node);
|
|
165
|
+
groups[node.group] = groupNodes;
|
|
166
|
+
}
|
|
167
|
+
return Object.values(clientFetch.UiNodeGroupEnum).filter((group) => {
|
|
168
|
+
var _a2;
|
|
169
|
+
return (_a2 = groups[group]) == null ? void 0 : _a2.length;
|
|
170
|
+
}).filter(
|
|
171
|
+
(group) => ![
|
|
172
|
+
clientFetch.UiNodeGroupEnum.Default,
|
|
173
|
+
clientFetch.UiNodeGroupEnum.IdentifierFirst,
|
|
174
|
+
clientFetch.UiNodeGroupEnum.Profile,
|
|
175
|
+
...excludeAuthMethods
|
|
176
|
+
].includes(group)
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
function useNodesGroups(nodes) {
|
|
180
|
+
const groupSorter = useGroupSorter();
|
|
181
|
+
const groups = react.useMemo(() => {
|
|
182
|
+
var _a;
|
|
183
|
+
const groups2 = {};
|
|
184
|
+
for (const node of nodes) {
|
|
185
|
+
if (node.type === "script") {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
const groupNodes = (_a = groups2[node.group]) != null ? _a : [];
|
|
189
|
+
groupNodes.push(node);
|
|
190
|
+
groups2[node.group] = groupNodes;
|
|
191
|
+
}
|
|
192
|
+
return groups2;
|
|
193
|
+
}, [nodes]);
|
|
194
|
+
const entries = react.useMemo(
|
|
195
|
+
() => Object.entries(groups).sort(([a], [b]) => groupSorter(a, b)),
|
|
196
|
+
[groups, groupSorter]
|
|
197
|
+
);
|
|
198
|
+
return {
|
|
199
|
+
groups,
|
|
200
|
+
entries
|
|
201
|
+
};
|
|
202
|
+
}
|
|
108
203
|
|
|
109
204
|
// src/context/form-state.ts
|
|
110
205
|
function findMethodWithMessage(nodes) {
|
|
@@ -129,6 +224,10 @@ function parseStateFromFlow(flow) {
|
|
|
129
224
|
} else if (flow.flow.active && !["default", "identifier_first", "oidc"].includes(flow.flow.active)) {
|
|
130
225
|
return { current: "method_active", method: flow.flow.active };
|
|
131
226
|
} else if (isChoosingMethod(flow.flow.ui.nodes)) {
|
|
227
|
+
const authMethods = nodesToAuthMethodGroups(flow.flow.ui.nodes);
|
|
228
|
+
if (authMethods.length === 1) {
|
|
229
|
+
return { current: "method_active", method: authMethods[0] };
|
|
230
|
+
}
|
|
132
231
|
return { current: "select_method" };
|
|
133
232
|
} else if ((_a = flow.flow.ui.messages) == null ? void 0 : _a.some((m) => m.id === 1010016)) {
|
|
134
233
|
return { current: "select_method" };
|
|
@@ -2230,78 +2329,6 @@ function OryCardHeader() {
|
|
|
2230
2329
|
const { Card } = useComponents();
|
|
2231
2330
|
return /* @__PURE__ */ jsxRuntime.jsx(Card.Header, {});
|
|
2232
2331
|
}
|
|
2233
|
-
function triggerToWindowCall(trigger) {
|
|
2234
|
-
if (!trigger) {
|
|
2235
|
-
return;
|
|
2236
|
-
}
|
|
2237
|
-
const fn = triggerToFunction(trigger);
|
|
2238
|
-
if (fn) {
|
|
2239
|
-
fn();
|
|
2240
|
-
return;
|
|
2241
|
-
}
|
|
2242
|
-
let i = 0;
|
|
2243
|
-
const ms = 100;
|
|
2244
|
-
const interval = setInterval(() => {
|
|
2245
|
-
i++;
|
|
2246
|
-
if (i > 100) {
|
|
2247
|
-
clearInterval(interval);
|
|
2248
|
-
throw new Error(
|
|
2249
|
-
"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."
|
|
2250
|
-
);
|
|
2251
|
-
}
|
|
2252
|
-
const fn2 = triggerToFunction(trigger);
|
|
2253
|
-
if (fn2) {
|
|
2254
|
-
clearInterval(interval);
|
|
2255
|
-
return fn2();
|
|
2256
|
-
}
|
|
2257
|
-
}, ms);
|
|
2258
|
-
return;
|
|
2259
|
-
}
|
|
2260
|
-
function triggerToFunction(trigger) {
|
|
2261
|
-
if (typeof window === "undefined") {
|
|
2262
|
-
console.debug(
|
|
2263
|
-
"The Ory SDK is missing a required function: window is undefined."
|
|
2264
|
-
);
|
|
2265
|
-
return void 0;
|
|
2266
|
-
}
|
|
2267
|
-
const typedWindow = window;
|
|
2268
|
-
if (!(trigger in typedWindow) || !typedWindow[trigger]) {
|
|
2269
|
-
console.debug(`The Ory SDK is missing a required function: ${trigger}.`);
|
|
2270
|
-
return void 0;
|
|
2271
|
-
}
|
|
2272
|
-
const triggerFn = typedWindow[trigger];
|
|
2273
|
-
if (typeof triggerFn !== "function") {
|
|
2274
|
-
console.debug(
|
|
2275
|
-
`The Ory SDK is missing a required function: ${trigger}. It is not a function.`
|
|
2276
|
-
);
|
|
2277
|
-
return void 0;
|
|
2278
|
-
}
|
|
2279
|
-
return triggerFn;
|
|
2280
|
-
}
|
|
2281
|
-
function useNodesGroups(nodes) {
|
|
2282
|
-
const groupSorter = useGroupSorter();
|
|
2283
|
-
const groups = react.useMemo(() => {
|
|
2284
|
-
var _a;
|
|
2285
|
-
const groups2 = {};
|
|
2286
|
-
for (const node of nodes) {
|
|
2287
|
-
if (node.type === "script") {
|
|
2288
|
-
continue;
|
|
2289
|
-
}
|
|
2290
|
-
const groupNodes = (_a = groups2[node.group]) != null ? _a : [];
|
|
2291
|
-
groupNodes.push(node);
|
|
2292
|
-
groups2[node.group] = groupNodes;
|
|
2293
|
-
}
|
|
2294
|
-
return groups2;
|
|
2295
|
-
}, [nodes]);
|
|
2296
|
-
const entries = react.useMemo(
|
|
2297
|
-
() => Object.entries(groups).sort(([a], [b]) => groupSorter(a, b)),
|
|
2298
|
-
[groups, groupSorter]
|
|
2299
|
-
);
|
|
2300
|
-
return {
|
|
2301
|
-
groups,
|
|
2302
|
-
entries
|
|
2303
|
-
};
|
|
2304
|
-
}
|
|
2305
2332
|
var NodeInput = ({
|
|
2306
2333
|
node,
|
|
2307
2334
|
attributes
|
|
@@ -2355,11 +2382,25 @@ var NodeInput = ({
|
|
|
2355
2382
|
if (isResendNode || isScreenSelectionNode) {
|
|
2356
2383
|
return null;
|
|
2357
2384
|
}
|
|
2358
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2385
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2386
|
+
Node2.Label,
|
|
2387
|
+
{
|
|
2388
|
+
attributes: { ...attrs, label: void 0 },
|
|
2389
|
+
node: { ...node, meta: { ...node.meta, label: void 0 } },
|
|
2390
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Node2.Button, { attributes: attrs, node, onClick: handleClick })
|
|
2391
|
+
}
|
|
2392
|
+
);
|
|
2359
2393
|
case clientFetch.UiNodeInputAttributesTypeEnum.DatetimeLocal:
|
|
2360
2394
|
throw new Error("Not implemented");
|
|
2361
2395
|
case clientFetch.UiNodeInputAttributesTypeEnum.Checkbox:
|
|
2362
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2396
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2397
|
+
Node2.Label,
|
|
2398
|
+
{
|
|
2399
|
+
attributes: { ...attrs, label: void 0 },
|
|
2400
|
+
node: { ...node, meta: { ...node.meta, label: void 0 } },
|
|
2401
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Node2.Checkbox, { attributes: attrs, node, onClick: handleClick })
|
|
2402
|
+
}
|
|
2403
|
+
);
|
|
2363
2404
|
case clientFetch.UiNodeInputAttributesTypeEnum.Hidden:
|
|
2364
2405
|
return /* @__PURE__ */ jsxRuntime.jsx(Node2.Input, { attributes: attrs, node, onClick: handleClick });
|
|
2365
2406
|
default:
|
|
@@ -2447,8 +2488,6 @@ function unrollTrait(input, output = {}) {
|
|
|
2447
2488
|
});
|
|
2448
2489
|
return output;
|
|
2449
2490
|
}
|
|
2450
|
-
|
|
2451
|
-
// src/components/form/form-resolver.ts
|
|
2452
2491
|
function isCodeResendRequest(data) {
|
|
2453
2492
|
var _a;
|
|
2454
2493
|
return (_a = data.email) != null ? _a : data.resend;
|
|
@@ -2457,10 +2496,22 @@ function useOryFormResolver() {
|
|
|
2457
2496
|
const flowContainer = useOryFlow();
|
|
2458
2497
|
return (data) => {
|
|
2459
2498
|
if (flowContainer.formState.current === "method_active") {
|
|
2460
|
-
if (
|
|
2499
|
+
if (
|
|
2500
|
+
// When we submit a code
|
|
2501
|
+
data.method === "code" && // And the code is not present
|
|
2502
|
+
!data.code && // And the flow is not a code resend request
|
|
2503
|
+
!isCodeResendRequest(data) && // And the flow has a code input node
|
|
2504
|
+
flowContainer.flow.ui.nodes.find(({ attributes, group }) => {
|
|
2505
|
+
if (!clientFetch.isUiNodeInputAttributes(attributes)) {
|
|
2506
|
+
return false;
|
|
2507
|
+
}
|
|
2508
|
+
return group === "code" && attributes.name === "code" && attributes.type !== "hidden";
|
|
2509
|
+
})
|
|
2510
|
+
) {
|
|
2461
2511
|
return {
|
|
2462
2512
|
values: data,
|
|
2463
2513
|
errors: {
|
|
2514
|
+
// We know the code node exists, so we can safely hardcode the ID.
|
|
2464
2515
|
code: {
|
|
2465
2516
|
id: 4000002,
|
|
2466
2517
|
context: {
|
|
@@ -2551,6 +2602,13 @@ function frontendClient(sdkUrl, opts = {}) {
|
|
|
2551
2602
|
return new clientFetch.FrontendApi(config);
|
|
2552
2603
|
}
|
|
2553
2604
|
|
|
2605
|
+
// src/util/internal.ts
|
|
2606
|
+
function replaceWindowFlowId(flow) {
|
|
2607
|
+
const url = new URL(window.location.href);
|
|
2608
|
+
url.searchParams.set("flow", flow);
|
|
2609
|
+
window.location.href = url.toString();
|
|
2610
|
+
}
|
|
2611
|
+
|
|
2554
2612
|
// src/util/onSubmitLogin.ts
|
|
2555
2613
|
async function onSubmitLogin({ config, flow }, {
|
|
2556
2614
|
setFlowContainer,
|
|
@@ -2572,8 +2630,12 @@ async function onSubmitLogin({ config, flow }, {
|
|
|
2572
2630
|
(_a2 = flow.return_to) != null ? _a2 : config.sdk.url + "/self-service/login/browser";
|
|
2573
2631
|
}).catch(
|
|
2574
2632
|
clientFetch.handleFlowError({
|
|
2575
|
-
onRestartFlow: () => {
|
|
2576
|
-
|
|
2633
|
+
onRestartFlow: (useFlowId) => {
|
|
2634
|
+
if (useFlowId) {
|
|
2635
|
+
replaceWindowFlowId(useFlowId);
|
|
2636
|
+
} else {
|
|
2637
|
+
onRedirect(clientFetch.loginUrl(config), true);
|
|
2638
|
+
}
|
|
2577
2639
|
},
|
|
2578
2640
|
onValidationError: (body2) => {
|
|
2579
2641
|
setFlowContainer({
|
|
@@ -2615,8 +2677,12 @@ async function onSubmitRecovery({ config, flow }, {
|
|
|
2615
2677
|
});
|
|
2616
2678
|
}).catch(
|
|
2617
2679
|
clientFetch.handleFlowError({
|
|
2618
|
-
onRestartFlow: () => {
|
|
2619
|
-
|
|
2680
|
+
onRestartFlow: (useFlowId) => {
|
|
2681
|
+
if (useFlowId) {
|
|
2682
|
+
replaceWindowFlowId(useFlowId);
|
|
2683
|
+
} else {
|
|
2684
|
+
onRedirect(clientFetch.recoveryUrl(config), true);
|
|
2685
|
+
}
|
|
2620
2686
|
},
|
|
2621
2687
|
onValidationError: (body2) => {
|
|
2622
2688
|
if ("error" in body2) {
|
|
@@ -2673,8 +2739,12 @@ async function onSubmitRegistration({ config, flow }, {
|
|
|
2673
2739
|
onRedirect(clientFetch.registrationUrl(config), true);
|
|
2674
2740
|
}).catch(
|
|
2675
2741
|
clientFetch.handleFlowError({
|
|
2676
|
-
onRestartFlow: () => {
|
|
2677
|
-
|
|
2742
|
+
onRestartFlow: (useFlowId) => {
|
|
2743
|
+
if (useFlowId) {
|
|
2744
|
+
replaceWindowFlowId(useFlowId);
|
|
2745
|
+
} else {
|
|
2746
|
+
onRedirect(clientFetch.registrationUrl(config), true);
|
|
2747
|
+
}
|
|
2678
2748
|
},
|
|
2679
2749
|
onValidationError: (body2) => {
|
|
2680
2750
|
setFlowContainer({
|
|
@@ -2717,8 +2787,12 @@ async function onSubmitSettings({ config, flow }, {
|
|
|
2717
2787
|
});
|
|
2718
2788
|
}).catch(
|
|
2719
2789
|
clientFetch.handleFlowError({
|
|
2720
|
-
onRestartFlow: () => {
|
|
2721
|
-
|
|
2790
|
+
onRestartFlow: (useFlowId) => {
|
|
2791
|
+
if (useFlowId) {
|
|
2792
|
+
replaceWindowFlowId(useFlowId);
|
|
2793
|
+
} else {
|
|
2794
|
+
onRedirect(clientFetch.settingsUrl(config), true);
|
|
2795
|
+
}
|
|
2722
2796
|
},
|
|
2723
2797
|
onValidationError: (body2) => {
|
|
2724
2798
|
setFlowContainer({
|
|
@@ -2763,8 +2837,12 @@ async function onSubmitVerification({ config, flow }, {
|
|
|
2763
2837
|
})
|
|
2764
2838
|
).catch(
|
|
2765
2839
|
clientFetch.handleFlowError({
|
|
2766
|
-
onRestartFlow: () => {
|
|
2767
|
-
|
|
2840
|
+
onRestartFlow: (useFlowId) => {
|
|
2841
|
+
if (useFlowId) {
|
|
2842
|
+
replaceWindowFlowId(useFlowId);
|
|
2843
|
+
} else {
|
|
2844
|
+
onRedirect(clientFetch.verificationUrl(config), true);
|
|
2845
|
+
}
|
|
2768
2846
|
},
|
|
2769
2847
|
onValidationError: (body2) => {
|
|
2770
2848
|
setFlowContainer({
|
|
@@ -3589,16 +3667,16 @@ var uiTextToFormattedMessage = ({ id, context = {}, text }, intl) => {
|
|
|
3589
3667
|
new Date(value),
|
|
3590
3668
|
/* @__PURE__ */ new Date()
|
|
3591
3669
|
),
|
|
3592
|
-
[key + "_since_minutes"]: Math.
|
|
3670
|
+
[key + "_since_minutes"]: Math.ceil(
|
|
3593
3671
|
(value - (/* @__PURE__ */ new Date()).getTime() / 1e3) / 60
|
|
3594
|
-
).toFixed(
|
|
3672
|
+
).toFixed(0),
|
|
3595
3673
|
[key + "_until"]: intl.formatDateTimeRange(
|
|
3596
3674
|
/* @__PURE__ */ new Date(),
|
|
3597
3675
|
new Date(value)
|
|
3598
3676
|
),
|
|
3599
|
-
[key + "_until_minutes"]: Math.
|
|
3677
|
+
[key + "_until_minutes"]: Math.ceil(
|
|
3600
3678
|
((/* @__PURE__ */ new Date()).getTime() / 1e3 - value) / 60
|
|
3601
|
-
).toFixed(
|
|
3679
|
+
).toFixed(0)
|
|
3602
3680
|
};
|
|
3603
3681
|
}
|
|
3604
3682
|
}
|
|
@@ -3621,7 +3699,7 @@ var uiTextToFormattedMessage = ({ id, context = {}, text }, intl) => {
|
|
|
3621
3699
|
// src/util/test-id.ts
|
|
3622
3700
|
function messageTestId(message) {
|
|
3623
3701
|
return {
|
|
3624
|
-
"data-testid": `ory
|
|
3702
|
+
"data-testid": `ory/ui/message/${message.id}`
|
|
3625
3703
|
};
|
|
3626
3704
|
}
|
|
3627
3705
|
|