@xyo-network/react-xns 3.0.17 → 3.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/components/EstimateName/EstimateNameTextField.d.ts.map +1 -1
- package/dist/browser/components/XnsNameCapture/XnsNameCapture.d.ts.map +1 -1
- package/dist/browser/components/XnsNameCapture/lib/index.d.ts +2 -0
- package/dist/browser/components/XnsNameCapture/lib/index.d.ts.map +1 -0
- package/dist/browser/components/XnsNameCapture/lib/navigateWithUsername.d.ts +3 -0
- package/dist/browser/components/XnsNameCapture/lib/navigateWithUsername.d.ts.map +1 -0
- package/dist/browser/index.mjs +46 -14
- package/dist/browser/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/EstimateName/EstimateNameTextField.stories.tsx +10 -2
- package/src/components/EstimateName/EstimateNameTextField.tsx +21 -3
- package/src/components/XnsNameCapture/XnsNameCapture.tsx +3 -1
- package/src/components/XnsNameCapture/XnsNameCaptureWithContext.stories.tsx +5 -1
- package/src/components/XnsNameCapture/lib/index.ts +1 -0
- package/src/components/XnsNameCapture/lib/navigateWithUsername.ts +21 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EstimateNameTextField.d.ts","sourceRoot":"","sources":["../../../../src/components/EstimateName/EstimateNameTextField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA0B,cAAc,EAAE,MAAM,eAAe,CAAA;AAK3E,OAAO,
|
|
1
|
+
{"version":3,"file":"EstimateNameTextField.d.ts","sourceRoot":"","sources":["../../../../src/components/EstimateName/EstimateNameTextField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA0B,cAAc,EAAE,MAAM,eAAe,CAAA;AAK3E,OAAO,KAEN,MAAM,OAAO,CAAA;AAEd,MAAM,WAAW,6BAA6B;IAC5C,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,eAAO,MAAM,wBAAwB,EAAE,KAAK,CAAC,EAAE,CAAC,6BAA6B,GAAG,cAAc,CAsD7F,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"XnsNameCapture.d.ts","sourceRoot":"","sources":["../../../../src/components/XnsNameCapture/XnsNameCapture.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAgC,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"XnsNameCapture.d.ts","sourceRoot":"","sources":["../../../../src/components/XnsNameCapture/XnsNameCapture.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAgC,MAAM,OAAO,CAAA;AAKpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAGrD,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAsGxD,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/XnsNameCapture/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigateWithUsername.d.ts","sourceRoot":"","sources":["../../../../../src/components/XnsNameCapture/lib/navigateWithUsername.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AAE1C,eAAO,MAAM,oBAAoB,YAAa,MAAM,gBAAgB,MAAM,aAAa,CAAC,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC,OAAO,EAAE,SAkBrH,CAAA"}
|
package/dist/browser/index.mjs
CHANGED
|
@@ -4,15 +4,28 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
|
|
|
4
4
|
// src/components/EstimateName/EstimateNameTextField.tsx
|
|
5
5
|
import { alpha, TextField, useTheme } from "@mui/material";
|
|
6
6
|
import { MIN_DOMAIN_LENGTH, XnsNameHelper } from "@xyo-network/xns-record-payloadset-plugins";
|
|
7
|
-
import React, { useState } from "react";
|
|
8
|
-
var XnsEstimateNameTextField = /* @__PURE__ */ __name(({ maskOutput = true, onChange: onChangeProp, onBlur: onBlurProp, ...props }) => {
|
|
7
|
+
import React, { useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
8
|
+
var XnsEstimateNameTextField = /* @__PURE__ */ __name(({ maskOutput = true, onChange: onChangeProp, onBlur: onBlurProp, value, ...props }) => {
|
|
9
9
|
const theme = useTheme();
|
|
10
10
|
const [validLength, setValidLength] = useState(false);
|
|
11
|
-
const inputRef =
|
|
11
|
+
const inputRef = useRef(null);
|
|
12
|
+
useMemo(() => {
|
|
13
|
+
const validValueLength = !!(value && typeof value === "string" && value.length >= MIN_DOMAIN_LENGTH);
|
|
14
|
+
setValidLength(validValueLength);
|
|
15
|
+
}, [
|
|
16
|
+
value
|
|
17
|
+
]);
|
|
18
|
+
useLayoutEffect(() => {
|
|
19
|
+
if (inputRef.current && typeof value === "string") {
|
|
20
|
+
inputRef.current.value = value;
|
|
21
|
+
}
|
|
22
|
+
}, [
|
|
23
|
+
value
|
|
24
|
+
]);
|
|
12
25
|
const handleChange = /* @__PURE__ */ __name((event) => {
|
|
13
26
|
if (maskOutput) {
|
|
14
|
-
const
|
|
15
|
-
event.target.value = XnsNameHelper.mask(
|
|
27
|
+
const value2 = event.target.value;
|
|
28
|
+
event.target.value = XnsNameHelper.mask(value2);
|
|
16
29
|
}
|
|
17
30
|
onChangeProp?.(event);
|
|
18
31
|
if (inputRef.current) {
|
|
@@ -21,8 +34,8 @@ var XnsEstimateNameTextField = /* @__PURE__ */ __name(({ maskOutput = true, onCh
|
|
|
21
34
|
}, "handleChange");
|
|
22
35
|
const handleBlur = /* @__PURE__ */ __name((event) => {
|
|
23
36
|
if (maskOutput) {
|
|
24
|
-
const
|
|
25
|
-
event.target.value = XnsNameHelper.mask(
|
|
37
|
+
const value2 = event.target.value;
|
|
38
|
+
event.target.value = XnsNameHelper.mask(value2, {
|
|
26
39
|
maskStartEndHyphens: true
|
|
27
40
|
});
|
|
28
41
|
}
|
|
@@ -78,7 +91,7 @@ var XnsNameCaptureErrors = /* @__PURE__ */ __name(({ error, errorUi, resetError
|
|
|
78
91
|
}, "XnsNameCaptureErrors");
|
|
79
92
|
|
|
80
93
|
// src/components/XnsNameCapture/hooks/routing/useXnsNameCaptureRouting.ts
|
|
81
|
-
import { useMemo } from "react";
|
|
94
|
+
import { useMemo as useMemo2 } from "react";
|
|
82
95
|
import { useNavigate, useSearchParams } from "react-router-dom";
|
|
83
96
|
|
|
84
97
|
// src/components/XnsNameCapture/hooks/routing/useXnsNameFromLocation.ts
|
|
@@ -121,7 +134,7 @@ var useXnsNameCaptureRouting = /* @__PURE__ */ __name((props) => {
|
|
|
121
134
|
const [params] = useSearchParams();
|
|
122
135
|
const navigate = useNavigate();
|
|
123
136
|
const [name, error] = useXnsNameFromLocation();
|
|
124
|
-
return
|
|
137
|
+
return useMemo2(() => ({
|
|
125
138
|
...props,
|
|
126
139
|
defaultXnsName: name,
|
|
127
140
|
routingError: error,
|
|
@@ -137,10 +150,10 @@ var useXnsNameCaptureRouting = /* @__PURE__ */ __name((props) => {
|
|
|
137
150
|
|
|
138
151
|
// src/components/XnsNameCapture/hooks/useXnsNameCaptureProviders.ts
|
|
139
152
|
import { useMixpanel } from "@xylabs/react-mixpanel";
|
|
140
|
-
import { useMemo as
|
|
153
|
+
import { useMemo as useMemo3 } from "react";
|
|
141
154
|
var useXnsNameCaptureProviders = /* @__PURE__ */ __name((props) => {
|
|
142
155
|
const mixpanel = useMixpanel();
|
|
143
|
-
return
|
|
156
|
+
return useMemo3(() => ({
|
|
144
157
|
...props,
|
|
145
158
|
mixpanel: props.mixpanel ?? mixpanel
|
|
146
159
|
}), [
|
|
@@ -200,6 +213,25 @@ import { ButtonEx } from "@xylabs/react-button";
|
|
|
200
213
|
import { FlexCol, FlexRow as FlexRow2 } from "@xylabs/react-flexbox";
|
|
201
214
|
import { MIN_DOMAIN_LENGTH as MIN_DOMAIN_LENGTH2, XnsNameHelper as XnsNameHelper3 } from "@xyo-network/xns-record-payloadset-plugins";
|
|
202
215
|
import React4, { useCallback, useState as useState2 } from "react";
|
|
216
|
+
|
|
217
|
+
// src/components/XnsNameCapture/lib/navigateWithUsername.ts
|
|
218
|
+
var navigateWithUsername = /* @__PURE__ */ __name((xnsName, paramsString, navigate, to) => {
|
|
219
|
+
const params = new URLSearchParams(paramsString);
|
|
220
|
+
const usernameParam = params.get("username");
|
|
221
|
+
if (usernameParam) {
|
|
222
|
+
if (usernameParam === xnsName) {
|
|
223
|
+
navigate?.(`${to}?${paramsString}`);
|
|
224
|
+
}
|
|
225
|
+
if (usernameParam !== xnsName) {
|
|
226
|
+
params.set("username", xnsName);
|
|
227
|
+
navigate?.(`${to}?${params.toString()}`);
|
|
228
|
+
}
|
|
229
|
+
} else {
|
|
230
|
+
navigate?.(`${to}?username=${xnsName}&${paramsString}`);
|
|
231
|
+
}
|
|
232
|
+
}, "navigateWithUsername");
|
|
233
|
+
|
|
234
|
+
// src/components/XnsNameCapture/XnsNameCapture.tsx
|
|
203
235
|
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, onNameChange, paramsString = "", placement = "", routingError, showSecondary = false, to = "/xns/estimation", userEvents, ...props }) => {
|
|
204
236
|
const [xnsName, setXnsName] = useState2(() => defaultXnsName ?? "");
|
|
205
237
|
const [error, setError] = useState2(routingError);
|
|
@@ -227,7 +259,7 @@ var XnsNameCapture = /* @__PURE__ */ __name(({ autoFocus = false, buttonText = "
|
|
|
227
259
|
elementType: "xns-cta"
|
|
228
260
|
});
|
|
229
261
|
await onCaptureNameProp?.(xnsName);
|
|
230
|
-
|
|
262
|
+
navigateWithUsername(xnsName, paramsString, navigate, to);
|
|
231
263
|
} else {
|
|
232
264
|
setError(new Error(errors.join(", ")));
|
|
233
265
|
}
|
|
@@ -295,12 +327,12 @@ var XnsNameCapture = /* @__PURE__ */ __name(({ autoFocus = false, buttonText = "
|
|
|
295
327
|
|
|
296
328
|
// src/components/XnsNameCapture/XnsNameCaptureWithContext.tsx
|
|
297
329
|
import { useUserEvents } from "@xylabs/react-pixel";
|
|
298
|
-
import React5, { useMemo as
|
|
330
|
+
import React5, { useMemo as useMemo4 } from "react";
|
|
299
331
|
var XnsNameCaptureWithContext = /* @__PURE__ */ __name((props) => {
|
|
300
332
|
const routingProps = useXnsNameCaptureRouting(props);
|
|
301
333
|
const providersProps = useXnsNameCaptureProviders(routingProps);
|
|
302
334
|
const userEvents = useUserEvents(false);
|
|
303
|
-
const updatedProps =
|
|
335
|
+
const updatedProps = useMemo4(() => ({
|
|
304
336
|
...props,
|
|
305
337
|
...routingProps,
|
|
306
338
|
...providersProps,
|
|
@@ -1 +1 @@
|
|
|
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\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: props.paramsString ? `${props.paramsString}${params.toString()}` : params.toString(),\n }), [props, params, name, error])\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 onNameChange,\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 onNameChange?.(NsName)\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, onCaptureNameProp, navigate])\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 { useUserEvents } from '@xylabs/react-pixel'\nimport 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 const userEvents = useUserEvents(false)\n\n const updatedProps = useMemo<XnsNameCaptureProps>(() => ({\n ...props,\n ...routingProps,\n ...providersProps,\n userEvents: props.userEvents ?? userEvents,\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","navigate","useNavigate","name","error","useXnsNameFromLocation","useMemo","defaultXnsName","routingError","to","paramsString","toString","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","onNameChange","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","useUserEvents","React","useMemo","XnsNameCaptureWithContext","props","routingProps","useXnsNameCaptureRouting","providersProps","useXnsNameCaptureProviders","userEvents","useUserEvents","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/lib/navigateWithUsername.ts","../../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, {\n useLayoutEffect, useMemo, useRef, useState,\n} 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, value, ...props\n}) => {\n const theme = useTheme()\n const [validLength, setValidLength] = useState(false)\n\n const inputRef = useRef<HTMLInputElement>(null)\n\n // watch for external changes to the value and update the validLength state\n useMemo(() => {\n const validValueLength = !!(value && typeof value === 'string' && value.length >= MIN_DOMAIN_LENGTH)\n setValidLength(validValueLength)\n }, [value])\n\n // Update the input value when the value prop changes\n // NOTE: the intent of this component is to remain uncontrolled to avoid the need to manage the value state\n // Therefore, we use useLayoutEffect to update the input value directly.\n useLayoutEffect(() => {\n if (inputRef.current && typeof value === 'string') {\n inputRef.current.value = value\n }\n }, [value])\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 // override onBlur to do a final mask of the input and update the event value\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\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: props.paramsString ? `${props.paramsString}${params.toString()}` : params.toString(),\n }), [props, params, name, error])\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 { navigateWithUsername } from './lib/index.ts'\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 onNameChange,\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 onNameChange?.(NsName)\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\n navigateWithUsername(xnsName, paramsString, navigate, to)\n } else {\n setError(new Error(errors.join(', ')))\n }\n }, [event, funnel, mixpanel, paramsString, placement, to, userEvents, xnsName, onCaptureNameProp, navigate])\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 type { To } from 'react-router-dom'\n\nexport const navigateWithUsername = (xnsName: string, paramsString: string, navigate?: ((to: string) => void), to?: To) => {\n // avoid duplicating the username param\n const params = new URLSearchParams(paramsString)\n const usernameParam = params.get('username')\n if (usernameParam) {\n // if username param is the same as the xnsName, navigate\n if (usernameParam === xnsName) {\n navigate?.(`${to}?${paramsString}`)\n }\n if (usernameParam !== xnsName) {\n // if username param is different, replace it\n params.set('username', xnsName)\n navigate?.(`${to}?${params.toString()}`)\n }\n } else {\n // if no username param, include it\n navigate?.(`${to}?username=${xnsName}&${paramsString}`)\n }\n}\n","import { useUserEvents } from '@xylabs/react-pixel'\nimport 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 const userEvents = useUserEvents(false)\n\n const updatedProps = useMemo<XnsNameCaptureProps>(() => ({\n ...props,\n ...routingProps,\n ...providersProps,\n userEvents: props.userEvents ?? userEvents,\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","useLayoutEffect","useMemo","useRef","useState","XnsEstimateNameTextField","maskOutput","onChange","onChangeProp","onBlur","onBlurProp","value","props","theme","useTheme","validLength","setValidLength","useState","inputRef","useRef","useMemo","validValueLength","length","MIN_DOMAIN_LENGTH","useLayoutEffect","current","handleChange","event","target","XnsNameHelper","mask","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","navigate","useNavigate","name","error","useXnsNameFromLocation","useMemo","defaultXnsName","routingError","to","paramsString","toString","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","navigateWithUsername","xnsName","paramsString","navigate","to","params","URLSearchParams","usernameParam","get","set","toString","XnsNameCapture","autoFocus","buttonText","children","defaultXnsName","errorUi","event","funnel","mixpanel","mobileButtonText","navigate","onCaptureName","onCaptureNameProp","onNameChange","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","navigateWithUsername","Error","join","onKeyDown","key","React","FlexCol","gap","alignItems","FlexRow","XnsEstimateNameTextField","label","variant","size","onChange","onBlur","ButtonEx","disabled","color","endIcon","KeyboardArrowRightRounded","onClick","XnsCaptureSecondaryLink","XnsNameCaptureErrors","resetError","useUserEvents","React","useMemo","XnsNameCaptureWithContext","props","routingProps","useXnsNameCaptureRouting","providersProps","useXnsNameCaptureProviders","userEvents","useUserEvents","updatedProps","useMemo","React","XnsNameCapture"]}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryFn } from '@storybook/react'
|
|
2
|
-
import React from 'react'
|
|
2
|
+
import React, { useState } from 'react'
|
|
3
3
|
|
|
4
4
|
import { XnsEstimateNameTextField } from './EstimateNameTextField.tsx'
|
|
5
5
|
|
|
@@ -9,7 +9,15 @@ const Template: StoryFn<typeof XnsEstimateNameTextField> = (args) => {
|
|
|
9
9
|
return <XnsEstimateNameTextField {...args}></XnsEstimateNameTextField>
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
const TemplateWithExternalValue: StoryFn<typeof XnsEstimateNameTextField> = (args) => {
|
|
13
|
+
const [value] = useState('foobar')
|
|
14
|
+
return <XnsEstimateNameTextField value={value} {...args}></XnsEstimateNameTextField>
|
|
15
|
+
}
|
|
16
|
+
|
|
12
17
|
const Default = Template.bind({})
|
|
13
18
|
Default.args = {}
|
|
14
19
|
|
|
15
|
-
|
|
20
|
+
const WithExternalValue = TemplateWithExternalValue.bind({})
|
|
21
|
+
WithExternalValue.args = {}
|
|
22
|
+
|
|
23
|
+
export { Default, WithExternalValue }
|
|
@@ -3,19 +3,36 @@ import {
|
|
|
3
3
|
alpha, TextField, useTheme,
|
|
4
4
|
} from '@mui/material'
|
|
5
5
|
import { MIN_DOMAIN_LENGTH, XnsNameHelper } from '@xyo-network/xns-record-payloadset-plugins'
|
|
6
|
-
import React, {
|
|
6
|
+
import React, {
|
|
7
|
+
useLayoutEffect, useMemo, useRef, useState,
|
|
8
|
+
} from 'react'
|
|
7
9
|
|
|
8
10
|
export interface XnsEstimateNameTextFieldProps {
|
|
9
11
|
maskOutput?: boolean
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
export const XnsEstimateNameTextField: React.FC<XnsEstimateNameTextFieldProps & TextFieldProps> = ({
|
|
13
|
-
maskOutput = true, onChange: onChangeProp, onBlur: onBlurProp, ...props
|
|
15
|
+
maskOutput = true, onChange: onChangeProp, onBlur: onBlurProp, value, ...props
|
|
14
16
|
}) => {
|
|
15
17
|
const theme = useTheme()
|
|
16
18
|
const [validLength, setValidLength] = useState(false)
|
|
17
19
|
|
|
18
|
-
const inputRef =
|
|
20
|
+
const inputRef = useRef<HTMLInputElement>(null)
|
|
21
|
+
|
|
22
|
+
// watch for external changes to the value and update the validLength state
|
|
23
|
+
useMemo(() => {
|
|
24
|
+
const validValueLength = !!(value && typeof value === 'string' && value.length >= MIN_DOMAIN_LENGTH)
|
|
25
|
+
setValidLength(validValueLength)
|
|
26
|
+
}, [value])
|
|
27
|
+
|
|
28
|
+
// Update the input value when the value prop changes
|
|
29
|
+
// NOTE: the intent of this component is to remain uncontrolled to avoid the need to manage the value state
|
|
30
|
+
// Therefore, we use useLayoutEffect to update the input value directly.
|
|
31
|
+
useLayoutEffect(() => {
|
|
32
|
+
if (inputRef.current && typeof value === 'string') {
|
|
33
|
+
inputRef.current.value = value
|
|
34
|
+
}
|
|
35
|
+
}, [value])
|
|
19
36
|
|
|
20
37
|
// override onChange to mask the input and update the event value
|
|
21
38
|
const handleChange: StandardTextFieldProps['onChange'] = (event) => {
|
|
@@ -30,6 +47,7 @@ export const XnsEstimateNameTextField: React.FC<XnsEstimateNameTextFieldProps &
|
|
|
30
47
|
}
|
|
31
48
|
}
|
|
32
49
|
|
|
50
|
+
// override onBlur to do a final mask of the input and update the event value
|
|
33
51
|
const handleBlur: StandardTextFieldProps['onBlur'] = (event) => {
|
|
34
52
|
if (maskOutput) {
|
|
35
53
|
const value = event.target.value
|
|
@@ -9,6 +9,7 @@ import React, { useCallback, useState } from 'react'
|
|
|
9
9
|
|
|
10
10
|
import { XnsEstimateNameTextField } from '../EstimateName/index.ts'
|
|
11
11
|
import { XnsNameCaptureErrors } from './Errors.tsx'
|
|
12
|
+
import { navigateWithUsername } from './lib/index.ts'
|
|
12
13
|
import type { XnsNameCaptureProps } from './Props.ts'
|
|
13
14
|
import { XnsCaptureSecondaryLink } from './SecondaryLink.js'
|
|
14
15
|
|
|
@@ -60,7 +61,8 @@ export const XnsNameCapture: React.FC<XnsNameCaptureProps> = ({
|
|
|
60
61
|
if (valid) {
|
|
61
62
|
await userEvents?.userClick({ elementName: event, elementType: 'xns-cta' })
|
|
62
63
|
await onCaptureNameProp?.(xnsName)
|
|
63
|
-
|
|
64
|
+
|
|
65
|
+
navigateWithUsername(xnsName, paramsString, navigate, to)
|
|
64
66
|
} else {
|
|
65
67
|
setError(new Error(errors.join(', ')))
|
|
66
68
|
}
|
|
@@ -53,6 +53,10 @@ WithBadXnsNameInRoute.args = {
|
|
|
53
53
|
onCaptureName: (name: string) => Promise.resolve(alert(`Buy Name: ${name}`)),
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
const WithUserName = Template.bind({})
|
|
57
|
+
WithUserName.decorators = [RouteDecorator([['username', 'foobar']])]
|
|
58
|
+
WithUserName.args = { navigate: (to: To) => alert(`navigated to: ${to}`) }
|
|
59
|
+
|
|
56
60
|
export {
|
|
57
|
-
Default, WithBadXnsNameInRoute, WithOnCaptureName,
|
|
61
|
+
Default, WithBadXnsNameInRoute, WithOnCaptureName, WithUserName,
|
|
58
62
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './navigateWithUsername.ts'
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { To } from 'react-router-dom'
|
|
2
|
+
|
|
3
|
+
export const navigateWithUsername = (xnsName: string, paramsString: string, navigate?: ((to: string) => void), to?: To) => {
|
|
4
|
+
// avoid duplicating the username param
|
|
5
|
+
const params = new URLSearchParams(paramsString)
|
|
6
|
+
const usernameParam = params.get('username')
|
|
7
|
+
if (usernameParam) {
|
|
8
|
+
// if username param is the same as the xnsName, navigate
|
|
9
|
+
if (usernameParam === xnsName) {
|
|
10
|
+
navigate?.(`${to}?${paramsString}`)
|
|
11
|
+
}
|
|
12
|
+
if (usernameParam !== xnsName) {
|
|
13
|
+
// if username param is different, replace it
|
|
14
|
+
params.set('username', xnsName)
|
|
15
|
+
navigate?.(`${to}?${params.toString()}`)
|
|
16
|
+
}
|
|
17
|
+
} else {
|
|
18
|
+
// if no username param, include it
|
|
19
|
+
navigate?.(`${to}?username=${xnsName}&${paramsString}`)
|
|
20
|
+
}
|
|
21
|
+
}
|