@xyo-network/react-xns 3.0.10

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 (50) hide show
  1. package/LICENSE +165 -0
  2. package/README.md +13 -0
  3. package/dist/browser/components/EstimateName/EstimateNameTextField.d.ts +7 -0
  4. package/dist/browser/components/EstimateName/EstimateNameTextField.d.ts.map +1 -0
  5. package/dist/browser/components/EstimateName/index.d.ts +2 -0
  6. package/dist/browser/components/EstimateName/index.d.ts.map +1 -0
  7. package/dist/browser/components/XnsNameCapture/Errors.d.ts +8 -0
  8. package/dist/browser/components/XnsNameCapture/Errors.d.ts.map +1 -0
  9. package/dist/browser/components/XnsNameCapture/Props.d.ts +34 -0
  10. package/dist/browser/components/XnsNameCapture/Props.d.ts.map +1 -0
  11. package/dist/browser/components/XnsNameCapture/SecondaryLink.d.ts +14 -0
  12. package/dist/browser/components/XnsNameCapture/SecondaryLink.d.ts.map +1 -0
  13. package/dist/browser/components/XnsNameCapture/XnsNameCapture.d.ts +4 -0
  14. package/dist/browser/components/XnsNameCapture/XnsNameCapture.d.ts.map +1 -0
  15. package/dist/browser/components/XnsNameCapture/XnsNameCaptureWithContext.d.ts +4 -0
  16. package/dist/browser/components/XnsNameCapture/XnsNameCaptureWithContext.d.ts.map +1 -0
  17. package/dist/browser/components/XnsNameCapture/hooks/index.d.ts +3 -0
  18. package/dist/browser/components/XnsNameCapture/hooks/index.d.ts.map +1 -0
  19. package/dist/browser/components/XnsNameCapture/hooks/useXnsNameCaptureProviders.d.ts +399 -0
  20. package/dist/browser/components/XnsNameCapture/hooks/useXnsNameCaptureProviders.d.ts.map +1 -0
  21. package/dist/browser/components/XnsNameCapture/hooks/useXnsNameCaptureRouting.d.ts +399 -0
  22. package/dist/browser/components/XnsNameCapture/hooks/useXnsNameCaptureRouting.d.ts.map +1 -0
  23. package/dist/browser/components/XnsNameCapture/index.d.ts +7 -0
  24. package/dist/browser/components/XnsNameCapture/index.d.ts.map +1 -0
  25. package/dist/browser/components/index.d.ts +3 -0
  26. package/dist/browser/components/index.d.ts.map +1 -0
  27. package/dist/browser/index.d.ts +2 -0
  28. package/dist/browser/index.d.ts.map +1 -0
  29. package/dist/browser/index.mjs +276 -0
  30. package/dist/browser/index.mjs.map +1 -0
  31. package/package.json +85 -0
  32. package/src/components/EstimateName/EstimateNameTextField.stories.tsx +15 -0
  33. package/src/components/EstimateName/EstimateNameTextField.tsx +50 -0
  34. package/src/components/EstimateName/index.ts +1 -0
  35. package/src/components/XnsNameCapture/Errors.tsx +55 -0
  36. package/src/components/XnsNameCapture/Props.ts +50 -0
  37. package/src/components/XnsNameCapture/SecondaryLink.stories.tsx +18 -0
  38. package/src/components/XnsNameCapture/SecondaryLink.tsx +66 -0
  39. package/src/components/XnsNameCapture/XnsNameCapture.stories.tsx +19 -0
  40. package/src/components/XnsNameCapture/XnsNameCapture.tsx +114 -0
  41. package/src/components/XnsNameCapture/XnsNameCaptureWithContext.stories.tsx +32 -0
  42. package/src/components/XnsNameCapture/XnsNameCaptureWithContext.tsx +20 -0
  43. package/src/components/XnsNameCapture/hooks/index.ts +2 -0
  44. package/src/components/XnsNameCapture/hooks/useXnsNameCaptureProviders.ts +13 -0
  45. package/src/components/XnsNameCapture/hooks/useXnsNameCaptureRouting.ts +18 -0
  46. package/src/components/XnsNameCapture/index.ts +6 -0
  47. package/src/components/index.ts +2 -0
  48. package/src/index.ts +1 -0
  49. package/typedoc.json +5 -0
  50. package/xy.config.ts +10 -0
@@ -0,0 +1,19 @@
1
+ import type { Meta, StoryFn } from '@storybook/react'
2
+ import React from 'react'
3
+ import type { To } from 'react-router-dom'
4
+
5
+ import { XnsNameCapture } from './XnsNameCapture.tsx'
6
+
7
+ export default { title: 'modules/xns/XnsNameCapture' } as Meta
8
+
9
+ const Template: StoryFn<typeof XnsNameCapture> = (args) => {
10
+ return <XnsNameCapture {...args}></XnsNameCapture>
11
+ }
12
+
13
+ const Default = Template.bind({})
14
+ Default.args = {}
15
+
16
+ const WithOnBuyName = Template.bind({})
17
+ WithOnBuyName.args = { navigate: (to: To) => alert(`navigated to: ${to}`), onBuyName: (name: string) => Promise.resolve(alert(`Buy Name: ${name}`)) }
18
+
19
+ export { Default, WithOnBuyName }
@@ -0,0 +1,114 @@
1
+ import { KeyboardArrowRightRounded } from '@mui/icons-material'
2
+ import type { StandardTextFieldProps } from '@mui/material'
3
+ import { useMediaQuery, useTheme } from '@mui/material'
4
+ import { ButtonEx } from '@xylabs/react-button'
5
+ import { FlexCol, FlexRow } from '@xylabs/react-flexbox'
6
+ import { MIN_DOMAIN_LENGTH, XnsNameHelper } from '@xyo-network/xns-record-payloadset-plugins'
7
+ import type { KeyboardEventHandler } from 'react'
8
+ import React, { useCallback, useState } from 'react'
9
+
10
+ import { XnsEstimateNameTextField } from '../EstimateName/index.ts'
11
+ import { XnsNameCaptureErrors } from './Errors.tsx'
12
+ import type { XnsNameCaptureProps } from './Props.ts'
13
+ import { XnsCaptureSecondaryLink } from './SecondaryLink.js'
14
+
15
+ export const XnsNameCapture: React.FC<XnsNameCaptureProps> = ({
16
+ autoFocus = false,
17
+ buttonText = 'Buy My Name',
18
+ children,
19
+ defaultXnsName,
20
+ errorUi = 'alert',
21
+ event = 'Click to Checkout',
22
+ funnel = 'xns',
23
+ mixpanel,
24
+ mobileButtonText = 'Buy',
25
+ navigate,
26
+ onBuyName: onBuyNameProp,
27
+ paramsString = '',
28
+ placement = '',
29
+ showSecondary = false,
30
+ to = '/xns/estimation',
31
+ userEvents,
32
+ ...props
33
+ }) => {
34
+ const [xnsName, setXnsName] = useState<string>(() => defaultXnsName ?? '')
35
+ const [error, setError] = useState<Error | undefined>()
36
+
37
+ const theme = useTheme()
38
+ const isMobile = useMediaQuery(theme.breakpoints.down('md'))
39
+
40
+ const buyDisabled = !xnsName || xnsName.length < MIN_DOMAIN_LENGTH
41
+
42
+ const handleChange: StandardTextFieldProps['onChange'] = (event) => {
43
+ const NsName = XnsNameHelper.mask(event.target.value)
44
+ setXnsName(NsName)
45
+ setError(undefined)
46
+ }
47
+
48
+ const onBuyName = useCallback(async () => {
49
+ if (!xnsName) return
50
+
51
+ mixpanel?.track(event, {
52
+ Funnel: funnel,
53
+ Placement: placement,
54
+ })
55
+ const formattedXnsName = `${xnsName}.xyo`
56
+ const helper = XnsNameHelper.fromString(formattedXnsName)
57
+ const [valid, errors] = await helper.validate()
58
+ if (valid) {
59
+ await userEvents?.userClick({ elementName: event, elementType: 'xns-cta' })
60
+ await onBuyNameProp?.(xnsName)
61
+ navigate?.(`${to}?username=${xnsName}${paramsString}`)
62
+ } else {
63
+ setError(new Error(errors.join(', ')))
64
+ }
65
+ }, [event, funnel, mixpanel, paramsString, placement, to, userEvents, xnsName])
66
+
67
+ const onKeyDown: KeyboardEventHandler<HTMLDivElement> = useCallback(async (event) => {
68
+ if (event.key === 'Enter' && !buyDisabled) {
69
+ await onBuyName?.()
70
+ }
71
+ }, [buyDisabled, onBuyName])
72
+
73
+ return (
74
+ <FlexCol gap={showSecondary ? 1.5 : 0} alignItems="center" {...props}>
75
+ <FlexRow gap={1}>
76
+ <XnsEstimateNameTextField
77
+ autoFocus={autoFocus}
78
+ label="xNS Name"
79
+ variant="outlined"
80
+ size="small"
81
+ value={xnsName ?? ''}
82
+ onKeyDown={onKeyDown}
83
+ onChange={handleChange}
84
+ onBlur={handleChange}
85
+ />
86
+ <ButtonEx
87
+ disabled={buyDisabled}
88
+ variant="contained"
89
+ color="success"
90
+ endIcon={<KeyboardArrowRightRounded />}
91
+ onClick={onBuyName}
92
+ >
93
+ {isMobile ? mobileButtonText : buttonText}
94
+ </ButtonEx>
95
+ </FlexRow>
96
+ {(showSecondary === true)
97
+ ? (
98
+ <XnsCaptureSecondaryLink
99
+ xnsName={xnsName}
100
+ placement={placement}
101
+ funnel={funnel}
102
+ setError={setError}
103
+ />
104
+ )
105
+ : null}
106
+ {
107
+ // eslint-disable-next-line unicorn/prefer-logical-operator-over-ternary
108
+ showSecondary ? showSecondary : null
109
+ }
110
+ {children}
111
+ <XnsNameCaptureErrors error={error} errorUi={errorUi} resetError={() => setError(undefined)} />
112
+ </FlexCol>
113
+ )
114
+ }
@@ -0,0 +1,32 @@
1
+ import type { Meta, StoryFn } from '@storybook/react'
2
+ import React from 'react'
3
+ import type { To } from 'react-router-dom'
4
+ import { BrowserRouter } from 'react-router-dom'
5
+
6
+ import { XnsNameCaptureWithContext } from './XnsNameCaptureWithContext.tsx'
7
+
8
+ export default { title: 'modules/xns/XnsNameCaptureWithContext' } as Meta
9
+
10
+ const Template: StoryFn<typeof XnsNameCaptureWithContext> = (args) => {
11
+ // Get the current URL
12
+ const url = new URL(window.location.href)
13
+
14
+ // Update or add the URL parameter
15
+ url.searchParams.set('signature', '0x1234567890abcdef')
16
+
17
+ // Update the URL without reloading the page
18
+ window.history.replaceState({}, '', url)
19
+ return (
20
+ <BrowserRouter>
21
+ <XnsNameCaptureWithContext {...args}></XnsNameCaptureWithContext>
22
+ </BrowserRouter>
23
+ )
24
+ }
25
+
26
+ const Default = Template.bind({})
27
+ Default.args = {}
28
+
29
+ const WithOnBuyName = Template.bind({})
30
+ WithOnBuyName.args = { navigate: (to: To) => alert(`navigated to: ${to}`), onBuyName: (name: string) => Promise.resolve(alert(`Buy Name: ${name}`)) }
31
+
32
+ export { Default, WithOnBuyName }
@@ -0,0 +1,20 @@
1
+ import React, { useMemo } from 'react'
2
+
3
+ import { useXnsNameCaptureProviders, useXnsNameCaptureRouting } from './hooks/index.ts'
4
+ import type { XnsNameCaptureProps } from './Props.ts'
5
+ import { XnsNameCapture } from './XnsNameCapture.tsx'
6
+
7
+ export const XnsNameCaptureWithContext: React.FC<XnsNameCaptureProps> = (props) => {
8
+ const routingProps = useXnsNameCaptureRouting(props)
9
+ const providersProps = useXnsNameCaptureProviders(routingProps)
10
+
11
+ const updatedProps = useMemo<XnsNameCaptureProps>(() => ({
12
+ ...props,
13
+ ...routingProps,
14
+ ...providersProps,
15
+ }), [providersProps])
16
+
17
+ return (
18
+ <XnsNameCapture {...updatedProps} />
19
+ )
20
+ }
@@ -0,0 +1,2 @@
1
+ export * from './useXnsNameCaptureProviders.ts'
2
+ export * from './useXnsNameCaptureRouting.ts'
@@ -0,0 +1,13 @@
1
+ import { useMixpanel } from '@xylabs/react-mixpanel'
2
+ import { useMemo } from 'react'
3
+
4
+ import type { XnsNameCaptureProps } from '../Props.ts'
5
+
6
+ export const useXnsNameCaptureProviders = (props: XnsNameCaptureProps) => {
7
+ const mixpanel = useMixpanel()
8
+
9
+ return useMemo(() => ({
10
+ ...props,
11
+ mixpanel: props.mixpanel ?? mixpanel,
12
+ }), [props, mixpanel])
13
+ }
@@ -0,0 +1,18 @@
1
+ import { useMemo } from 'react'
2
+ import { useNavigate, useSearchParams } from 'react-router-dom'
3
+
4
+ import type { XnsNameCaptureProps } from '../Props.ts'
5
+
6
+ export const useXnsNameCaptureRouting = (props: XnsNameCaptureProps) => {
7
+ const [params] = useSearchParams()
8
+ const signatureParam = params.get('signature')
9
+ const signatureParamString = signatureParam ? `&signature=${encodeURIComponent(signatureParam)}` : ''
10
+
11
+ const navigate = useNavigate()
12
+
13
+ return useMemo(() => ({
14
+ ...props,
15
+ navigate: props.navigate ?? ((to: string) => navigate(to)),
16
+ paramsString: signatureParamString,
17
+ }), [props, signatureParamString])
18
+ }
@@ -0,0 +1,6 @@
1
+ export * from './Errors.tsx'
2
+ export * from './hooks/index.ts'
3
+ export * from './Props.ts'
4
+ export * from './SecondaryLink.tsx'
5
+ export * from './XnsNameCapture.tsx'
6
+ export * from './XnsNameCaptureWithContext.tsx'
@@ -0,0 +1,2 @@
1
+ export * from './EstimateName/index.ts'
2
+ export * from './XnsNameCapture/index.ts'
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './components/index.ts'
package/typedoc.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "$schema": "https://typedoc.org/schema.json",
3
+ "entryPoints": ["src/index.ts"],
4
+ "tsconfig": "./tsconfig.typedoc.json"
5
+ }
package/xy.config.ts ADDED
@@ -0,0 +1,10 @@
1
+ import type { XyTsupConfig } from '@xylabs/ts-scripts-yarn3'
2
+ const config: XyTsupConfig = {
3
+ compile: {
4
+ browser: { src: true },
5
+ node: {},
6
+ neutral: {},
7
+ },
8
+ }
9
+
10
+ export default config