@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 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 collection of components and functions that help you get an
12
- authentication solution up, running and integrated into your application in no
13
- time.
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
- - Documentation: https://ory.sh/docs
26
+ ## Documentation
16
27
 
17
- ## Usage
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
- Install the package:
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: MouseEventHandler;
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: MouseEventHandler;
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 Fragment5 = REACT_FRAGMENT_TYPE;
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 = Fragment5;
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
- if (isCurrentIdentifier) {
4807
- return /* @__PURE__ */ jsxRuntime.jsx(Components.CurrentIdentifierButton, { attributes: attrs, node });
4808
- }
4809
- return /* @__PURE__ */ jsxRuntime.jsx(
4810
- Components.Input,
4811
- {
4812
- attributes: attrs,
4813
- node,
4814
- onClick: handleClick
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(