@ory/elements-react 1.0.0-next.2 → 1.0.0-next.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +159 -7
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +41 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +41 -13
- package/dist/index.mjs.map +1 -1
- package/dist/theme/default/index.d.mts +1 -1
- package/dist/theme/default/index.d.ts +1 -1
- package/dist/theme/default/index.js +69 -15
- package/dist/theme/default/index.js.map +1 -1
- package/dist/theme/default/index.mjs +79 -25
- package/dist/theme/default/index.mjs.map +1 -1
- package/package.json +11 -1
package/README.md
CHANGED
|
@@ -6,18 +6,170 @@
|
|
|
6
6
|
|
|
7
7
|
# @ory/elements-react
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a aria-label="NPM Version" href="https://www.npmjs.com/package/@ory/elements-react">
|
|
11
|
+
<img src="https://img.shields.io/npm/v/@ory/elements-react.svg?style=flat-square">
|
|
12
|
+
</a>
|
|
13
|
+
<a aria-label="License" href="https://github.com/ory/elements/blob/main/LICENSE">
|
|
14
|
+
<img src="https://img.shields.io/github/license/ory/elements?style=flat-square">
|
|
15
|
+
</a>
|
|
16
|
+
<a aria-label="Join Ory Slack community!" href="https://slack.ory.sh/">
|
|
17
|
+
<img src="https://img.shields.io/badge/Slack-Join%20the%20community!-4f46e5?style=flat-square&logo=slack&logoColor=eef2ff">
|
|
18
|
+
</a>
|
|
19
|
+
</p>
|
|
10
20
|
|
|
11
|
-
Ory Elements is a
|
|
12
|
-
|
|
13
|
-
|
|
21
|
+
Ory Elements is a set of components and functions tailored for easy integration
|
|
22
|
+
of Ory into your React application. It simplifies the process of adding
|
|
23
|
+
authentication and other identity features to your application using the Ory
|
|
24
|
+
Network.
|
|
14
25
|
|
|
15
|
-
|
|
26
|
+
## Documentation
|
|
16
27
|
|
|
17
|
-
|
|
28
|
+
Visit https://ory.sh/docs to see the full Ory documentation.
|
|
29
|
+
|
|
30
|
+
## Getting started
|
|
31
|
+
|
|
32
|
+
**Requirements**
|
|
33
|
+
|
|
34
|
+
- React `>= 18`
|
|
35
|
+
- Node.js `>= 18`
|
|
36
|
+
- **`@ory/client-fetch`** - fetch based version of ory client
|
|
18
37
|
|
|
19
|
-
|
|
38
|
+
**Installation**
|
|
20
39
|
|
|
21
40
|
```sh
|
|
22
41
|
npm install @ory/elements-react
|
|
23
42
|
```
|
|
43
|
+
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
Ory Elements provides components that can aggregate flow objects and display
|
|
47
|
+
user authentication flows based on the data.
|
|
48
|
+
|
|
49
|
+
To feed Ory Elements with flow data you need to use Ory client.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { frontendClient } from "@ory/client-fetch"
|
|
53
|
+
|
|
54
|
+
export function serverClientFrontend() {
|
|
55
|
+
// For testing purposes we're using Ory tunnel
|
|
56
|
+
return frontendClient("http://localhost:4000", {
|
|
57
|
+
headers: {
|
|
58
|
+
Accept: "application/json",
|
|
59
|
+
},
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Ory Network project setup
|
|
65
|
+
|
|
66
|
+
The Ory Identities APIs come with the ability to specify custom UI URLs. To make
|
|
67
|
+
sure, Ory knows about your custom UI, specify the URLs of your application on
|
|
68
|
+
https://console.ory.sh/projects/current/ui.
|
|
69
|
+
|
|
70
|
+
### Initializing a new flow
|
|
71
|
+
|
|
72
|
+
Initializing a new flow is done by navigating the user's page to the initialize
|
|
73
|
+
flow URL. After creating a new flow object, Ory will return a redirect to the
|
|
74
|
+
flow UI URL and, in some cases, return anti-CSRF cookies.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
export function init(params: QueryParams, flowType: FlowType) {
|
|
78
|
+
// Take advantage of the fact, that Ory handles the flow creation for us and redirects the user to the default return to automatically if they're logged in already.
|
|
79
|
+
return redirect(
|
|
80
|
+
"http://localhost:4000" +
|
|
81
|
+
"/self-service/" +
|
|
82
|
+
flowType.toString() +
|
|
83
|
+
"/browser?" +
|
|
84
|
+
new URLSearchParams(params).toString(),
|
|
85
|
+
RedirectType.replace,
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**FlowType** can be: `login`, `registration`, `recovery`, `verification`,
|
|
91
|
+
`settings` or `error`
|
|
92
|
+
|
|
93
|
+
To access & render the flow, on your flow page, you can use the `flow` query
|
|
94
|
+
parameter, that is included in the redirect. Use it to call the
|
|
95
|
+
[`getLoginFlow()`](https://www.ory.sh/docs/reference/api#tag/frontend/operation/getLoginFlow)
|
|
96
|
+
API.
|
|
97
|
+
|
|
98
|
+
**Full Example**:
|
|
99
|
+
|
|
100
|
+
````ts
|
|
101
|
+
export async function getOrCreateRegistrationFlow(
|
|
102
|
+
params: QueryParams
|
|
103
|
+
): Promise<RegistrationFlow> {
|
|
104
|
+
const onRestartFlow = () => init(params, FlowType.Registration);
|
|
105
|
+
|
|
106
|
+
// If flow ID doesn't exist in params simply trigget the init function.
|
|
107
|
+
if (!params.flow) {
|
|
108
|
+
return onRestartFlow();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return await serverClientFrontend()
|
|
112
|
+
// Passing the flow ID
|
|
113
|
+
.getRegistrationFlowRaw({ id: flow })
|
|
114
|
+
.then(res => res.value())
|
|
115
|
+
.catch(
|
|
116
|
+
// Ory Elements predefines the handleFlowError function to simplify error handling.
|
|
117
|
+
// You can define what should happen in each of these callbacks
|
|
118
|
+
handleFlowError({
|
|
119
|
+
onValidationError,
|
|
120
|
+
onRestartFlow,
|
|
121
|
+
onRedirect,
|
|
122
|
+
})
|
|
123
|
+
);
|
|
124
|
+
```
|
|
125
|
+
````
|
|
126
|
+
|
|
127
|
+
As soon as we have our flow data we can render the `<Registration/>` component
|
|
128
|
+
from `@ory/elements-react` package.
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
export default async function RegistrationPage({ searchParams }: PageProps) {
|
|
132
|
+
const flow = await getOrCreateRegistrationFlow(searchParams)
|
|
133
|
+
|
|
134
|
+
if (!flow) {
|
|
135
|
+
return <div>Flow not found</div>
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<Registration
|
|
140
|
+
flow={flow}
|
|
141
|
+
config={oryConfiguration}
|
|
142
|
+
components={ComponentOverrides}
|
|
143
|
+
/>
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Styling
|
|
149
|
+
|
|
150
|
+
To include the default styles, add the following import to your app. Make sure
|
|
151
|
+
it's included on all pages, that use Ory Elements.
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
import "@ory/elements-react/theme/styles.css"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Theming
|
|
158
|
+
|
|
159
|
+
Most styling can be overwritten, by providing your own custom CSS variables:
|
|
160
|
+
|
|
161
|
+
```css
|
|
162
|
+
:root {
|
|
163
|
+
/* To override the text color of the primary buttons */
|
|
164
|
+
--button-primary-fg-default: #fffeee;
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Package development
|
|
169
|
+
|
|
170
|
+
To develop and use the package `npm link` is recommended. To run the package in
|
|
171
|
+
watch mode use
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
npx nx run @ory/elements-react:dev
|
|
175
|
+
```
|
package/dist/index.d.mts
CHANGED
|
@@ -121,7 +121,7 @@ type HeadlessFormProps = ComponentPropsWithoutRef<"form"> & {
|
|
|
121
121
|
type HeadlessInputProps = {
|
|
122
122
|
attributes: UiNodeInputAttributes;
|
|
123
123
|
node: UiNode;
|
|
124
|
-
onClick
|
|
124
|
+
onClick?: MouseEventHandler;
|
|
125
125
|
};
|
|
126
126
|
type OryFlowComponents = OryFormComponents & OryCardComponents;
|
|
127
127
|
|
package/dist/index.d.ts
CHANGED
|
@@ -121,7 +121,7 @@ type HeadlessFormProps = ComponentPropsWithoutRef<"form"> & {
|
|
|
121
121
|
type HeadlessInputProps = {
|
|
122
122
|
attributes: UiNodeInputAttributes;
|
|
123
123
|
node: UiNode;
|
|
124
|
-
onClick
|
|
124
|
+
onClick?: MouseEventHandler;
|
|
125
125
|
};
|
|
126
126
|
type OryFlowComponents = OryFormComponents & OryCardComponents;
|
|
127
127
|
|
package/dist/index.js
CHANGED
|
@@ -234,7 +234,7 @@ var require_react_is_development = __commonJS({
|
|
|
234
234
|
var ContextProvider = REACT_PROVIDER_TYPE;
|
|
235
235
|
var Element = REACT_ELEMENT_TYPE;
|
|
236
236
|
var ForwardRef = REACT_FORWARD_REF_TYPE;
|
|
237
|
-
var
|
|
237
|
+
var Fragment6 = REACT_FRAGMENT_TYPE;
|
|
238
238
|
var Lazy = REACT_LAZY_TYPE;
|
|
239
239
|
var Memo = REACT_MEMO_TYPE;
|
|
240
240
|
var Portal = REACT_PORTAL_TYPE;
|
|
@@ -293,7 +293,7 @@ var require_react_is_development = __commonJS({
|
|
|
293
293
|
exports.ContextProvider = ContextProvider;
|
|
294
294
|
exports.Element = Element;
|
|
295
295
|
exports.ForwardRef = ForwardRef;
|
|
296
|
-
exports.Fragment =
|
|
296
|
+
exports.Fragment = Fragment6;
|
|
297
297
|
exports.Lazy = Lazy;
|
|
298
298
|
exports.Memo = Memo;
|
|
299
299
|
exports.Portal = Portal;
|
|
@@ -573,9 +573,11 @@ function parseDateTimeSkeleton(skeleton) {
|
|
|
573
573
|
skeleton.replace(DATE_TIME_REGEX, function(match) {
|
|
574
574
|
var len = match.length;
|
|
575
575
|
switch (match[0]) {
|
|
576
|
+
// Era
|
|
576
577
|
case "G":
|
|
577
578
|
result.era = len === 4 ? "long" : len === 5 ? "narrow" : "short";
|
|
578
579
|
break;
|
|
580
|
+
// Year
|
|
579
581
|
case "y":
|
|
580
582
|
result.year = len === 2 ? "2-digit" : "numeric";
|
|
581
583
|
break;
|
|
@@ -584,13 +586,16 @@ function parseDateTimeSkeleton(skeleton) {
|
|
|
584
586
|
case "U":
|
|
585
587
|
case "r":
|
|
586
588
|
throw new RangeError("`Y/u/U/r` (year) patterns are not supported, use `y` instead");
|
|
589
|
+
// Quarter
|
|
587
590
|
case "q":
|
|
588
591
|
case "Q":
|
|
589
592
|
throw new RangeError("`q/Q` (quarter) patterns are not supported");
|
|
593
|
+
// Month
|
|
590
594
|
case "M":
|
|
591
595
|
case "L":
|
|
592
596
|
result.month = ["numeric", "2-digit", "short", "long", "narrow"][len - 1];
|
|
593
597
|
break;
|
|
598
|
+
// Week
|
|
594
599
|
case "w":
|
|
595
600
|
case "W":
|
|
596
601
|
throw new RangeError("`w/W` (week) patterns are not supported");
|
|
@@ -601,6 +606,7 @@ function parseDateTimeSkeleton(skeleton) {
|
|
|
601
606
|
case "F":
|
|
602
607
|
case "g":
|
|
603
608
|
throw new RangeError("`D/F/g` (day) patterns are not supported, use `d` instead");
|
|
609
|
+
// Weekday
|
|
604
610
|
case "E":
|
|
605
611
|
result.weekday = len === 4 ? "short" : len === 5 ? "narrow" : "short";
|
|
606
612
|
break;
|
|
@@ -616,12 +622,15 @@ function parseDateTimeSkeleton(skeleton) {
|
|
|
616
622
|
}
|
|
617
623
|
result.weekday = ["short", "long", "narrow", "short"][len - 4];
|
|
618
624
|
break;
|
|
625
|
+
// Period
|
|
619
626
|
case "a":
|
|
620
627
|
result.hour12 = true;
|
|
621
628
|
break;
|
|
622
629
|
case "b":
|
|
630
|
+
// am, pm, noon, midnight
|
|
623
631
|
case "B":
|
|
624
632
|
throw new RangeError("`b/B` (period) patterns are not supported, use `a` instead");
|
|
633
|
+
// Hour
|
|
625
634
|
case "h":
|
|
626
635
|
result.hourCycle = "h12";
|
|
627
636
|
result.hour = ["numeric", "2-digit"][len - 1];
|
|
@@ -642,23 +651,31 @@ function parseDateTimeSkeleton(skeleton) {
|
|
|
642
651
|
case "J":
|
|
643
652
|
case "C":
|
|
644
653
|
throw new RangeError("`j/J/C` (hour) patterns are not supported, use `h/H/K/k` instead");
|
|
654
|
+
// Minute
|
|
645
655
|
case "m":
|
|
646
656
|
result.minute = ["numeric", "2-digit"][len - 1];
|
|
647
657
|
break;
|
|
658
|
+
// Second
|
|
648
659
|
case "s":
|
|
649
660
|
result.second = ["numeric", "2-digit"][len - 1];
|
|
650
661
|
break;
|
|
651
662
|
case "S":
|
|
652
663
|
case "A":
|
|
653
664
|
throw new RangeError("`S/A` (second) patterns are not supported, use `s` instead");
|
|
665
|
+
// Zone
|
|
654
666
|
case "z":
|
|
655
667
|
result.timeZoneName = len < 4 ? "short" : "long";
|
|
656
668
|
break;
|
|
657
669
|
case "Z":
|
|
670
|
+
// 1..3, 4, 5: The ISO8601 varios formats
|
|
658
671
|
case "O":
|
|
672
|
+
// 1, 4: miliseconds in day short, long
|
|
659
673
|
case "v":
|
|
674
|
+
// 1, 4: generic non-location format
|
|
660
675
|
case "V":
|
|
676
|
+
// 1, 2, 3, 4: time zone ID or city
|
|
661
677
|
case "X":
|
|
678
|
+
// 1, 2, 3, 4: The ISO8601 varios formats
|
|
662
679
|
case "x":
|
|
663
680
|
throw new RangeError("`Z/O/v/V/X/x` (timeZone) patterns are not supported, use `z` instead");
|
|
664
681
|
}
|
|
@@ -856,6 +873,7 @@ function parseNumberSkeleton(tokens) {
|
|
|
856
873
|
case "notation-simple":
|
|
857
874
|
result.notation = "standard";
|
|
858
875
|
continue;
|
|
876
|
+
// https://github.com/unicode-org/icu/blob/master/icu4c/source/i18n/unicode/unumberformatter.h
|
|
859
877
|
case "unit-width-narrow":
|
|
860
878
|
result.currencyDisplay = "narrowSymbol";
|
|
861
879
|
result.unitDisplay = "narrow";
|
|
@@ -874,6 +892,7 @@ function parseNumberSkeleton(tokens) {
|
|
|
874
892
|
case "scale":
|
|
875
893
|
result.scale = parseFloat(token.options[0]);
|
|
876
894
|
continue;
|
|
895
|
+
// https://unicode-org.github.io/icu/userguide/format_parse/numbers/skeletons.html#integer-width
|
|
877
896
|
case "integer-width":
|
|
878
897
|
if (token.options.length > 1) {
|
|
879
898
|
throw new RangeError("integer-width stems only accept a single optional option");
|
|
@@ -2636,6 +2655,7 @@ var Parser = (
|
|
|
2636
2655
|
this.bump();
|
|
2637
2656
|
this.bump();
|
|
2638
2657
|
return "'";
|
|
2658
|
+
// '{', '<', '>', '}'
|
|
2639
2659
|
case 123:
|
|
2640
2660
|
case 60:
|
|
2641
2661
|
case 62:
|
|
@@ -2701,6 +2721,7 @@ var Parser = (
|
|
|
2701
2721
|
return this.error(ErrorKind.EXPECT_ARGUMENT_CLOSING_BRACE, createLocation(openingBracePosition, this.clonePosition()));
|
|
2702
2722
|
}
|
|
2703
2723
|
switch (this.char()) {
|
|
2724
|
+
// Simple argument: `{name}`
|
|
2704
2725
|
case 125: {
|
|
2705
2726
|
this.bump();
|
|
2706
2727
|
return {
|
|
@@ -2713,6 +2734,7 @@ var Parser = (
|
|
|
2713
2734
|
err: null
|
|
2714
2735
|
};
|
|
2715
2736
|
}
|
|
2737
|
+
// Argument with options: `{name, format, ...}`
|
|
2716
2738
|
case 44: {
|
|
2717
2739
|
this.bump();
|
|
2718
2740
|
this.bumpSpace();
|
|
@@ -4803,17 +4825,23 @@ var NodeInput = ({
|
|
|
4803
4825
|
}
|
|
4804
4826
|
);
|
|
4805
4827
|
case clientFetch.UiNodeInputAttributesTypeEnum.Hidden:
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4828
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4829
|
+
isCurrentIdentifier && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4830
|
+
Components.CurrentIdentifierButton,
|
|
4831
|
+
{
|
|
4832
|
+
attributes: attrs,
|
|
4833
|
+
node
|
|
4834
|
+
}
|
|
4835
|
+
),
|
|
4836
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4837
|
+
Components.Input,
|
|
4838
|
+
{
|
|
4839
|
+
attributes: attrs,
|
|
4840
|
+
node,
|
|
4841
|
+
onClick: handleClick
|
|
4842
|
+
}
|
|
4843
|
+
)
|
|
4844
|
+
] });
|
|
4817
4845
|
default:
|
|
4818
4846
|
if (isPinCodeInput) {
|
|
4819
4847
|
return /* @__PURE__ */ jsxRuntime.jsx(Components.Label, { attributes: attrs, node, children: /* @__PURE__ */ jsxRuntime.jsx(
|