@xyo-network/react-xns 3.0.11 → 3.0.13

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.
Files changed (25) hide show
  1. package/dist/browser/components/XnsNameCapture/Props.d.ts +2 -1
  2. package/dist/browser/components/XnsNameCapture/Props.d.ts.map +1 -1
  3. package/dist/browser/components/XnsNameCapture/hooks/index.d.ts +1 -1
  4. package/dist/browser/components/XnsNameCapture/hooks/index.d.ts.map +1 -1
  5. package/dist/browser/components/XnsNameCapture/hooks/routing/index.d.ts +3 -0
  6. package/dist/browser/components/XnsNameCapture/hooks/routing/index.d.ts.map +1 -0
  7. package/dist/browser/components/XnsNameCapture/hooks/{useXnsNameCaptureRouting.d.ts → routing/useXnsNameCaptureRouting.d.ts} +4 -3
  8. package/dist/browser/components/XnsNameCapture/hooks/{useXnsNameCaptureRouting.d.ts.map → routing/useXnsNameCaptureRouting.d.ts.map} +1 -1
  9. package/dist/browser/components/XnsNameCapture/hooks/routing/useXnsNameFromLocation.d.ts +2 -0
  10. package/dist/browser/components/XnsNameCapture/hooks/routing/useXnsNameFromLocation.d.ts.map +1 -0
  11. package/dist/browser/components/XnsNameCapture/hooks/useXnsNameCaptureProviders.d.ts +2 -1
  12. package/dist/browser/components/XnsNameCapture/hooks/useXnsNameCaptureProviders.d.ts.map +1 -1
  13. package/dist/browser/index.mjs +72 -31
  14. package/dist/browser/index.mjs.map +1 -1
  15. package/package.json +2 -2
  16. package/src/components/XnsNameCapture/Props.ts +2 -1
  17. package/src/components/XnsNameCapture/SecondaryLink.stories.tsx +1 -1
  18. package/src/components/XnsNameCapture/SecondaryLink.tsx +2 -2
  19. package/src/components/XnsNameCapture/XnsNameCapture.stories.tsx +1 -1
  20. package/src/components/XnsNameCapture/XnsNameCapture.tsx +12 -12
  21. package/src/components/XnsNameCapture/XnsNameCaptureWithContext.stories.tsx +35 -9
  22. package/src/components/XnsNameCapture/hooks/index.ts +1 -1
  23. package/src/components/XnsNameCapture/hooks/routing/index.ts +2 -0
  24. package/src/components/XnsNameCapture/hooks/{useXnsNameCaptureRouting.ts → routing/useXnsNameCaptureRouting.ts} +6 -1
  25. package/src/components/XnsNameCapture/hooks/routing/useXnsNameFromLocation.ts +26 -0
@@ -4,7 +4,7 @@ import type { Mixpanel } from 'mixpanel-browser';
4
4
  import type { ReactNode } from 'react';
5
5
  import type { To } from 'react-router-dom';
6
6
  export interface XnsNameCaptureBuyCallbacks {
7
- onBuyName?: (name: string) => Promise<void>;
7
+ onCaptureName?: (name: string) => Promise<void>;
8
8
  }
9
9
  export interface XnsNameCaptureTrackingProps {
10
10
  event?: string;
@@ -15,6 +15,7 @@ export interface XnsNameCaptureTrackingProps {
15
15
  export interface XnsNameCaptureRoutingProps {
16
16
  navigate?: (to: string) => void;
17
17
  paramsString?: string;
18
+ routingError?: Error;
18
19
  to?: To;
19
20
  }
20
21
  export interface XnsNameCaptureBaseProps {
@@ -1 +1 @@
1
- {"version":3,"file":"Props.d.ts","sourceRoot":"","sources":["../../../../src/components/XnsNameCapture/Props.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AAE1C,MAAM,WAAW,0BAA0B;IACzC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5C;AAKD,MAAM,WAAW,2BAA2B;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,UAAU,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CACvD;AAKD,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,EAAE,CAAC,EAAE,EAAE,CAAA;CACR;AAKD,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CACpC;AAED,MAAM,WAAW,mBAAoB,SAAQ,uBAAuB,EAClE,2BAA2B,EAC3B,0BAA0B,EAC1B,0BAA0B,EAC1B,YAAY;CACZ;AAEF,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,UAAU,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAA;CAAE,CAAA"}
1
+ {"version":3,"file":"Props.d.ts","sourceRoot":"","sources":["../../../../src/components/XnsNameCapture/Props.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AAE1C,MAAM,WAAW,0BAA0B;IACzC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAChD;AAKD,MAAM,WAAW,2BAA2B;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,UAAU,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CACvD;AAKD,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,KAAK,CAAA;IACpB,EAAE,CAAC,EAAE,EAAE,CAAA;CACR;AAKD,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CACpC;AAED,MAAM,WAAW,mBAAoB,SAAQ,uBAAuB,EAClE,2BAA2B,EAC3B,0BAA0B,EAC1B,0BAA0B,EAC1B,YAAY;CACZ;AAEF,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,UAAU,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAA;CAAE,CAAA"}
@@ -1,3 +1,3 @@
1
+ export * from './routing/index.ts';
1
2
  export * from './useXnsNameCaptureProviders.ts';
2
- export * from './useXnsNameCaptureRouting.ts';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/XnsNameCapture/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAA;AAC/C,cAAc,+BAA+B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/XnsNameCapture/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,cAAc,iCAAiC,CAAA"}
@@ -0,0 +1,3 @@
1
+ export * from './useXnsNameCaptureRouting.ts';
2
+ export * from './useXnsNameFromLocation.ts';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/XnsNameCapture/hooks/routing/index.ts"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAA;AAC7C,cAAc,6BAA6B,CAAA"}
@@ -1,10 +1,11 @@
1
- import type { XnsNameCaptureProps } from '../Props.ts';
1
+ import type { XnsNameCaptureProps } from '../../Props.ts';
2
2
  export declare const useXnsNameCaptureRouting: (props: XnsNameCaptureProps) => {
3
+ defaultXnsName: string | undefined;
4
+ routingError: Error | undefined;
3
5
  navigate: (to: string) => void;
4
6
  paramsString: string;
5
7
  autoFocus?: boolean;
6
8
  buttonText?: string;
7
- defaultXnsName?: string;
8
9
  errorUi?: "alert" | "toast";
9
10
  mobileButtonText?: string;
10
11
  placement?: string;
@@ -13,7 +14,7 @@ export declare const useXnsNameCaptureRouting: (props: XnsNameCaptureProps) => {
13
14
  funnel?: string;
14
15
  mixpanel?: import("mixpanel-browser").Mixpanel;
15
16
  userEvents?: import("@xylabs/pixel").UserEventHandler<Record<string, unknown>>;
16
- onBuyName?: (name: string) => Promise<void>;
17
+ onCaptureName?: (name: string) => Promise<void>;
17
18
  to?: import("react-router-dom").To;
18
19
  background?: boolean;
19
20
  paper?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"useXnsNameCaptureRouting.d.ts","sourceRoot":"","sources":["../../../../../src/components/XnsNameCapture/hooks/useXnsNameCaptureRouting.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEtD,eAAO,MAAM,wBAAwB,UAAW,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAYlE,CAAA"}
1
+ {"version":3,"file":"useXnsNameCaptureRouting.d.ts","sourceRoot":"","sources":["../../../../../../src/components/XnsNameCapture/hooks/routing/useXnsNameCaptureRouting.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAGzD,eAAO,MAAM,wBAAwB,UAAW,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgBlE,CAAA"}
@@ -0,0 +1,2 @@
1
+ export declare const useXnsNameFromLocation: () => [name: string | undefined, error: Error | undefined];
2
+ //# sourceMappingURL=useXnsNameFromLocation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useXnsNameFromLocation.d.ts","sourceRoot":"","sources":["../../../../../../src/components/XnsNameCapture/hooks/routing/useXnsNameFromLocation.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,sBAAsB,QAAO,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,SAAS,CAmB5F,CAAA"}
@@ -11,9 +11,10 @@ export declare const useXnsNameCaptureProviders: (props: XnsNameCaptureProps) =>
11
11
  event?: string;
12
12
  funnel?: string;
13
13
  userEvents?: import("@xylabs/pixel").UserEventHandler<Record<string, unknown>>;
14
- onBuyName?: (name: string) => Promise<void>;
14
+ onCaptureName?: (name: string) => Promise<void>;
15
15
  navigate?: (to: string) => void;
16
16
  paramsString?: string;
17
+ routingError?: Error;
17
18
  to?: import("react-router").To;
18
19
  background?: boolean;
19
20
  paper?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"useXnsNameCaptureProviders.d.ts","sourceRoot":"","sources":["../../../../../src/components/XnsNameCapture/hooks/useXnsNameCaptureProviders.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEtD,eAAO,MAAM,0BAA0B,UAAW,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAOpE,CAAA"}
1
+ {"version":3,"file":"useXnsNameCaptureProviders.d.ts","sourceRoot":"","sources":["../../../../../src/components/XnsNameCapture/hooks/useXnsNameCaptureProviders.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEtD,eAAO,MAAM,0BAA0B,UAAW,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAOpE,CAAA"}
@@ -77,30 +77,56 @@ var XnsNameCaptureErrors = /* @__PURE__ */ __name(({ error, errorUi, resetError
77
77
  })());
78
78
  }, "XnsNameCaptureErrors");
79
79
 
80
- // src/components/XnsNameCapture/hooks/useXnsNameCaptureProviders.ts
81
- import { useMixpanel } from "@xylabs/react-mixpanel";
80
+ // src/components/XnsNameCapture/hooks/routing/useXnsNameCaptureRouting.ts
82
81
  import { useMemo } from "react";
83
- var useXnsNameCaptureProviders = /* @__PURE__ */ __name((props) => {
84
- const mixpanel = useMixpanel();
85
- return useMemo(() => ({
86
- ...props,
87
- mixpanel: props.mixpanel ?? mixpanel
88
- }), [
89
- props,
90
- mixpanel
91
- ]);
92
- }, "useXnsNameCaptureProviders");
93
-
94
- // src/components/XnsNameCapture/hooks/useXnsNameCaptureRouting.ts
95
- import { useMemo as useMemo2 } from "react";
96
82
  import { useNavigate, useSearchParams } from "react-router-dom";
83
+
84
+ // src/components/XnsNameCapture/hooks/routing/useXnsNameFromLocation.ts
85
+ import { useLocation } from "react-router-dom";
86
+ var useXnsNameFromLocation = /* @__PURE__ */ __name(() => {
87
+ const location = useLocation();
88
+ const search = new URLSearchParams(location.search);
89
+ const rawName = (search.get("xnsname") ?? search.get("name") ?? search.get("username") ?? "").toLowerCase();
90
+ switch (rawName?.split(".").length) {
91
+ case 1: {
92
+ return [
93
+ rawName,
94
+ void 0
95
+ ];
96
+ }
97
+ case 2: {
98
+ const rawNameParts = rawName.split(".");
99
+ if (rawNameParts[1] !== "xyo") {
100
+ return [
101
+ ,
102
+ new Error("Invalid xNS name [Bad root]")
103
+ ];
104
+ }
105
+ return [
106
+ rawNameParts[0],
107
+ void 0
108
+ ];
109
+ }
110
+ default: {
111
+ return [
112
+ ,
113
+ new Error("Invalid xNS name [Too many parts]")
114
+ ];
115
+ }
116
+ }
117
+ }, "useXnsNameFromLocation");
118
+
119
+ // src/components/XnsNameCapture/hooks/routing/useXnsNameCaptureRouting.ts
97
120
  var useXnsNameCaptureRouting = /* @__PURE__ */ __name((props) => {
98
121
  const [params] = useSearchParams();
99
122
  const signatureParam = params.get("signature");
100
123
  const signatureParamString = signatureParam ? `&signature=${encodeURIComponent(signatureParam)}` : "";
101
124
  const navigate = useNavigate();
102
- return useMemo2(() => ({
125
+ const [name, error] = useXnsNameFromLocation();
126
+ return useMemo(() => ({
103
127
  ...props,
128
+ defaultXnsName: name,
129
+ routingError: error,
104
130
  navigate: props.navigate ?? ((to) => navigate(to)),
105
131
  paramsString: signatureParamString
106
132
  }), [
@@ -109,13 +135,27 @@ var useXnsNameCaptureRouting = /* @__PURE__ */ __name((props) => {
109
135
  ]);
110
136
  }, "useXnsNameCaptureRouting");
111
137
 
138
+ // src/components/XnsNameCapture/hooks/useXnsNameCaptureProviders.ts
139
+ import { useMixpanel } from "@xylabs/react-mixpanel";
140
+ import { useMemo as useMemo2 } from "react";
141
+ var useXnsNameCaptureProviders = /* @__PURE__ */ __name((props) => {
142
+ const mixpanel = useMixpanel();
143
+ return useMemo2(() => ({
144
+ ...props,
145
+ mixpanel: props.mixpanel ?? mixpanel
146
+ }), [
147
+ props,
148
+ mixpanel
149
+ ]);
150
+ }, "useXnsNameCaptureProviders");
151
+
112
152
  // src/components/XnsNameCapture/SecondaryLink.tsx
113
153
  import { ArrowForwardRounded } from "@mui/icons-material";
114
154
  import { Stack } from "@mui/material";
115
155
  import { LinkEx } from "@xylabs/react-link";
116
156
  import { XnsNameHelper as XnsNameHelper2 } from "@xyo-network/xns-record-payloadset-plugins";
117
157
  import React3 from "react";
118
- var XnsCaptureSecondaryLink = /* @__PURE__ */ __name(({ event = "Click to Reservation", funnel = "xns", mixpanel, navigate, onBuyName, paramsString = "", placement = "", setError, text = "Or make a free reservation", to = "/xns/reservation", userEvents, xnsName, ...props }) => {
158
+ var XnsCaptureSecondaryLink = /* @__PURE__ */ __name(({ event = "Click to Reservation", funnel = "xns", mixpanel, navigate, onCaptureName, paramsString = "", placement = "", setError, text = "Or make a free reservation", to = "/xns/reservation", userEvents, xnsName, ...props }) => {
119
159
  return /* @__PURE__ */ React3.createElement(LinkEx, {
120
160
  paddingX: 0,
121
161
  color: "inherit",
@@ -137,7 +177,7 @@ var XnsCaptureSecondaryLink = /* @__PURE__ */ __name(({ event = "Click to Reserv
137
177
  elementType: "xns-cta"
138
178
  });
139
179
  navigate?.(`${to}?username=${xnsName}${paramsString}`);
140
- await onBuyName?.(xnsName);
180
+ await onCaptureName?.(xnsName);
141
181
  } else {
142
182
  setError?.(new Error(errors.join(", ")));
143
183
  }
@@ -160,19 +200,19 @@ import { ButtonEx } from "@xylabs/react-button";
160
200
  import { FlexCol, FlexRow as FlexRow2 } from "@xylabs/react-flexbox";
161
201
  import { MIN_DOMAIN_LENGTH as MIN_DOMAIN_LENGTH2, XnsNameHelper as XnsNameHelper3 } from "@xyo-network/xns-record-payloadset-plugins";
162
202
  import React4, { useCallback, useState as useState2 } from "react";
163
- var XnsNameCapture = /* @__PURE__ */ __name(({ autoFocus = false, buttonText = "Buy My Name", children, defaultXnsName, errorUi = "alert", event = "Click to Checkout", funnel = "xns", mixpanel, mobileButtonText = "Buy", navigate, onBuyName: onBuyNameProp, paramsString = "", placement = "", showSecondary = false, to = "/xns/estimation", userEvents, ...props }) => {
203
+ var XnsNameCapture = /* @__PURE__ */ __name(({ autoFocus = false, buttonText = "Buy My Name", children, defaultXnsName, errorUi = "alert", event = "Click to Checkout", funnel = "xns", mixpanel, mobileButtonText = "Buy", navigate, onCaptureName: onCaptureNameProp, paramsString = "", placement = "", routingError, showSecondary = false, to = "/xns/estimation", userEvents, ...props }) => {
164
204
  const [xnsName, setXnsName] = useState2(() => defaultXnsName ?? "");
165
- const [error, setError] = useState2();
205
+ const [error, setError] = useState2(routingError);
166
206
  const theme = useTheme3();
167
207
  const isMobile = useMediaQuery2(theme.breakpoints.down("md"));
168
- const buyDisabled = !xnsName || xnsName.length < MIN_DOMAIN_LENGTH2;
208
+ const captureDisabled = !xnsName || xnsName.length < MIN_DOMAIN_LENGTH2;
169
209
  const handleChange = /* @__PURE__ */ __name((event2) => {
170
210
  const NsName = XnsNameHelper3.mask(event2.target.value);
171
211
  setXnsName(NsName);
172
212
  setError(void 0);
173
213
  }, "handleChange");
174
- const onBuyName = useCallback(async () => {
175
- if (!xnsName) return;
214
+ const onCaptureName = useCallback(async () => {
215
+ if (captureDisabled) return;
176
216
  mixpanel?.track(event, {
177
217
  Funnel: funnel,
178
218
  Placement: placement
@@ -185,7 +225,7 @@ var XnsNameCapture = /* @__PURE__ */ __name(({ autoFocus = false, buttonText = "
185
225
  elementName: event,
186
226
  elementType: "xns-cta"
187
227
  });
188
- await onBuyNameProp?.(xnsName);
228
+ await onCaptureNameProp?.(xnsName);
189
229
  navigate?.(`${to}?username=${xnsName}${paramsString}`);
190
230
  } else {
191
231
  setError(new Error(errors.join(", ")));
@@ -201,12 +241,12 @@ var XnsNameCapture = /* @__PURE__ */ __name(({ autoFocus = false, buttonText = "
201
241
  xnsName
202
242
  ]);
203
243
  const onKeyDown = useCallback(async (event2) => {
204
- if (event2.key === "Enter" && !buyDisabled) {
205
- await onBuyName?.();
244
+ if (event2.key === "Enter" && !captureDisabled) {
245
+ await onCaptureName?.();
206
246
  }
207
247
  }, [
208
- buyDisabled,
209
- onBuyName
248
+ captureDisabled,
249
+ onCaptureName
210
250
  ]);
211
251
  return /* @__PURE__ */ React4.createElement(
212
252
  FlexCol,
@@ -227,11 +267,11 @@ var XnsNameCapture = /* @__PURE__ */ __name(({ autoFocus = false, buttonText = "
227
267
  onChange: handleChange,
228
268
  onBlur: handleChange
229
269
  }), /* @__PURE__ */ React4.createElement(ButtonEx, {
230
- disabled: buyDisabled,
270
+ disabled: captureDisabled,
231
271
  variant: "contained",
232
272
  color: "success",
233
273
  endIcon: /* @__PURE__ */ React4.createElement(KeyboardArrowRightRounded, null),
234
- onClick: onBuyName
274
+ onClick: onCaptureName
235
275
  }, isMobile ? mobileButtonText : buttonText)),
236
276
  showSecondary === true ? /* @__PURE__ */ React4.createElement(XnsCaptureSecondaryLink, {
237
277
  xnsName,
@@ -271,6 +311,7 @@ export {
271
311
  XnsNameCaptureErrors,
272
312
  XnsNameCaptureWithContext,
273
313
  useXnsNameCaptureProviders,
274
- useXnsNameCaptureRouting
314
+ useXnsNameCaptureRouting,
315
+ useXnsNameFromLocation
275
316
  };
276
317
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/EstimateName/EstimateNameTextField.tsx","../../src/components/XnsNameCapture/Errors.tsx","../../src/components/XnsNameCapture/hooks/useXnsNameCaptureProviders.ts","../../src/components/XnsNameCapture/hooks/useXnsNameCaptureRouting.ts","../../src/components/XnsNameCapture/SecondaryLink.tsx","../../src/components/XnsNameCapture/XnsNameCapture.tsx","../../src/components/XnsNameCapture/XnsNameCaptureWithContext.tsx"],"sourcesContent":["import type { StandardTextFieldProps, TextFieldProps } from '@mui/material'\nimport {\n alpha, TextField, useTheme,\n} from '@mui/material'\nimport { MIN_DOMAIN_LENGTH, XnsNameHelper } from '@xyo-network/xns-record-payloadset-plugins'\nimport React, { useState } from 'react'\n\nexport interface XnsEstimateNameTextFieldProps {\n maskOutput?: boolean\n}\n\nexport const XnsEstimateNameTextField: React.FC<XnsEstimateNameTextFieldProps & TextFieldProps> = ({\n maskOutput = true, onChange: onChangeProp, onBlur: onBlurProp, ...props\n}) => {\n const theme = useTheme()\n const [validLength, setValidLength] = useState(false)\n\n const inputRef = React.useRef<HTMLInputElement>(null)\n\n // override onChange to mask the input and update the event value\n const handleChange: StandardTextFieldProps['onChange'] = (event) => {\n if (maskOutput) {\n const value = event.target.value\n event.target.value = XnsNameHelper.mask(value)\n }\n onChangeProp?.(event)\n\n if (inputRef.current) {\n setValidLength(inputRef.current.value.length >= MIN_DOMAIN_LENGTH)\n }\n }\n\n const handleBlur: StandardTextFieldProps['onBlur'] = (event) => {\n if (maskOutput) {\n const value = event.target.value\n event.target.value = XnsNameHelper.mask(value, { maskStartEndHyphens: true })\n }\n onBlurProp?.(event)\n }\n\n return (\n <TextField\n inputProps={{ style: { color: validLength ? theme.palette.text.primary : alpha(theme.palette.text.primary, 0.5) } }}\n inputRef={inputRef}\n onBlur={handleBlur}\n onChange={handleChange}\n {...props}\n />\n )\n}\n","import {\n Alert, Snackbar, useMediaQuery, useTheme,\n} from '@mui/material'\nimport { FlexRow } from '@xylabs/react-flexbox'\nimport React from 'react'\n\nexport interface XnsNameCaptureErrorsProps {\n error?: Error\n errorUi?: 'alert' | 'toast'\n resetError?: () => void\n}\n\nexport const XnsNameCaptureErrors: React.FC<XnsNameCaptureErrorsProps> = ({\n error, errorUi, resetError,\n}) => {\n const theme = useTheme()\n const isMobile = useMediaQuery(theme.breakpoints.down('md'))\n\n return (\n <>\n {(errorUi === 'toast')\n ? (\n <Snackbar\n open={!!error}\n message={error?.toString()}\n autoHideDuration={3000}\n onClose={() => resetError?.()}\n anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}\n >\n <Alert\n severity=\"error\"\n sx={{\n width: '100%', display: (isMobile && !error) ? 'none' : undefined, visibility: error ? 'visible' : 'hidden',\n }}\n >\n {error?.message}\n </Alert>\n </Snackbar>\n )\n : (() => {\n // setTimeout(() => setError(undefined), 1500)\n return (\n <FlexRow alignSelf=\"stretch\">\n <Alert\n severity=\"error\"\n sx={{ display: (isMobile && !error) ? 'none' : undefined, visibility: error ? 'visible' : 'hidden' }}\n >\n {error?.message}\n </Alert>\n </FlexRow>\n )\n })()}\n </>\n )\n}\n","import { useMixpanel } from '@xylabs/react-mixpanel'\nimport { useMemo } from 'react'\n\nimport type { XnsNameCaptureProps } from '../Props.ts'\n\nexport const useXnsNameCaptureProviders = (props: XnsNameCaptureProps) => {\n const mixpanel = useMixpanel()\n\n return useMemo(() => ({\n ...props,\n mixpanel: props.mixpanel ?? mixpanel,\n }), [props, mixpanel])\n}\n","import { useMemo } from 'react'\nimport { useNavigate, useSearchParams } from 'react-router-dom'\n\nimport type { XnsNameCaptureProps } from '../Props.ts'\n\nexport const useXnsNameCaptureRouting = (props: XnsNameCaptureProps) => {\n const [params] = useSearchParams()\n const signatureParam = params.get('signature')\n const signatureParamString = signatureParam ? `&signature=${encodeURIComponent(signatureParam)}` : ''\n\n const navigate = useNavigate()\n\n return useMemo(() => ({\n ...props,\n navigate: props.navigate ?? ((to: string) => navigate(to)),\n paramsString: signatureParamString,\n }), [props, signatureParamString])\n}\n","import { ArrowForwardRounded } from '@mui/icons-material'\nimport { Stack } from '@mui/material'\nimport type { LinkExProps } from '@xylabs/react-link'\nimport { LinkEx } from '@xylabs/react-link'\nimport { XnsNameHelper } from '@xyo-network/xns-record-payloadset-plugins'\nimport type { Dispatch } from 'react'\nimport React from 'react'\n\nimport type {\n XnsNameCaptureBuyCallbacks, XnsNameCaptureRoutingProps, XnsNameCaptureTrackingProps,\n} from './Props.ts'\n\nexport interface XnsCaptureSecondaryLinkProps extends XnsNameCaptureTrackingProps, XnsNameCaptureRoutingProps, XnsNameCaptureBuyCallbacks, LinkExProps {\n event?: string\n funnel?: string\n placement?: string\n setError?: Dispatch<Error | undefined>\n text?: string\n xnsName: string\n}\n\nexport const XnsCaptureSecondaryLink: React.FC<XnsCaptureSecondaryLinkProps> = ({\n event = 'Click to Reservation',\n funnel = 'xns',\n mixpanel,\n navigate,\n onBuyName,\n paramsString = '',\n placement = '',\n setError,\n text = 'Or make a free reservation',\n to = '/xns/reservation',\n userEvents,\n xnsName,\n ...props\n}) => {\n return (\n <LinkEx\n paddingX={0}\n color=\"inherit\"\n style={{ textDecoration: 'underline', textUnderlineOffset: '5px' }}\n onClick={async () => {\n mixpanel?.track(event, {\n Funnel: funnel,\n Placement: placement,\n })\n const formattedXnsName = `${xnsName}.xyo`\n const helper = XnsNameHelper.fromString(formattedXnsName)\n const [valid, errors] = await helper.validate()\n if (valid) {\n await userEvents?.userClick({ elementName: event, elementType: 'xns-cta' })\n navigate?.(`${to}?username=${xnsName}${paramsString}`)\n await onBuyName?.(xnsName)\n } else {\n setError?.(new Error(errors.join(', ')))\n }\n }}\n {...props}\n >\n <Stack flexDirection=\"row\" gap={0.5} alignItems=\"center\" sx={{ cursor: 'pointer' }}>\n {text}\n <ArrowForwardRounded />\n </Stack>\n </LinkEx>\n )\n}\n","import { KeyboardArrowRightRounded } from '@mui/icons-material'\nimport type { StandardTextFieldProps } from '@mui/material'\nimport { useMediaQuery, useTheme } from '@mui/material'\nimport { ButtonEx } from '@xylabs/react-button'\nimport { FlexCol, FlexRow } from '@xylabs/react-flexbox'\nimport { MIN_DOMAIN_LENGTH, XnsNameHelper } from '@xyo-network/xns-record-payloadset-plugins'\nimport type { KeyboardEventHandler } from 'react'\nimport React, { useCallback, useState } from 'react'\n\nimport { XnsEstimateNameTextField } from '../EstimateName/index.ts'\nimport { XnsNameCaptureErrors } from './Errors.tsx'\nimport type { XnsNameCaptureProps } from './Props.ts'\nimport { XnsCaptureSecondaryLink } from './SecondaryLink.js'\n\nexport const XnsNameCapture: React.FC<XnsNameCaptureProps> = ({\n autoFocus = false,\n buttonText = 'Buy My Name',\n children,\n defaultXnsName,\n errorUi = 'alert',\n event = 'Click to Checkout',\n funnel = 'xns',\n mixpanel,\n mobileButtonText = 'Buy',\n navigate,\n onBuyName: onBuyNameProp,\n paramsString = '',\n placement = '',\n showSecondary = false,\n to = '/xns/estimation',\n userEvents,\n ...props\n}) => {\n const [xnsName, setXnsName] = useState<string>(() => defaultXnsName ?? '')\n const [error, setError] = useState<Error | undefined>()\n\n const theme = useTheme()\n const isMobile = useMediaQuery(theme.breakpoints.down('md'))\n\n const buyDisabled = !xnsName || xnsName.length < MIN_DOMAIN_LENGTH\n\n const handleChange: StandardTextFieldProps['onChange'] = (event) => {\n const NsName = XnsNameHelper.mask(event.target.value)\n setXnsName(NsName)\n setError(undefined)\n }\n\n const onBuyName = useCallback(async () => {\n if (!xnsName) return\n\n mixpanel?.track(event, {\n Funnel: funnel,\n Placement: placement,\n })\n const formattedXnsName = `${xnsName}.xyo`\n const helper = XnsNameHelper.fromString(formattedXnsName)\n const [valid, errors] = await helper.validate()\n if (valid) {\n await userEvents?.userClick({ elementName: event, elementType: 'xns-cta' })\n await onBuyNameProp?.(xnsName)\n navigate?.(`${to}?username=${xnsName}${paramsString}`)\n } else {\n setError(new Error(errors.join(', ')))\n }\n }, [event, funnel, mixpanel, paramsString, placement, to, userEvents, xnsName])\n\n const onKeyDown: KeyboardEventHandler<HTMLDivElement> = useCallback(async (event) => {\n if (event.key === 'Enter' && !buyDisabled) {\n await onBuyName?.()\n }\n }, [buyDisabled, onBuyName])\n\n return (\n <FlexCol gap={showSecondary ? 1.5 : 0} alignItems=\"center\" {...props}>\n <FlexRow gap={1}>\n <XnsEstimateNameTextField\n autoFocus={autoFocus}\n label=\"xNS Name\"\n variant=\"outlined\"\n size=\"small\"\n value={xnsName ?? ''}\n onKeyDown={onKeyDown}\n onChange={handleChange}\n onBlur={handleChange}\n />\n <ButtonEx\n disabled={buyDisabled}\n variant=\"contained\"\n color=\"success\"\n endIcon={<KeyboardArrowRightRounded />}\n onClick={onBuyName}\n >\n {isMobile ? mobileButtonText : buttonText}\n </ButtonEx>\n </FlexRow>\n {(showSecondary === true)\n ? (\n <XnsCaptureSecondaryLink\n xnsName={xnsName}\n placement={placement}\n funnel={funnel}\n setError={setError}\n />\n )\n : null}\n {\n // eslint-disable-next-line unicorn/prefer-logical-operator-over-ternary\n showSecondary ? showSecondary : null\n }\n {children}\n <XnsNameCaptureErrors error={error} errorUi={errorUi} resetError={() => setError(undefined)} />\n </FlexCol>\n )\n}\n","import React, { useMemo } from 'react'\n\nimport { useXnsNameCaptureProviders, useXnsNameCaptureRouting } from './hooks/index.ts'\nimport type { XnsNameCaptureProps } from './Props.ts'\nimport { XnsNameCapture } from './XnsNameCapture.tsx'\n\nexport const XnsNameCaptureWithContext: React.FC<XnsNameCaptureProps> = (props) => {\n const routingProps = useXnsNameCaptureRouting(props)\n const providersProps = useXnsNameCaptureProviders(routingProps)\n\n const updatedProps = useMemo<XnsNameCaptureProps>(() => ({\n ...props,\n ...routingProps,\n ...providersProps,\n }), [providersProps])\n\n return (\n <XnsNameCapture {...updatedProps} />\n )\n}\n"],"mappings":"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","names":["alpha","TextField","useTheme","MIN_DOMAIN_LENGTH","XnsNameHelper","React","useState","XnsEstimateNameTextField","maskOutput","onChange","onChangeProp","onBlur","onBlurProp","props","theme","useTheme","validLength","setValidLength","useState","inputRef","React","useRef","handleChange","event","value","target","XnsNameHelper","mask","current","length","MIN_DOMAIN_LENGTH","handleBlur","maskStartEndHyphens","TextField","inputProps","style","color","palette","text","primary","alpha","Alert","Snackbar","useMediaQuery","useTheme","FlexRow","React","XnsNameCaptureErrors","error","errorUi","resetError","theme","useTheme","isMobile","useMediaQuery","breakpoints","down","React","Snackbar","open","message","toString","autoHideDuration","onClose","anchorOrigin","vertical","horizontal","Alert","severity","sx","width","display","undefined","visibility","FlexRow","alignSelf","useMixpanel","useMemo","useXnsNameCaptureProviders","props","mixpanel","useMixpanel","useMemo","useMemo","useNavigate","useSearchParams","useXnsNameCaptureRouting","props","params","useSearchParams","signatureParam","get","signatureParamString","encodeURIComponent","navigate","useNavigate","useMemo","to","paramsString","ArrowForwardRounded","Stack","LinkEx","XnsNameHelper","React","XnsCaptureSecondaryLink","event","funnel","mixpanel","navigate","onBuyName","paramsString","placement","setError","text","to","userEvents","xnsName","props","React","LinkEx","paddingX","color","style","textDecoration","textUnderlineOffset","onClick","track","Funnel","Placement","formattedXnsName","helper","XnsNameHelper","fromString","valid","errors","validate","userClick","elementName","elementType","Error","join","Stack","flexDirection","gap","alignItems","sx","cursor","ArrowForwardRounded","KeyboardArrowRightRounded","useMediaQuery","useTheme","ButtonEx","FlexCol","FlexRow","MIN_DOMAIN_LENGTH","XnsNameHelper","React","useCallback","useState","XnsNameCapture","autoFocus","buttonText","children","defaultXnsName","errorUi","event","funnel","mixpanel","mobileButtonText","navigate","onBuyName","onBuyNameProp","paramsString","placement","showSecondary","to","userEvents","props","xnsName","setXnsName","useState","error","setError","theme","useTheme","isMobile","useMediaQuery","breakpoints","down","buyDisabled","length","MIN_DOMAIN_LENGTH","handleChange","NsName","XnsNameHelper","mask","target","value","undefined","useCallback","track","Funnel","Placement","formattedXnsName","helper","fromString","valid","errors","validate","userClick","elementName","elementType","Error","join","onKeyDown","key","React","FlexCol","gap","alignItems","FlexRow","XnsEstimateNameTextField","label","variant","size","onChange","onBlur","ButtonEx","disabled","color","endIcon","KeyboardArrowRightRounded","onClick","XnsCaptureSecondaryLink","XnsNameCaptureErrors","resetError","React","useMemo","XnsNameCaptureWithContext","props","routingProps","useXnsNameCaptureRouting","providersProps","useXnsNameCaptureProviders","updatedProps","useMemo","React","XnsNameCapture"]}
1
+ {"version":3,"sources":["../../src/components/EstimateName/EstimateNameTextField.tsx","../../src/components/XnsNameCapture/Errors.tsx","../../src/components/XnsNameCapture/hooks/routing/useXnsNameCaptureRouting.ts","../../src/components/XnsNameCapture/hooks/routing/useXnsNameFromLocation.ts","../../src/components/XnsNameCapture/hooks/useXnsNameCaptureProviders.ts","../../src/components/XnsNameCapture/SecondaryLink.tsx","../../src/components/XnsNameCapture/XnsNameCapture.tsx","../../src/components/XnsNameCapture/XnsNameCaptureWithContext.tsx"],"sourcesContent":["import type { StandardTextFieldProps, TextFieldProps } from '@mui/material'\nimport {\n alpha, TextField, useTheme,\n} from '@mui/material'\nimport { MIN_DOMAIN_LENGTH, XnsNameHelper } from '@xyo-network/xns-record-payloadset-plugins'\nimport React, { useState } from 'react'\n\nexport interface XnsEstimateNameTextFieldProps {\n maskOutput?: boolean\n}\n\nexport const XnsEstimateNameTextField: React.FC<XnsEstimateNameTextFieldProps & TextFieldProps> = ({\n maskOutput = true, onChange: onChangeProp, onBlur: onBlurProp, ...props\n}) => {\n const theme = useTheme()\n const [validLength, setValidLength] = useState(false)\n\n const inputRef = React.useRef<HTMLInputElement>(null)\n\n // override onChange to mask the input and update the event value\n const handleChange: StandardTextFieldProps['onChange'] = (event) => {\n if (maskOutput) {\n const value = event.target.value\n event.target.value = XnsNameHelper.mask(value)\n }\n onChangeProp?.(event)\n\n if (inputRef.current) {\n setValidLength(inputRef.current.value.length >= MIN_DOMAIN_LENGTH)\n }\n }\n\n const handleBlur: StandardTextFieldProps['onBlur'] = (event) => {\n if (maskOutput) {\n const value = event.target.value\n event.target.value = XnsNameHelper.mask(value, { maskStartEndHyphens: true })\n }\n onBlurProp?.(event)\n }\n\n return (\n <TextField\n inputProps={{ style: { color: validLength ? theme.palette.text.primary : alpha(theme.palette.text.primary, 0.5) } }}\n inputRef={inputRef}\n onBlur={handleBlur}\n onChange={handleChange}\n {...props}\n />\n )\n}\n","import {\n Alert, Snackbar, useMediaQuery, useTheme,\n} from '@mui/material'\nimport { FlexRow } from '@xylabs/react-flexbox'\nimport React from 'react'\n\nexport interface XnsNameCaptureErrorsProps {\n error?: Error\n errorUi?: 'alert' | 'toast'\n resetError?: () => void\n}\n\nexport const XnsNameCaptureErrors: React.FC<XnsNameCaptureErrorsProps> = ({\n error, errorUi, resetError,\n}) => {\n const theme = useTheme()\n const isMobile = useMediaQuery(theme.breakpoints.down('md'))\n\n return (\n <>\n {(errorUi === 'toast')\n ? (\n <Snackbar\n open={!!error}\n message={error?.toString()}\n autoHideDuration={3000}\n onClose={() => resetError?.()}\n anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}\n >\n <Alert\n severity=\"error\"\n sx={{\n width: '100%', display: (isMobile && !error) ? 'none' : undefined, visibility: error ? 'visible' : 'hidden',\n }}\n >\n {error?.message}\n </Alert>\n </Snackbar>\n )\n : (() => {\n // setTimeout(() => setError(undefined), 1500)\n return (\n <FlexRow alignSelf=\"stretch\">\n <Alert\n severity=\"error\"\n sx={{ display: (isMobile && !error) ? 'none' : undefined, visibility: error ? 'visible' : 'hidden' }}\n >\n {error?.message}\n </Alert>\n </FlexRow>\n )\n })()}\n </>\n )\n}\n","import { useMemo } from 'react'\nimport { useNavigate, useSearchParams } from 'react-router-dom'\n\nimport type { XnsNameCaptureProps } from '../../Props.ts'\nimport { useXnsNameFromLocation } from './useXnsNameFromLocation.ts'\n\nexport const useXnsNameCaptureRouting = (props: XnsNameCaptureProps) => {\n const [params] = useSearchParams()\n const signatureParam = params.get('signature')\n const signatureParamString = signatureParam ? `&signature=${encodeURIComponent(signatureParam)}` : ''\n\n const navigate = useNavigate()\n\n const [name, error] = useXnsNameFromLocation()\n\n return useMemo(() => ({\n ...props,\n defaultXnsName: name,\n routingError: error,\n navigate: props.navigate ?? ((to: string) => navigate(to)),\n paramsString: signatureParamString,\n }), [props, signatureParamString])\n}\n","import { useLocation } from 'react-router-dom'\n\n/**\n * Assumes the user was redirected with a link that contains a username query parameter.\n * @returns The xNS name from the URI username query parameter.\n */\nexport const useXnsNameFromLocation = (): [name: string | undefined, error: Error | undefined] => {\n const location = useLocation()\n const search = new URLSearchParams(location.search)\n const rawName = (search.get('xnsname') ?? search.get('name') ?? search.get('username') ?? '').toLowerCase()\n switch (rawName?.split('.').length) {\n case 1: {\n return [rawName, undefined]\n }\n case 2: {\n const rawNameParts = rawName.split('.')\n if (rawNameParts[1] !== 'xyo') {\n return [, new Error('Invalid xNS name [Bad root]')]\n }\n return [rawNameParts[0], undefined]\n }\n default: {\n return [, new Error('Invalid xNS name [Too many parts]')]\n }\n }\n}\n","import { useMixpanel } from '@xylabs/react-mixpanel'\nimport { useMemo } from 'react'\n\nimport type { XnsNameCaptureProps } from '../Props.ts'\n\nexport const useXnsNameCaptureProviders = (props: XnsNameCaptureProps) => {\n const mixpanel = useMixpanel()\n\n return useMemo(() => ({\n ...props,\n mixpanel: props.mixpanel ?? mixpanel,\n }), [props, mixpanel])\n}\n","import { ArrowForwardRounded } from '@mui/icons-material'\nimport { Stack } from '@mui/material'\nimport type { LinkExProps } from '@xylabs/react-link'\nimport { LinkEx } from '@xylabs/react-link'\nimport { XnsNameHelper } from '@xyo-network/xns-record-payloadset-plugins'\nimport type { Dispatch } from 'react'\nimport React from 'react'\n\nimport type {\n XnsNameCaptureBuyCallbacks, XnsNameCaptureRoutingProps, XnsNameCaptureTrackingProps,\n} from './Props.ts'\n\nexport interface XnsCaptureSecondaryLinkProps extends XnsNameCaptureTrackingProps, XnsNameCaptureRoutingProps, XnsNameCaptureBuyCallbacks, LinkExProps {\n event?: string\n funnel?: string\n placement?: string\n setError?: Dispatch<Error | undefined>\n text?: string\n xnsName: string\n}\n\nexport const XnsCaptureSecondaryLink: React.FC<XnsCaptureSecondaryLinkProps> = ({\n event = 'Click to Reservation',\n funnel = 'xns',\n mixpanel,\n navigate,\n onCaptureName,\n paramsString = '',\n placement = '',\n setError,\n text = 'Or make a free reservation',\n to = '/xns/reservation',\n userEvents,\n xnsName,\n ...props\n}) => {\n return (\n <LinkEx\n paddingX={0}\n color=\"inherit\"\n style={{ textDecoration: 'underline', textUnderlineOffset: '5px' }}\n onClick={async () => {\n mixpanel?.track(event, {\n Funnel: funnel,\n Placement: placement,\n })\n const formattedXnsName = `${xnsName}.xyo`\n const helper = XnsNameHelper.fromString(formattedXnsName)\n const [valid, errors] = await helper.validate()\n if (valid) {\n await userEvents?.userClick({ elementName: event, elementType: 'xns-cta' })\n navigate?.(`${to}?username=${xnsName}${paramsString}`)\n await onCaptureName?.(xnsName)\n } else {\n setError?.(new Error(errors.join(', ')))\n }\n }}\n {...props}\n >\n <Stack flexDirection=\"row\" gap={0.5} alignItems=\"center\" sx={{ cursor: 'pointer' }}>\n {text}\n <ArrowForwardRounded />\n </Stack>\n </LinkEx>\n )\n}\n","import { KeyboardArrowRightRounded } from '@mui/icons-material'\nimport type { StandardTextFieldProps } from '@mui/material'\nimport { useMediaQuery, useTheme } from '@mui/material'\nimport { ButtonEx } from '@xylabs/react-button'\nimport { FlexCol, FlexRow } from '@xylabs/react-flexbox'\nimport { MIN_DOMAIN_LENGTH, XnsNameHelper } from '@xyo-network/xns-record-payloadset-plugins'\nimport type { KeyboardEventHandler } from 'react'\nimport React, { useCallback, useState } from 'react'\n\nimport { XnsEstimateNameTextField } from '../EstimateName/index.ts'\nimport { XnsNameCaptureErrors } from './Errors.tsx'\nimport type { XnsNameCaptureProps } from './Props.ts'\nimport { XnsCaptureSecondaryLink } from './SecondaryLink.js'\n\nexport const XnsNameCapture: React.FC<XnsNameCaptureProps> = ({\n autoFocus = false,\n buttonText = 'Buy My Name',\n children,\n defaultXnsName,\n errorUi = 'alert',\n event = 'Click to Checkout',\n funnel = 'xns',\n mixpanel,\n mobileButtonText = 'Buy',\n navigate,\n onCaptureName: onCaptureNameProp,\n paramsString = '',\n placement = '',\n routingError,\n showSecondary = false,\n to = '/xns/estimation',\n userEvents,\n ...props\n}) => {\n const [xnsName, setXnsName] = useState<string>(() => defaultXnsName ?? '')\n const [error, setError] = useState<Error | undefined>(routingError)\n\n const theme = useTheme()\n const isMobile = useMediaQuery(theme.breakpoints.down('md'))\n\n const captureDisabled = !xnsName || xnsName.length < MIN_DOMAIN_LENGTH\n\n const handleChange: StandardTextFieldProps['onChange'] = (event) => {\n const NsName = XnsNameHelper.mask(event.target.value)\n setXnsName(NsName)\n setError(undefined)\n }\n\n const onCaptureName = useCallback(async () => {\n if (captureDisabled) return\n mixpanel?.track(event, {\n Funnel: funnel,\n Placement: placement,\n })\n const formattedXnsName = `${xnsName}.xyo`\n const helper = XnsNameHelper.fromString(formattedXnsName)\n const [valid, errors] = await helper.validate()\n if (valid) {\n await userEvents?.userClick({ elementName: event, elementType: 'xns-cta' })\n await onCaptureNameProp?.(xnsName)\n navigate?.(`${to}?username=${xnsName}${paramsString}`)\n } else {\n setError(new Error(errors.join(', ')))\n }\n }, [event, funnel, mixpanel, paramsString, placement, to, userEvents, xnsName])\n\n const onKeyDown: KeyboardEventHandler<HTMLDivElement> = useCallback(async (event) => {\n if (event.key === 'Enter' && !captureDisabled) {\n await onCaptureName?.()\n }\n }, [captureDisabled, onCaptureName])\n\n return (\n <FlexCol gap={showSecondary ? 1.5 : 0} alignItems=\"center\" {...props}>\n <FlexRow gap={1}>\n <XnsEstimateNameTextField\n autoFocus={autoFocus}\n label=\"xNS Name\"\n variant=\"outlined\"\n size=\"small\"\n value={xnsName ?? ''}\n onKeyDown={onKeyDown}\n onChange={handleChange}\n onBlur={handleChange}\n />\n <ButtonEx\n disabled={captureDisabled}\n variant=\"contained\"\n color=\"success\"\n endIcon={<KeyboardArrowRightRounded />}\n onClick={onCaptureName}\n >\n {isMobile ? mobileButtonText : buttonText}\n </ButtonEx>\n </FlexRow>\n {(showSecondary === true)\n ? (\n <XnsCaptureSecondaryLink\n xnsName={xnsName}\n placement={placement}\n funnel={funnel}\n setError={setError}\n />\n )\n : null}\n {\n // eslint-disable-next-line unicorn/prefer-logical-operator-over-ternary\n showSecondary ? showSecondary : null\n }\n {children}\n <XnsNameCaptureErrors error={error} errorUi={errorUi} resetError={() => setError(undefined)} />\n </FlexCol>\n )\n}\n","import React, { useMemo } from 'react'\n\nimport { useXnsNameCaptureProviders, useXnsNameCaptureRouting } from './hooks/index.ts'\nimport type { XnsNameCaptureProps } from './Props.ts'\nimport { XnsNameCapture } from './XnsNameCapture.tsx'\n\nexport const XnsNameCaptureWithContext: React.FC<XnsNameCaptureProps> = (props) => {\n const routingProps = useXnsNameCaptureRouting(props)\n const providersProps = useXnsNameCaptureProviders(routingProps)\n\n const updatedProps = useMemo<XnsNameCaptureProps>(() => ({\n ...props,\n ...routingProps,\n ...providersProps,\n }), [providersProps])\n\n return (\n <XnsNameCapture {...updatedProps} />\n )\n}\n"],"mappings":"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","names":["alpha","TextField","useTheme","MIN_DOMAIN_LENGTH","XnsNameHelper","React","useState","XnsEstimateNameTextField","maskOutput","onChange","onChangeProp","onBlur","onBlurProp","props","theme","useTheme","validLength","setValidLength","useState","inputRef","React","useRef","handleChange","event","value","target","XnsNameHelper","mask","current","length","MIN_DOMAIN_LENGTH","handleBlur","maskStartEndHyphens","TextField","inputProps","style","color","palette","text","primary","alpha","Alert","Snackbar","useMediaQuery","useTheme","FlexRow","React","XnsNameCaptureErrors","error","errorUi","resetError","theme","useTheme","isMobile","useMediaQuery","breakpoints","down","React","Snackbar","open","message","toString","autoHideDuration","onClose","anchorOrigin","vertical","horizontal","Alert","severity","sx","width","display","undefined","visibility","FlexRow","alignSelf","useMemo","useNavigate","useSearchParams","useLocation","useXnsNameFromLocation","location","useLocation","search","URLSearchParams","rawName","get","toLowerCase","split","length","undefined","rawNameParts","Error","useXnsNameCaptureRouting","props","params","useSearchParams","signatureParam","get","signatureParamString","encodeURIComponent","navigate","useNavigate","name","error","useXnsNameFromLocation","useMemo","defaultXnsName","routingError","to","paramsString","useMixpanel","useMemo","useXnsNameCaptureProviders","props","mixpanel","useMixpanel","useMemo","ArrowForwardRounded","Stack","LinkEx","XnsNameHelper","React","XnsCaptureSecondaryLink","event","funnel","mixpanel","navigate","onCaptureName","paramsString","placement","setError","text","to","userEvents","xnsName","props","React","LinkEx","paddingX","color","style","textDecoration","textUnderlineOffset","onClick","track","Funnel","Placement","formattedXnsName","helper","XnsNameHelper","fromString","valid","errors","validate","userClick","elementName","elementType","Error","join","Stack","flexDirection","gap","alignItems","sx","cursor","ArrowForwardRounded","KeyboardArrowRightRounded","useMediaQuery","useTheme","ButtonEx","FlexCol","FlexRow","MIN_DOMAIN_LENGTH","XnsNameHelper","React","useCallback","useState","XnsNameCapture","autoFocus","buttonText","children","defaultXnsName","errorUi","event","funnel","mixpanel","mobileButtonText","navigate","onCaptureName","onCaptureNameProp","paramsString","placement","routingError","showSecondary","to","userEvents","props","xnsName","setXnsName","useState","error","setError","theme","useTheme","isMobile","useMediaQuery","breakpoints","down","captureDisabled","length","MIN_DOMAIN_LENGTH","handleChange","NsName","XnsNameHelper","mask","target","value","undefined","useCallback","track","Funnel","Placement","formattedXnsName","helper","fromString","valid","errors","validate","userClick","elementName","elementType","Error","join","onKeyDown","key","React","FlexCol","gap","alignItems","FlexRow","XnsEstimateNameTextField","label","variant","size","onChange","onBlur","ButtonEx","disabled","color","endIcon","KeyboardArrowRightRounded","onClick","XnsCaptureSecondaryLink","XnsNameCaptureErrors","resetError","React","useMemo","XnsNameCaptureWithContext","props","routingProps","useXnsNameCaptureRouting","providersProps","useXnsNameCaptureProviders","updatedProps","useMemo","React","XnsNameCapture"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xyo-network/react-xns",
3
- "version": "3.0.11",
3
+ "version": "3.0.13",
4
4
  "description": "Common React library for all XYO projects that use React",
5
5
  "keywords": [
6
6
  "xyo",
@@ -59,7 +59,7 @@
59
59
  "@types/mixpanel-browser": "^2.50.0",
60
60
  "@xylabs/ts-scripts-yarn3": "^4.0.7",
61
61
  "@xylabs/tsconfig-react": "^4.0.7",
62
- "@xyo-network/react-storybook": "^3.0.11",
62
+ "@xyo-network/react-storybook": "^3.0.13",
63
63
  "react": "^18.3.1",
64
64
  "react-dom": "^18.3.1",
65
65
  "react-router-dom": "^6.26.1",
@@ -5,7 +5,7 @@ import type { ReactNode } from 'react'
5
5
  import type { To } from 'react-router-dom'
6
6
 
7
7
  export interface XnsNameCaptureBuyCallbacks {
8
- onBuyName?: (name: string) => Promise<void>
8
+ onCaptureName?: (name: string) => Promise<void>
9
9
  }
10
10
 
11
11
  /**
@@ -24,6 +24,7 @@ export interface XnsNameCaptureTrackingProps {
24
24
  export interface XnsNameCaptureRoutingProps {
25
25
  navigate?: (to: string) => void
26
26
  paramsString?: string
27
+ routingError?: Error
27
28
  to?: To
28
29
  }
29
30
 
@@ -13,6 +13,6 @@ const Default = Template.bind({})
13
13
  Default.args = {}
14
14
 
15
15
  const WithOnBuyName = Template.bind({})
16
- WithOnBuyName.args = { xnsName: 'testing123', onBuyName: (name: string) => Promise.resolve(alert(`Buy Name: ${name}`)) }
16
+ WithOnBuyName.args = { xnsName: 'testing123', onCaptureName: (name: string) => Promise.resolve(alert(`Buy Name: ${name}`)) }
17
17
 
18
18
  export { Default, WithOnBuyName }
@@ -24,7 +24,7 @@ export const XnsCaptureSecondaryLink: React.FC<XnsCaptureSecondaryLinkProps> = (
24
24
  funnel = 'xns',
25
25
  mixpanel,
26
26
  navigate,
27
- onBuyName,
27
+ onCaptureName,
28
28
  paramsString = '',
29
29
  placement = '',
30
30
  setError,
@@ -50,7 +50,7 @@ export const XnsCaptureSecondaryLink: React.FC<XnsCaptureSecondaryLinkProps> = (
50
50
  if (valid) {
51
51
  await userEvents?.userClick({ elementName: event, elementType: 'xns-cta' })
52
52
  navigate?.(`${to}?username=${xnsName}${paramsString}`)
53
- await onBuyName?.(xnsName)
53
+ await onCaptureName?.(xnsName)
54
54
  } else {
55
55
  setError?.(new Error(errors.join(', ')))
56
56
  }
@@ -14,6 +14,6 @@ const Default = Template.bind({})
14
14
  Default.args = {}
15
15
 
16
16
  const WithOnBuyName = Template.bind({})
17
- WithOnBuyName.args = { navigate: (to: To) => alert(`navigated to: ${to}`), onBuyName: (name: string) => Promise.resolve(alert(`Buy Name: ${name}`)) }
17
+ WithOnBuyName.args = { navigate: (to: To) => alert(`navigated to: ${to}`), onCaptureName: (name: string) => Promise.resolve(alert(`Buy Name: ${name}`)) }
18
18
 
19
19
  export { Default, WithOnBuyName }
@@ -23,21 +23,22 @@ export const XnsNameCapture: React.FC<XnsNameCaptureProps> = ({
23
23
  mixpanel,
24
24
  mobileButtonText = 'Buy',
25
25
  navigate,
26
- onBuyName: onBuyNameProp,
26
+ onCaptureName: onCaptureNameProp,
27
27
  paramsString = '',
28
28
  placement = '',
29
+ routingError,
29
30
  showSecondary = false,
30
31
  to = '/xns/estimation',
31
32
  userEvents,
32
33
  ...props
33
34
  }) => {
34
35
  const [xnsName, setXnsName] = useState<string>(() => defaultXnsName ?? '')
35
- const [error, setError] = useState<Error | undefined>()
36
+ const [error, setError] = useState<Error | undefined>(routingError)
36
37
 
37
38
  const theme = useTheme()
38
39
  const isMobile = useMediaQuery(theme.breakpoints.down('md'))
39
40
 
40
- const buyDisabled = !xnsName || xnsName.length < MIN_DOMAIN_LENGTH
41
+ const captureDisabled = !xnsName || xnsName.length < MIN_DOMAIN_LENGTH
41
42
 
42
43
  const handleChange: StandardTextFieldProps['onChange'] = (event) => {
43
44
  const NsName = XnsNameHelper.mask(event.target.value)
@@ -45,9 +46,8 @@ export const XnsNameCapture: React.FC<XnsNameCaptureProps> = ({
45
46
  setError(undefined)
46
47
  }
47
48
 
48
- const onBuyName = useCallback(async () => {
49
- if (!xnsName) return
50
-
49
+ const onCaptureName = useCallback(async () => {
50
+ if (captureDisabled) return
51
51
  mixpanel?.track(event, {
52
52
  Funnel: funnel,
53
53
  Placement: placement,
@@ -57,7 +57,7 @@ export const XnsNameCapture: React.FC<XnsNameCaptureProps> = ({
57
57
  const [valid, errors] = await helper.validate()
58
58
  if (valid) {
59
59
  await userEvents?.userClick({ elementName: event, elementType: 'xns-cta' })
60
- await onBuyNameProp?.(xnsName)
60
+ await onCaptureNameProp?.(xnsName)
61
61
  navigate?.(`${to}?username=${xnsName}${paramsString}`)
62
62
  } else {
63
63
  setError(new Error(errors.join(', ')))
@@ -65,10 +65,10 @@ export const XnsNameCapture: React.FC<XnsNameCaptureProps> = ({
65
65
  }, [event, funnel, mixpanel, paramsString, placement, to, userEvents, xnsName])
66
66
 
67
67
  const onKeyDown: KeyboardEventHandler<HTMLDivElement> = useCallback(async (event) => {
68
- if (event.key === 'Enter' && !buyDisabled) {
69
- await onBuyName?.()
68
+ if (event.key === 'Enter' && !captureDisabled) {
69
+ await onCaptureName?.()
70
70
  }
71
- }, [buyDisabled, onBuyName])
71
+ }, [captureDisabled, onCaptureName])
72
72
 
73
73
  return (
74
74
  <FlexCol gap={showSecondary ? 1.5 : 0} alignItems="center" {...props}>
@@ -84,11 +84,11 @@ export const XnsNameCapture: React.FC<XnsNameCaptureProps> = ({
84
84
  onBlur={handleChange}
85
85
  />
86
86
  <ButtonEx
87
- disabled={buyDisabled}
87
+ disabled={captureDisabled}
88
88
  variant="contained"
89
89
  color="success"
90
90
  endIcon={<KeyboardArrowRightRounded />}
91
- onClick={onBuyName}
91
+ onClick={onCaptureName}
92
92
  >
93
93
  {isMobile ? mobileButtonText : buttonText}
94
94
  </ButtonEx>
@@ -1,4 +1,6 @@
1
- import type { Meta, StoryFn } from '@storybook/react'
1
+ import type {
2
+ Decorator, Meta, StoryFn,
3
+ } from '@storybook/react'
2
4
  import React from 'react'
3
5
  import type { To } from 'react-router-dom'
4
6
  import { BrowserRouter } from 'react-router-dom'
@@ -7,15 +9,28 @@ import { XnsNameCaptureWithContext } from './XnsNameCaptureWithContext.tsx'
7
9
 
8
10
  export default { title: 'modules/xns/XnsNameCaptureWithContext' } as Meta
9
11
 
10
- const Template: StoryFn<typeof XnsNameCaptureWithContext> = (args) => {
11
- // Get the current URL
12
+ const testableParams = ['signature', 'username'] as const
13
+ type RouteDecorator = (params: [typeof testableParams[number], string][]) => Decorator
14
+
15
+ // eslint-disable-next-line react/display-name
16
+ const RouteDecorator: RouteDecorator = params => (Story, args) => {
17
+ // Get the URL object
12
18
  const url = new URL(window.location.href)
13
19
 
14
- // Update or add the URL parameter
15
- url.searchParams.set('signature', '0x1234567890abcdef')
20
+ // Remove all stale testable params from the URL
21
+ for (const param of testableParams) url.searchParams.delete(param)
22
+ window.history.replaceState({}, '', url)
23
+
24
+ // Add the new testable params to the URL
25
+ for (const [param, value] of params) url.searchParams.set(param, value)
16
26
 
17
- // Update the URL without reloading the page
27
+ // Replace the URL without reloading
18
28
  window.history.replaceState({}, '', url)
29
+
30
+ return <Story {...args} />
31
+ }
32
+
33
+ const Template: StoryFn<typeof XnsNameCaptureWithContext> = (args) => {
19
34
  return (
20
35
  <BrowserRouter>
21
36
  <XnsNameCaptureWithContext {...args}></XnsNameCaptureWithContext>
@@ -24,9 +39,20 @@ const Template: StoryFn<typeof XnsNameCaptureWithContext> = (args) => {
24
39
  }
25
40
 
26
41
  const Default = Template.bind({})
42
+ Default.decorators = [RouteDecorator([['signature', '0x1234567890abcdef']])]
27
43
  Default.args = {}
28
44
 
29
- const WithOnBuyName = Template.bind({})
30
- WithOnBuyName.args = { navigate: (to: To) => alert(`navigated to: ${to}`), onBuyName: (name: string) => Promise.resolve(alert(`Buy Name: ${name}`)) }
45
+ const WithOnCaptureName = Template.bind({})
46
+ WithOnCaptureName.decorators = [RouteDecorator([['signature', '0x1234567890abcdef']])]
47
+ WithOnCaptureName.args = { navigate: (to: To) => alert(`navigated to: ${to}`), onCaptureName: (name: string) => Promise.resolve(alert(`Buy Name: ${name}`)) }
31
48
 
32
- export { Default, WithOnBuyName }
49
+ const WithBadXnsNameInRoute = Template.bind({})
50
+ WithBadXnsNameInRoute.decorators = [RouteDecorator([['signature', '0x1234567890abcdef'], ['username', 'badname.xyo.xyo']])]
51
+ WithBadXnsNameInRoute.args = {
52
+ navigate: (to: To) => alert(`navigated to: ${to}`),
53
+ onCaptureName: (name: string) => Promise.resolve(alert(`Buy Name: ${name}`)),
54
+ }
55
+
56
+ export {
57
+ Default, WithBadXnsNameInRoute, WithOnCaptureName,
58
+ }
@@ -1,2 +1,2 @@
1
+ export * from './routing/index.ts'
1
2
  export * from './useXnsNameCaptureProviders.ts'
2
- export * from './useXnsNameCaptureRouting.ts'
@@ -0,0 +1,2 @@
1
+ export * from './useXnsNameCaptureRouting.ts'
2
+ export * from './useXnsNameFromLocation.ts'
@@ -1,7 +1,8 @@
1
1
  import { useMemo } from 'react'
2
2
  import { useNavigate, useSearchParams } from 'react-router-dom'
3
3
 
4
- import type { XnsNameCaptureProps } from '../Props.ts'
4
+ import type { XnsNameCaptureProps } from '../../Props.ts'
5
+ import { useXnsNameFromLocation } from './useXnsNameFromLocation.ts'
5
6
 
6
7
  export const useXnsNameCaptureRouting = (props: XnsNameCaptureProps) => {
7
8
  const [params] = useSearchParams()
@@ -10,8 +11,12 @@ export const useXnsNameCaptureRouting = (props: XnsNameCaptureProps) => {
10
11
 
11
12
  const navigate = useNavigate()
12
13
 
14
+ const [name, error] = useXnsNameFromLocation()
15
+
13
16
  return useMemo(() => ({
14
17
  ...props,
18
+ defaultXnsName: name,
19
+ routingError: error,
15
20
  navigate: props.navigate ?? ((to: string) => navigate(to)),
16
21
  paramsString: signatureParamString,
17
22
  }), [props, signatureParamString])
@@ -0,0 +1,26 @@
1
+ import { useLocation } from 'react-router-dom'
2
+
3
+ /**
4
+ * Assumes the user was redirected with a link that contains a username query parameter.
5
+ * @returns The xNS name from the URI username query parameter.
6
+ */
7
+ export const useXnsNameFromLocation = (): [name: string | undefined, error: Error | undefined] => {
8
+ const location = useLocation()
9
+ const search = new URLSearchParams(location.search)
10
+ const rawName = (search.get('xnsname') ?? search.get('name') ?? search.get('username') ?? '').toLowerCase()
11
+ switch (rawName?.split('.').length) {
12
+ case 1: {
13
+ return [rawName, undefined]
14
+ }
15
+ case 2: {
16
+ const rawNameParts = rawName.split('.')
17
+ if (rawNameParts[1] !== 'xyo') {
18
+ return [, new Error('Invalid xNS name [Bad root]')]
19
+ }
20
+ return [rawNameParts[0], undefined]
21
+ }
22
+ default: {
23
+ return [, new Error('Invalid xNS name [Too many parts]')]
24
+ }
25
+ }
26
+ }