@xyo-network/react-chain-network 1.20.15 → 1.20.16

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 (49) hide show
  1. package/README.md +9 -540
  2. package/dist/browser/context/network/context.d.ts +12 -12
  3. package/dist/browser/context/network/use.d.ts +4 -4
  4. package/dist/browser/hooks/provider/useViewerInPage.d.ts.map +1 -1
  5. package/dist/browser/index.mjs.map +1 -1
  6. package/package.json +158 -48
  7. package/src/components/broadcast/CloseDrawerIconButton.tsx +0 -23
  8. package/src/components/broadcast/Drawer.tsx +0 -88
  9. package/src/components/broadcast/details/Card.tsx +0 -71
  10. package/src/components/broadcast/details/SummaryStack.stories.tsx +0 -36
  11. package/src/components/broadcast/details/SummaryStack.tsx +0 -68
  12. package/src/components/broadcast/details/index.ts +0 -2
  13. package/src/components/broadcast/index.ts +0 -1
  14. package/src/components/broadcast/usePaginatedEventPairs.ts +0 -69
  15. package/src/components/index.ts +0 -3
  16. package/src/components/menu/Avatar.tsx +0 -42
  17. package/src/components/menu/Icon.tsx +0 -21
  18. package/src/components/menu/MenuItem.tsx +0 -38
  19. package/src/components/menu/index.ts +0 -3
  20. package/src/components/status/Alert.stories.tsx +0 -74
  21. package/src/components/status/Alert.tsx +0 -51
  22. package/src/components/status/Dialog.tsx +0 -51
  23. package/src/components/status/NetworkStatus.tsx +0 -21
  24. package/src/components/status/index.ts +0 -2
  25. package/src/context/ActiveGatewayProvider.tsx +0 -21
  26. package/src/context/index.ts +0 -2
  27. package/src/context/network/Provider.tsx +0 -85
  28. package/src/context/network/context.ts +0 -5
  29. package/src/context/network/index.ts +0 -5
  30. package/src/context/network/settings/defaultChainNetworkSettings.ts +0 -5
  31. package/src/context/network/settings/index.ts +0 -3
  32. package/src/context/network/settings/types.ts +0 -7
  33. package/src/context/network/settings/useChainNetworkSettings.ts +0 -27
  34. package/src/context/network/state.ts +0 -13
  35. package/src/context/network/use.ts +0 -5
  36. package/src/hooks/index.ts +0 -2
  37. package/src/hooks/provider/UseViewerInPageV2.stories.tsx +0 -126
  38. package/src/hooks/provider/index.ts +0 -2
  39. package/src/hooks/provider/useRpcBroadcastListener.ts +0 -70
  40. package/src/hooks/provider/useViewerInPage.ts +0 -49
  41. package/src/hooks/status/index.ts +0 -1
  42. package/src/hooks/status/usePollNetworkStatus.ts +0 -39
  43. package/src/index.ts +0 -5
  44. package/src/model/BroadcastRpc.ts +0 -29
  45. package/src/model/index.ts +0 -1
  46. package/src/story/NetworkGatewayDecorators.tsx +0 -44
  47. package/src/story/index.ts +0 -1
  48. package/src/types/global.d.ts +0 -9
  49. package/src/types/images.d.ts +0 -20
@@ -1,88 +0,0 @@
1
- import type { DrawerProps } from '@mui/material'
2
- import {
3
- Box, Button, Drawer, Pagination, Stack, Typography,
4
- } from '@mui/material'
5
- import React, { useState } from 'react'
6
-
7
- import { useRpcBroadcastListener } from '../../hooks/index.ts'
8
- import type { RpcRequestResponsePairsById } from '../../model/index.ts'
9
- import { CloseDrawerIconButton } from './CloseDrawerIconButton.tsx'
10
- import { BroadcastedRpcCallDetailsCard } from './details/index.ts'
11
- import { usePaginatedEventPairs } from './usePaginatedEventPairs.ts'
12
-
13
- export interface BroadcastRpcCallsDrawer extends DrawerProps {
14
- drawerTitle?: string
15
- events: RpcRequestResponsePairsById
16
- numberOfVisibleEvents?: number
17
- onClearEvents?: () => void
18
- }
19
-
20
- export const BroadcastedRpcCallsDrawer: React.FC<BroadcastRpcCallsDrawer> = ({
21
- anchor = 'right',
22
- onClearEvents,
23
- drawerTitle,
24
- events,
25
- onClose,
26
- numberOfVisibleEvents = 25,
27
- ...props
28
- }) => {
29
- const [scrollableDiv, setScrollableDiv] = useState<HTMLDivElement | null>(null)
30
- const {
31
- allEventEntries,
32
- visibleEvents,
33
- totalPages,
34
- effectiveCurrentPage,
35
- handleClearEvents,
36
- handlePageChange,
37
- } = usePaginatedEventPairs(
38
- events,
39
- numberOfVisibleEvents,
40
- onClearEvents,
41
- scrollableDiv,
42
- )
43
-
44
- return (
45
- <Drawer anchor={anchor} onClose={onClose} keepMounted={false} {...props}>
46
- <CloseDrawerIconButton anchor={anchor} onClose={onClose} />
47
- <Stack gap={2} sx={{ p: 3 }} flexShrink={0}>
48
- <Stack direction="row" justifyContent="space-between" alignItems="center" gap={4}>
49
- <Typography variant="h6">{drawerTitle ?? 'Broadcasted RPC Calls'}</Typography>
50
- <Button variant="outlined" size="small" onClick={handleClearEvents}>Clear All</Button>
51
- </Stack>
52
- {allEventEntries.length > 0 && (
53
- <Pagination
54
- count={totalPages}
55
- page={effectiveCurrentPage}
56
- onChange={handlePageChange}
57
- color="primary"
58
- />
59
- )}
60
-
61
- </Stack>
62
- <Stack direction="column" id="events-container" flexGrow={1} sx={{ overflowY: 'hidden' }}>
63
- <Box
64
- ref={(el: HTMLDivElement) => setScrollableDiv(el)}
65
- sx={{
66
- overflowY: 'auto', px: 3, pb: 3,
67
- }}
68
- >
69
- {visibleEvents.map(([id, broadcastedRpcCall], index) => {
70
- return <BroadcastedRpcCallDetailsCard key={id} rpcRequestResponsePairs={broadcastedRpcCall} sx={{ mb: index < visibleEvents.length - 1 ? 2 : 0 }} />
71
- })}
72
- </Box>
73
- </Stack>
74
- </Drawer>
75
- )
76
- }
77
-
78
- export const BroadcastedRpcCallsDrawerWithEvents: React.FC<DrawerProps> = (props) => {
79
- const { clearEvents, events } = useRpcBroadcastListener()
80
-
81
- return (
82
- <BroadcastedRpcCallsDrawer
83
- events={events}
84
- onClearEvents={clearEvents}
85
- {...props}
86
- />
87
- )
88
- }
@@ -1,71 +0,0 @@
1
- import type { CardProps } from '@mui/material'
2
- import {
3
- Card, Collapse,
4
- Stack, Typography,
5
- } from '@mui/material'
6
- import { isDefined } from '@xylabs/sdk-js'
7
- import { JsonViewerEx } from '@xyo-network/react-payload-raw-info'
8
- import React, { memo, useState } from 'react'
9
-
10
- import type { RpcRequestResponsePairs } from '../../../model/index.ts'
11
- import { BroadcastedRpcCallDetailsSummaryStack } from './SummaryStack.tsx'
12
-
13
- const JSON_VIEWER_WIDTH = 600
14
-
15
- export interface BroadcastRpcCallDetailsCardProps extends CardProps {
16
- rpcRequestResponsePairs?: RpcRequestResponsePairs
17
- }
18
-
19
- export const BroadcastedRpcCallDetailsCard: React.FC<BroadcastRpcCallDetailsCardProps> = memo(({
20
- rpcRequestResponsePairs, sx, ...props
21
- }) => {
22
- const [expanded, setExpanded] = useState(false)
23
-
24
- if (!rpcRequestResponsePairs) return null
25
-
26
- const {
27
- request, result, source,
28
- } = rpcRequestResponsePairs
29
-
30
- return (
31
- <Card
32
- sx={{
33
- p: 1, display: 'flex', flexDirection: 'column', width: JSON_VIEWER_WIDTH, ...sx,
34
- }}
35
- {...props}
36
- >
37
- <BroadcastedRpcCallDetailsSummaryStack
38
- expanded={expanded}
39
- params={request.rpcCall.params}
40
- hasResult={isDefined(result)}
41
- method={request.rpcCall.method}
42
- setExpanded={setExpanded}
43
- timestamp={request.timestamp}
44
- />
45
- <Collapse in={expanded} mountOnEnter unmountOnExit>
46
- <Stack direction="column" p={1} gap={2} alignItems="stretch">
47
- <Typography variant="body2">
48
- Source:
49
- <Typography variant="caption" component="span" fontFamily="monospace" sx={{ ml: 1 }}>{source}</Typography>
50
- </Typography>
51
- <Typography variant="body2">Request:</Typography>
52
- <JsonViewerEx
53
- value={request}
54
- sx={{ maxHeight: 300, overflow: 'auto' }}
55
- />
56
- {isDefined(result)
57
- ? (
58
- <>
59
- <Typography variant="body2">Result:</Typography>
60
- <JsonViewerEx
61
- value={result}
62
- sx={{ maxHeight: 300, overflow: 'auto' }}
63
- />
64
- </>
65
- )
66
- : null}
67
- </Stack>
68
- </Collapse>
69
- </Card>
70
- )
71
- })
@@ -1,36 +0,0 @@
1
- import type { Meta, StoryFn } from '@storybook/react-vite'
2
- import React from 'react'
3
-
4
- import { BroadcastedRpcCallDetailsSummaryStack } from './index.ts'
5
-
6
- export default {
7
- title: 'network/Broadcast/Details/SummaryStack',
8
- component: BroadcastedRpcCallDetailsSummaryStack,
9
- } as Meta
10
-
11
- const Template: StoryFn<typeof BroadcastedRpcCallDetailsSummaryStack> = args => <BroadcastedRpcCallDetailsSummaryStack {...args} />
12
-
13
- const Default = Template.bind({})
14
- Default.args = {}
15
-
16
- const WithHashParam = Template.bind({})
17
- WithHashParam.args = {
18
- expanded: true,
19
- hasResult: true,
20
- method: 'xyoViewer_blocksByHash',
21
- params: ['5378eddddc7f5a16766988eafcfd28499a9d0248974c23bef2d92eb359834bca', 1],
22
- timestamp: Date.now(),
23
- }
24
-
25
- const WithUnknownParam = Template.bind({})
26
- WithUnknownParam.args = {
27
- expanded: true,
28
- hasResult: true,
29
- method: 'xyoViewer_currentBlock',
30
- params: [],
31
- timestamp: Date.now(),
32
- }
33
-
34
- export {
35
- Default, WithHashParam, WithUnknownParam,
36
- }
@@ -1,68 +0,0 @@
1
- import type { JsonRpcParams } from '@metamask/json-rpc-engine/v2'
2
- import {
3
- ArrowRight, CheckCircle, Warning,
4
- } from '@mui/icons-material'
5
- import {
6
- Avatar,
7
- Icon, IconButton, Stack, type StackProps, Tooltip, Typography,
8
- useTheme,
9
- } from '@mui/material'
10
- import { Identicon } from '@xylabs/react-identicon'
11
- import { usePromise } from '@xylabs/react-promise'
12
- import { isDefined } from '@xylabs/sdk-js'
13
- import { ObjectHasher } from '@xyo-network/hash'
14
- import React, { useMemo } from 'react'
15
-
16
- export interface BroadcastRpcCallDetailsSummaryStackProps extends StackProps {
17
- expanded?: boolean
18
- hasResult?: boolean
19
- method?: string
20
- params?: JsonRpcParams
21
- setExpanded?: (expanded: boolean) => void
22
- timestamp?: number
23
- }
24
-
25
- export const BroadcastedRpcCallDetailsSummaryStack: React.FC<BroadcastRpcCallDetailsSummaryStackProps> = ({
26
- expanded, setExpanded, method, timestamp, hasResult, params, ...props
27
- }) => {
28
- const theme = useTheme()
29
- const [hash, hashError] = usePromise(async () => {
30
- if (isDefined(params)) {
31
- return await ObjectHasher.hash(params)
32
- }
33
- }, [params])
34
-
35
- const formattedTimestamp = useMemo(() => isDefined(timestamp) ? new Date(timestamp).toLocaleString() : '', [timestamp])
36
-
37
- return (
38
- <Stack direction="row" gap={2} alignItems="center" justifyContent="space-between" {...props}>
39
- <Stack direction="row" gap={2} alignItems="center">
40
- <IconButton
41
- size="small"
42
- onClick={() => setExpanded?.(!expanded)}
43
- >
44
- <ArrowRight sx={{ transform: expanded ? 'rotate(90deg)' : 'rotate(0deg)', transition: 'transform 0.2s ease-in-out' }} fontSize="small" />
45
- </IconButton>
46
- <Tooltip
47
- title={isDefined(hashError)
48
- ? `Error generating hash of params: ${hashError.message}`
49
- : isDefined(params) ? `Params : ${JSON.stringify(params, null, 2)}` : 'No Params Provided'}
50
- >
51
- <Avatar sx={{
52
- backgroundColor: theme.vars?.palette.text.primary, width: 20, height: 20, opacity: isDefined(hash) ? 1 : 0.5,
53
- }}
54
- >
55
- <Identicon value={hash} size={14} />
56
- </Avatar>
57
- </Tooltip>
58
- <Typography component="span" variant="body2" fontFamily="monospace">
59
- {method}
60
- </Typography>
61
- <Typography component="span" variant="caption" color="text.secondary" sx={{ opacity: 0.6 }}>
62
- {formattedTimestamp}
63
- </Typography>
64
- </Stack>
65
- <Icon sx={{ justifySelf: 'end' }}>{hasResult ? <CheckCircle color="success" /> : <Warning color="warning" />}</Icon>
66
- </Stack>
67
- )
68
- }
@@ -1,2 +0,0 @@
1
- export * from './Card.tsx'
2
- export * from './SummaryStack.tsx'
@@ -1 +0,0 @@
1
- export * from './Drawer.tsx'
@@ -1,69 +0,0 @@
1
- import { isDefinedNotNull } from '@xylabs/sdk-js'
2
- import type { ChangeEvent } from 'react'
3
- import {
4
- useCallback, useMemo, useState,
5
- } from 'react'
6
-
7
- import type { RpcRequestResponsePairsById } from '../../model/index.ts'
8
-
9
- export const usePaginatedEventPairs = (
10
- formattedEvents: RpcRequestResponsePairsById,
11
- numberOfVisiblePairs: number,
12
- onClearEvents?: () => void,
13
- scrollableDiv?: HTMLDivElement | null,
14
- ) => {
15
- const [currentPage, setCurrentPage] = useState(0)
16
-
17
- const allEventEntries = useMemo(() => {
18
- return Object.entries(formattedEvents ?? {}).toSorted(([, a], [, b]) => b.request.timestamp - a.request.timestamp)
19
- }, [formattedEvents])
20
-
21
- const totalPages = useMemo(() => {
22
- return Math.ceil(allEventEntries.length / numberOfVisiblePairs)
23
- }, [allEventEntries.length, numberOfVisiblePairs])
24
-
25
- // Clamp current page to valid range
26
- const effectiveCurrentPage = useMemo(() => {
27
- if (totalPages === 0) return 0
28
- return Math.min(currentPage, totalPages - 1)
29
- }, [currentPage, totalPages])
30
-
31
- const visibleEvents = useMemo(() => {
32
- if (isDefinedNotNull(scrollableDiv)) {
33
- scrollableDiv.scrollTo({ top: 0, behavior: 'smooth' })
34
- }
35
- const startIndex = effectiveCurrentPage * numberOfVisiblePairs
36
- const endIndex = startIndex + numberOfVisiblePairs
37
- return allEventEntries.slice(startIndex, endIndex)
38
- }, [allEventEntries, effectiveCurrentPage, numberOfVisiblePairs, scrollableDiv])
39
-
40
- const handlePreviousPage = useCallback(() => {
41
- setCurrentPage(prev => Math.max(0, prev - 1))
42
- }, [])
43
-
44
- const handleNextPage = useCallback(() => {
45
- setCurrentPage(prev => Math.min(totalPages - 1, prev + 1))
46
- }, [totalPages])
47
-
48
- const handleClearEvents = useCallback(() => {
49
- setCurrentPage(0)
50
- onClearEvents?.()
51
- }, [onClearEvents])
52
-
53
- // Compatible with TablePagination's onPageChange signature
54
- // Accepts 1-indexed page, converts to 0-indexed internally
55
- const handlePageChange = useCallback((_event: ChangeEvent<unknown>, page: number) => {
56
- setCurrentPage(page - 1)
57
- }, [])
58
-
59
- return {
60
- allEventEntries,
61
- visibleEvents,
62
- effectiveCurrentPage: effectiveCurrentPage + 1, // Return 1-indexed page
63
- totalPages,
64
- handlePreviousPage,
65
- handleNextPage,
66
- handleClearEvents,
67
- handlePageChange,
68
- }
69
- }
@@ -1,3 +0,0 @@
1
- export * from './broadcast/index.ts'
2
- export * from './menu/index.ts'
3
- export * from './status/index.ts'
@@ -1,42 +0,0 @@
1
- import type { AvatarProps } from '@mui/material'
2
- import { Avatar } from '@mui/material'
3
- import type { CSSProperties } from 'react'
4
- import React from 'react'
5
-
6
- import { useChainNetwork } from '../../context/index.ts'
7
- import { NetworkIcon } from './Icon.tsx'
8
-
9
- export interface NetworkAvatarProps extends AvatarProps {
10
- icon?: string
11
- iconStyles?: CSSProperties
12
- name?: string
13
- }
14
-
15
- export const NetworkAvatar: React.FC<NetworkAvatarProps> = ({
16
- icon, iconStyles, name, sx, ...props
17
- }) => {
18
- return (
19
- <Avatar
20
- sx={{ backgroundColor: 'white', ...sx }}
21
- alt={name}
22
- {...props}
23
- >
24
- <NetworkIcon
25
- icon={icon}
26
- style={{ ...iconStyles }}
27
- />
28
- </Avatar>
29
- )
30
- }
31
-
32
- export const ActiveNetworkAvatar: React.FC<AvatarProps> = (props) => {
33
- const { activeNetwork } = useChainNetwork()
34
-
35
- return (
36
- <NetworkAvatar
37
- icon={activeNetwork?.icon}
38
- name={activeNetwork?.name}
39
- {...props}
40
- />
41
- )
42
- }
@@ -1,21 +0,0 @@
1
- import type { DetailedHTMLProps, HtmlHTMLAttributes } from 'react'
2
- import React from 'react'
3
-
4
- export interface NetworkIconProps extends DetailedHTMLProps<HtmlHTMLAttributes<HTMLSpanElement>, HTMLSpanElement> {
5
- icon?: string
6
- }
7
-
8
- export const NetworkIcon: React.FC<NetworkIconProps> = ({
9
- icon, style, ...props
10
- }) => {
11
- return (
12
- <span
13
- // eslint-disable-next-line react-dom/no-dangerously-set-innerhtml
14
- dangerouslySetInnerHTML={{ __html: icon ?? '' }} // Placeholder for SVG\
15
- style={{
16
- display: 'inline-flex', width: 24, height: 24, ...style,
17
- }}
18
- {...props}
19
- />
20
- )
21
- }
@@ -1,38 +0,0 @@
1
- import type { MenuItemProps } from '@mui/material'
2
- import { ListItemText } from '@mui/material'
3
- import { ActiveMenuItem } from '@xyo-network/react-chain-shared'
4
- import type { NetworkBootstrap, NetworkId } from '@xyo-network/xl1-sdk'
5
- import type { MouseEvent as ReactMouseEvent } from 'react'
6
- import React from 'react'
7
-
8
- import { NetworkAvatar } from './Avatar.tsx'
9
-
10
- export interface NetworkMenuItemProps extends MenuItemProps {
11
- active?: boolean
12
- network?: NetworkBootstrap
13
- updateActiveNetwork?: (networkId: NetworkId) => void
14
- }
15
-
16
- export const NetworkMenuItem: React.FC<NetworkMenuItemProps> = ({
17
- active, network, onClick, updateActiveNetwork, ...props
18
- }) => {
19
- const handleClick = (event: ReactMouseEvent<HTMLLIElement, MouseEvent>) => {
20
- if (network === undefined) throw new Error('Network is undefined')
21
- updateActiveNetwork?.(network.id)
22
- onClick?.(event)
23
- }
24
-
25
- return (
26
- <ActiveMenuItem
27
- title={network?.name}
28
- disableRipple
29
- onClick={handleClick}
30
- active={active}
31
- sx={{ py: 1 }}
32
- {...props}
33
- >
34
- <NetworkAvatar icon={network?.icon} name={network?.name} sx={{ width: 30, height: 30 }} />
35
- <ListItemText>{network?.name}</ListItemText>
36
- </ActiveMenuItem>
37
- )
38
- }
@@ -1,3 +0,0 @@
1
- export * from './Avatar.tsx'
2
- export * from './Icon.tsx'
3
- export * from './MenuItem.tsx'
@@ -1,74 +0,0 @@
1
- import type { Meta, StoryFn } from '@storybook/react-vite'
2
- import type { NetworkStatus } from '@xyo-network/xl1-sdk'
3
- import { NetworkStatusSchema } from '@xyo-network/xl1-sdk'
4
- import React from 'react'
5
-
6
- import { NetworkStatusAlert } from './Alert.tsx'
7
-
8
- const exampleOnlineStatus: NetworkStatus = {
9
- state: 'online',
10
- schema: NetworkStatusSchema,
11
- description: 'The network is online and functioning normally.',
12
- }
13
-
14
- const exampleOfflineStatus: NetworkStatus = {
15
- state: 'offline',
16
- schema: NetworkStatusSchema,
17
- description: 'The network is offline and not functioning.',
18
- updates: [
19
- {
20
- start: Date.now() - 1000 * 60 * 60,
21
- end: Date.now(),
22
- update: 'The network was offline for 1 hour.',
23
- },
24
- ],
25
- }
26
- const exampleUnknown: NetworkStatus = {
27
- state: 'unknown',
28
- schema: NetworkStatusSchema,
29
- description: 'Unable to fetch network status.',
30
- }
31
-
32
- const exampleDegradedStatus: NetworkStatus = {
33
- state: 'degraded',
34
- schema: NetworkStatusSchema,
35
- description: 'The network is degraded and may be experiencing issues.',
36
- updates: [
37
- {
38
- start: Date.now() - 1000 * 60 * 60,
39
- end: Date.now(),
40
- update: 'Blocks are being produced, but some nodes are offline.',
41
- },
42
- {
43
- start: Date.now() - 1000 * 60 * 60,
44
- end: Date.now(),
45
- update: 'Blocks are being produced, but some nodes are offline.',
46
- },
47
- ],
48
- }
49
-
50
- export default {
51
- title: 'Network/Status/Alert',
52
- component: NetworkStatusAlert,
53
- } as Meta
54
-
55
- const Template: StoryFn<typeof NetworkStatusAlert> = args => <NetworkStatusAlert {...args} />
56
-
57
- const Default = Template.bind({})
58
- Default.args = {}
59
-
60
- const WithOnlineStatus = Template.bind({})
61
- WithOnlineStatus.args = { status: exampleOnlineStatus }
62
-
63
- const WithOfflineStatus = Template.bind({})
64
- WithOfflineStatus.args = { status: exampleOfflineStatus }
65
-
66
- const WithDegradedStatus = Template.bind({})
67
- WithDegradedStatus.args = { status: exampleDegradedStatus }
68
-
69
- const WithUnknownStatus = Template.bind({})
70
- WithUnknownStatus.args = { status: exampleUnknown }
71
-
72
- export {
73
- Default, WithDegradedStatus, WithOfflineStatus, WithOnlineStatus, WithUnknownStatus,
74
- }
@@ -1,51 +0,0 @@
1
- import type { AlertProps } from '@mui/material'
2
- import {
3
- Alert, AlertTitle, Button,
4
- } from '@mui/material'
5
- import type { NetworkStatus } from '@xyo-network/xl1-sdk'
6
- import React, { useMemo, useState } from 'react'
7
-
8
- import { NetworkStatusDialog } from './Dialog.tsx'
9
-
10
- export interface NetworkStatusAlertProps extends AlertProps {
11
- status?: NetworkStatus
12
- }
13
-
14
- export const NetworkStatusAlert: React.FC<NetworkStatusAlertProps> = ({ status, ...props }) => {
15
- const [open, setOpen] = useState(false)
16
- const handleClose = () => setOpen(false)
17
-
18
- const severity = useMemo(() => {
19
- if (!status) return
20
- switch (status.state) {
21
- case 'online': {
22
- return 'success'
23
- }
24
- case 'offline': {
25
- return 'error'
26
- }
27
- case 'degraded': {
28
- return 'warning'
29
- }
30
- case 'unknown': {
31
- return 'error'
32
- }
33
- }
34
- }, [status])
35
-
36
- return (
37
- <Alert severity={severity} {...props}>
38
- <AlertTitle>{status?.description}</AlertTitle>
39
- {status?.updates && status.updates.length > 0
40
- ? (
41
- <>
42
- <Button color={severity} variant="outlined" size="small" onClick={() => setOpen(true)}>
43
- Updates
44
- </Button>
45
- <NetworkStatusDialog open={open} onClose={handleClose} updates={status.updates} />
46
- </>
47
- )
48
- : null}
49
- </Alert>
50
- )
51
- }
@@ -1,51 +0,0 @@
1
- import type { DialogProps } from '@mui/material'
2
- import {
3
- Button, Dialog, DialogActions, DialogContent, DialogTitle, List, ListItem, Typography,
4
- } from '@mui/material'
5
- import type { NetworkStatusUpdate } from '@xyo-network/xl1-sdk'
6
- import React from 'react'
7
-
8
- export interface NetworkStatusDialogProps extends DialogProps {
9
- updates: NetworkStatusUpdate[]
10
- }
11
-
12
- export const NetworkStatusDialog: React.FC<NetworkStatusDialogProps> = ({ updates, ...props }) => {
13
- return (
14
- <Dialog {...props}>
15
- <DialogTitle>Recent Status Updates</DialogTitle>
16
- <DialogContent>
17
- <List>
18
- {updates.map(({
19
- start, end, update,
20
- }) => (
21
- <ListItem
22
- key={start + update}
23
- sx={{
24
- flexDirection: 'column', alignItems: 'start', pl: 0,
25
- }}
26
- >
27
- <Typography>
28
- {update}
29
- </Typography>
30
- <Typography gutterBottom sx={{ opacity: 0.75, fontSize: '.8333rem' }}>
31
- Start:
32
- {' '}
33
- {new Date(start).toLocaleString()}
34
- {' '}
35
- <br />
36
- End:
37
- {' '}
38
- {new Date(end).toLocaleString()}
39
- </Typography>
40
- </ListItem>
41
- ))}
42
- </List>
43
- </DialogContent>
44
- <DialogActions>
45
- <Button onClick={e => props.onClose?.(e, 'backdropClick')} color="primary" variant="outlined">
46
- Close
47
- </Button>
48
- </DialogActions>
49
- </Dialog>
50
- )
51
- }
@@ -1,21 +0,0 @@
1
- import type { AlertProps } from '@mui/material'
2
- import type { PropsWithChildren } from 'react'
3
- import React from 'react'
4
-
5
- import { usePollNetworkStatus } from '../../hooks/index.ts'
6
- import { NetworkStatusAlert } from './Alert.tsx'
7
-
8
- const validNetworkStates = new Set(['online', 'unknown'])
9
-
10
- export interface NetworkStatusProps extends PropsWithChildren<AlertProps> {}
11
-
12
- export const NetworkStatus: React.FC<NetworkStatusProps> = ({ children, ...props }) => {
13
- const [networkStatus] = usePollNetworkStatus()
14
- const showStatus = networkStatus && !validNetworkStates.has(networkStatus.state)
15
- return (
16
- <>
17
- {showStatus ? <NetworkStatusAlert status={networkStatus} {...props} /> : null}
18
- {children}
19
- </>
20
- )
21
- }
@@ -1,2 +0,0 @@
1
- export * from './Alert.tsx'
2
- export * from './NetworkStatus.tsx'
@@ -1,21 +0,0 @@
1
- import { GatewayProvider, InPageGatewaysProvider } from '@xyo-network/react-chain-provider'
2
- import type { AccountInstance } from '@xyo-network/sdk-js'
3
- import type { PropsWithChildren } from 'react'
4
- import React from 'react'
5
-
6
- import { useChainNetwork } from './network/index.ts'
7
-
8
- export interface ActiveGatewayProviderProps extends PropsWithChildren {
9
- account?: AccountInstance
10
- }
11
-
12
- export const ActiveGatewayProvider: React.FC<ActiveGatewayProviderProps> = ({ account, children }) => {
13
- const { activeNetwork } = useChainNetwork()
14
- return (
15
- <InPageGatewaysProvider account={account}>
16
- <GatewayProvider gatewayName={activeNetwork?.id}>
17
- {children}
18
- </GatewayProvider>
19
- </InPageGatewaysProvider>
20
- )
21
- }