@xyo-network/react-payload 2.26.35 → 2.26.38

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 (39) hide show
  1. package/dist/docs.json +1 -1
  2. package/package.json +9 -9
  3. package/src/components/Details/DataDetails.tsx +65 -0
  4. package/src/components/Details/Details.stories.tsx +62 -0
  5. package/src/components/Details/Details.tsx +27 -0
  6. package/src/components/Details/HashSourceDetails.tsx +41 -0
  7. package/src/components/Details/JsonDetails.tsx +44 -0
  8. package/src/components/Details/MetaDetails.tsx +38 -0
  9. package/src/components/Details/ValidationDetails/ValidationDetails.stories.tsx +55 -0
  10. package/src/components/Details/ValidationDetails/ValidationDetails.tsx +42 -0
  11. package/src/components/Details/ValidationDetails/ValidationDetailsProps.ts +8 -0
  12. package/src/components/Details/ValidationDetails/index.ts +2 -0
  13. package/src/components/Details/index.ts +5 -0
  14. package/src/components/Table/PayloadTableColumnConfig.ts +28 -0
  15. package/src/components/Table/Table.stories.tsx +43 -0
  16. package/src/components/Table/Table.tsx +60 -0
  17. package/src/components/Table/TableRow.tsx +104 -0
  18. package/src/components/Table/index.ts +3 -0
  19. package/src/components/index.ts +2 -0
  20. package/src/contexts/Payload/Context.ts +5 -0
  21. package/src/contexts/Payload/Provider.tsx +31 -0
  22. package/src/contexts/Payload/State.ts +8 -0
  23. package/src/contexts/Payload/index.ts +4 -0
  24. package/src/contexts/Payload/use.ts +7 -0
  25. package/src/contexts/index.ts +1 -0
  26. package/src/hooks/ResolvePayloadArgs.ts +6 -0
  27. package/src/hooks/index.ts +6 -0
  28. package/src/hooks/lib/FetchHuriHashOptions.ts +3 -0
  29. package/src/hooks/lib/findHuriNetwork.ts +13 -0
  30. package/src/hooks/lib/index.ts +2 -0
  31. package/src/hooks/useGetSchema.stories.tsx +70 -0
  32. package/src/hooks/useGetSchema.tsx +51 -0
  33. package/src/hooks/useHuriHash.stories.tsx +108 -0
  34. package/src/hooks/useHuriHash.tsx +38 -0
  35. package/src/hooks/useLoadPayload.stories.tsx +69 -0
  36. package/src/hooks/useLoadPayload.tsx +60 -0
  37. package/src/hooks/useResolveHuri.tsx +74 -0
  38. package/src/index.ts +3 -0
  39. package/src/types/images.d.ts +5 -0
package/dist/docs.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "fileName": "index.ts",
11
11
  "line": 1,
12
12
  "character": 0,
13
- "url": "https://github.com/XYOracleNetwork/sdk-xyo-react-js/blob/7efa6fa/packages/payload/src/index.ts#L1"
13
+ "url": "https://github.com/XYOracleNetwork/sdk-xyo-react-js/blob/c31a96d/packages/payload/src/index.ts#L1"
14
14
  }
15
15
  ]
16
16
  }
package/package.json CHANGED
@@ -21,14 +21,14 @@
21
21
  "@xyo-network/api": "^2.22.15",
22
22
  "@xyo-network/network": "^2.22.15",
23
23
  "@xyo-network/payload": "^2.22.15",
24
- "@xyo-network/react-archive": "^2.26.35",
25
- "@xyo-network/react-archivist": "^2.26.35",
26
- "@xyo-network/react-archivist-api": "^2.26.35",
27
- "@xyo-network/react-auth-service": "^2.26.35",
28
- "@xyo-network/react-network": "^2.26.35",
29
- "@xyo-network/react-property": "^2.26.35",
30
- "@xyo-network/react-schema": "^2.26.35",
31
- "@xyo-network/react-shared": "^2.26.35",
24
+ "@xyo-network/react-archive": "^2.26.38",
25
+ "@xyo-network/react-archivist": "^2.26.38",
26
+ "@xyo-network/react-archivist-api": "^2.26.38",
27
+ "@xyo-network/react-auth-service": "^2.26.38",
28
+ "@xyo-network/react-network": "^2.26.38",
29
+ "@xyo-network/react-property": "^2.26.38",
30
+ "@xyo-network/react-schema": "^2.26.38",
31
+ "@xyo-network/react-shared": "^2.26.38",
32
32
  "@xyo-network/utils": "^2.22.15",
33
33
  "luxon": "^3.0.1",
34
34
  "react": "^18.2.0",
@@ -95,5 +95,5 @@
95
95
  },
96
96
  "sideEffects": false,
97
97
  "types": "dist/esm/index.d.ts",
98
- "version": "2.26.35"
98
+ "version": "2.26.38"
99
99
  }
@@ -0,0 +1,65 @@
1
+ import ContentCopyIcon from '@mui/icons-material/ContentCopy'
2
+ import VisibilityIcon from '@mui/icons-material/Visibility'
3
+ import { Dialog, DialogActions, DialogContent, DialogTitle } from '@mui/material'
4
+ import { ButtonEx } from '@xylabs/react-button'
5
+ import { XyoPayload, XyoPayloadWrapper } from '@xyo-network/payload'
6
+ import { Property, PropertyAction, PropertyProps } from '@xyo-network/react-property'
7
+ import { SizeProp } from '@xyo-network/react-shared'
8
+ import { useState } from 'react'
9
+
10
+ import { PayloadHashSourceDetails } from './HashSourceDetails'
11
+
12
+ export type PayloadDataDetailsProps = PropertyProps & {
13
+ payload?: XyoPayload
14
+ size?: SizeProp
15
+ badge?: boolean
16
+ }
17
+
18
+ export const PayloadDataDetails: React.FC<PayloadDataDetailsProps> = ({ size, badge, payload, ...props }) => {
19
+ const wrapper = payload ? new XyoPayloadWrapper(payload) : undefined
20
+
21
+ const [viewSourceOpen, setViewSourceOpen] = useState(false)
22
+ const hash = wrapper?.hash
23
+
24
+ let elevation = 2
25
+ if (props.paper) {
26
+ elevation += props.elevation ?? 0
27
+ }
28
+
29
+ const actions: PropertyAction[] = [
30
+ {
31
+ icon: <VisibilityIcon />,
32
+ name: 'View',
33
+ onClick: () => setViewSourceOpen(true),
34
+ },
35
+ {
36
+ icon: <ContentCopyIcon />,
37
+ name: 'Copy',
38
+ onClick: async () => await navigator.clipboard.writeText(wrapper?.hash ?? ''),
39
+ },
40
+ ]
41
+
42
+ const onCopy = async () => {
43
+ await navigator.clipboard.writeText(wrapper?.stringified ?? '')
44
+ }
45
+
46
+ return (
47
+ <>
48
+ <Property titleProps={{ elevation }} badge={badge} size={size} actions={actions} title="Payload Hash" value={hash ?? '<Unknown>'} tip="This is the payload hash" {...props} />
49
+ <Dialog open={viewSourceOpen} onClose={() => setViewSourceOpen(false)}>
50
+ <DialogTitle>Hash Source</DialogTitle>
51
+ <DialogContent>
52
+ <PayloadHashSourceDetails noTitle payload={payload} />
53
+ </DialogContent>
54
+ <DialogActions>
55
+ <ButtonEx color="secondary" onClick={onCopy}>
56
+ Copy
57
+ </ButtonEx>
58
+ <ButtonEx color="secondary" onClick={() => setViewSourceOpen(false)}>
59
+ Close
60
+ </ButtonEx>
61
+ </DialogActions>
62
+ </Dialog>
63
+ </>
64
+ )
65
+ }
@@ -0,0 +1,62 @@
1
+ import { ComponentMeta, ComponentStory } from '@storybook/react'
2
+ import { BrowserRouter, Route, Routes } from 'react-router-dom'
3
+
4
+ import { appThemeDecorator, samplePayload, samplePayloadFromBuilder } from '../../../../../.storybook'
5
+ import { PayloadDetails } from './Details'
6
+
7
+ const StorybookEntry = {
8
+ argTypes: {},
9
+ component: PayloadDetails,
10
+ parameters: {
11
+ docs: {
12
+ page: null,
13
+ },
14
+ },
15
+ title: 'payload/Details',
16
+ } as ComponentMeta<typeof PayloadDetails>
17
+
18
+ const Template: ComponentStory<typeof PayloadDetails> = (args) => (
19
+ <BrowserRouter>
20
+ <Routes>
21
+ <Route path="temp" element={<h1>Successfully navigated to archivePath</h1>} />
22
+ <Route path="*" element={<PayloadDetails {...args}></PayloadDetails>}></Route>
23
+ </Routes>
24
+ </BrowserRouter>
25
+ )
26
+
27
+ const Default = Template.bind({})
28
+ Default.args = {}
29
+ Default.decorators = [appThemeDecorator]
30
+
31
+ const WithSample = Template.bind({})
32
+ WithSample.args = { payload: samplePayload }
33
+ WithSample.decorators = [appThemeDecorator]
34
+
35
+ const WithBuilderSample = Template.bind({})
36
+ WithBuilderSample.args = { payload: samplePayloadFromBuilder }
37
+ WithBuilderSample.decorators = [appThemeDecorator]
38
+
39
+ const WithArchiveLink = Template.bind({})
40
+ WithArchiveLink.args = { archivePath: 'temp', payload: samplePayloadFromBuilder }
41
+ WithArchiveLink.decorators = [appThemeDecorator]
42
+
43
+ const DefaultPaper = Template.bind({})
44
+ DefaultPaper.args = { paper: true }
45
+ DefaultPaper.decorators = [appThemeDecorator]
46
+
47
+ const WithSamplePaper = Template.bind({})
48
+ WithSamplePaper.args = { paper: true, payload: samplePayload }
49
+ WithSamplePaper.decorators = [appThemeDecorator]
50
+
51
+ const WithBuilderSamplePaper = Template.bind({})
52
+ WithBuilderSamplePaper.args = { paper: true, payload: samplePayloadFromBuilder }
53
+ WithBuilderSamplePaper.decorators = [appThemeDecorator]
54
+
55
+ const WithArchiveLinkPaper = Template.bind({})
56
+ WithArchiveLinkPaper.args = { archivePath: 'temp', paper: true, payload: samplePayloadFromBuilder }
57
+ WithArchiveLinkPaper.decorators = [appThemeDecorator]
58
+
59
+ export { Default, DefaultPaper, WithArchiveLink, WithArchiveLinkPaper, WithBuilderSample, WithBuilderSamplePaper, WithSample, WithSamplePaper }
60
+
61
+ // eslint-disable-next-line import/no-default-export
62
+ export default StorybookEntry
@@ -0,0 +1,27 @@
1
+ import { FlexBoxProps, FlexCol } from '@xylabs/react-flexbox'
2
+ import { XyoPayload } from '@xyo-network/payload'
3
+
4
+ import { PayloadDataDetails } from './DataDetails'
5
+ import { PayloadJsonDetails } from './JsonDetails'
6
+ import { PayloadMetaDetails } from './MetaDetails'
7
+ import { PayloadValidationDetails } from './ValidationDetails'
8
+
9
+ export type WithPaper<T> = T & { paper: true }
10
+ export type WithoutPaper<T> = T & { paper?: false }
11
+
12
+ export type PayloadDetailsProps = FlexBoxProps & {
13
+ payload?: XyoPayload
14
+ paper?: boolean
15
+ archivePath?: string
16
+ }
17
+
18
+ export const PayloadDetails: React.FC<PayloadDetailsProps> = ({ archivePath, paper, payload, ...props }) => {
19
+ return (
20
+ <FlexCol gap={1} justifyContent="flex-start" alignItems="stretch" marginTop={2} marginBottom={8} {...props}>
21
+ <PayloadDataDetails paper={paper} size="large" badge payload={payload} />
22
+ <PayloadMetaDetails archivePath={archivePath} paper={paper ? true : false} value={payload} />
23
+ <PayloadValidationDetails paper={paper} value={payload} />
24
+ <PayloadJsonDetails paper={paper} payload={payload} />
25
+ </FlexCol>
26
+ )
27
+ }
@@ -0,0 +1,41 @@
1
+ import ContentCopyIcon from '@mui/icons-material/ContentCopy'
2
+ import { IconButton, Typography, useTheme } from '@mui/material'
3
+ import { FlexBoxProps, FlexCol, FlexGrowRow, FlexRow } from '@xylabs/react-flexbox'
4
+ import { QuickTipButton } from '@xylabs/react-quick-tip-button'
5
+ import { XyoPayload, XyoPayloadWrapper } from '@xyo-network/payload'
6
+
7
+ export interface PayloadHashSourceDetailsProps extends FlexBoxProps {
8
+ noTitle?: boolean
9
+ payload?: XyoPayload
10
+ }
11
+
12
+ export const PayloadHashSourceDetails: React.FC<PayloadHashSourceDetailsProps> = ({ noTitle = false, payload, ...props }) => {
13
+ const theme = useTheme()
14
+ const payloadWrapper = payload ? new XyoPayloadWrapper(payload) : null
15
+
16
+ return (
17
+ <FlexCol alignItems="stretch" {...props}>
18
+ {noTitle ? null : (
19
+ <FlexRow margin={1} justifyContent="flex-start">
20
+ <Typography>Hash Source</Typography>
21
+ <QuickTipButton title="Hash Source">The actual string used to generate the hash (SHA256)</QuickTipButton>
22
+ </FlexRow>
23
+ )}
24
+ <FlexRow>
25
+ <FlexGrowRow background border={1} borderColor={theme.palette.divider} justifyContent="start">
26
+ <Typography padding={2} fontFamily="monospace" variant="body1" sx={{ overflowWrap: 'break-word', wordBreak: 'break-all' }}>
27
+ {payloadWrapper?.stringified ?? ''}
28
+ </Typography>
29
+ </FlexGrowRow>
30
+ <IconButton>
31
+ <ContentCopyIcon />
32
+ </IconButton>
33
+ </FlexRow>
34
+ {noTitle ? (
35
+ <FlexRow margin={1} justifyContent="flex-start">
36
+ <Typography variant="body2">The actual string used to generate the hash (SHA256). This can be used to validate the hash manually.</Typography>
37
+ </FlexRow>
38
+ ) : null}
39
+ </FlexCol>
40
+ )
41
+ }
@@ -0,0 +1,44 @@
1
+ import { Paper, useMediaQuery, useTheme } from '@mui/material'
2
+ import { FlexGrowRow } from '@xylabs/react-flexbox'
3
+ import { XyoPayload } from '@xyo-network/payload'
4
+ import { PropertyGroup, PropertyGroupProps } from '@xyo-network/react-property'
5
+ import { lazy, Suspense } from 'react'
6
+ import { ReactJsonViewProps } from 'react-json-view'
7
+
8
+ const JsonView = lazy(() => import(/* webpackChunkName: "jsonView" */ 'react-json-view'))
9
+
10
+ export type PayloadJsonDetailsProps = PropertyGroupProps & {
11
+ payload?: XyoPayload
12
+ jsonViewProps?: ReactJsonViewProps
13
+ }
14
+
15
+ export const PayloadJsonDetails: React.FC<PayloadJsonDetailsProps> = ({ jsonViewProps, payload = {}, ...props }) => {
16
+ const { breakpoints, palette } = useTheme()
17
+ const belowSm = useMediaQuery(breakpoints.down('sm'))
18
+
19
+ let elevation = 2
20
+ if (props.paper) {
21
+ elevation += props.elevation ?? 0
22
+ }
23
+
24
+ const jsonTheme = palette.mode === 'dark' ? 'shapeshifter' : undefined
25
+
26
+ return (
27
+ <PropertyGroup titleProps={{ elevation }} title="JSON" tip="The raw JSON of the payload" {...props}>
28
+ <Paper square variant="elevation" style={{ overflow: 'hidden', padding: '16px', width: '100%' }}>
29
+ <Suspense fallback={<FlexGrowRow />}>
30
+ <JsonView
31
+ groupArraysAfterLength={5}
32
+ shouldCollapse={(props) => props.name !== 'root'}
33
+ style={{ backgroundColor: undefined, overflow: 'hidden' }}
34
+ src={payload}
35
+ enableClipboard
36
+ theme={jsonTheme}
37
+ collapseStringsAfterLength={belowSm ? 24 : 32}
38
+ {...jsonViewProps}
39
+ />
40
+ </Suspense>
41
+ </Paper>
42
+ </PropertyGroup>
43
+ )
44
+ }
@@ -0,0 +1,38 @@
1
+ import { XyoPayloadWithPartialMeta } from '@xyo-network/payload'
2
+ import { ArchiveProperty } from '@xyo-network/react-archive'
3
+ import { Property, PropertyGroup, PropertyGroupProps } from '@xyo-network/react-property'
4
+
5
+ export type PayloadMetaDetailsProps = PropertyGroupProps & {
6
+ value?: XyoPayloadWithPartialMeta
7
+ archivePath?: string
8
+ }
9
+
10
+ export const PayloadMetaDetails: React.FC<PayloadMetaDetailsProps> = ({ archivePath, value, ...props }) => {
11
+ let elevation = 2
12
+ if (props.paper) {
13
+ elevation += props.elevation ?? 0
14
+ }
15
+ return (
16
+ <PropertyGroup titleProps={{ elevation }} title="Meta" tip="The meta fields added to the record by the archivist" {...props}>
17
+ {value?._client ? (
18
+ <Property titleProps={{ elevation }} flexGrow={1} title="Client" value={value?._client ?? '<Unknown>'} tip="This client used to create this payload" />
19
+ ) : null}
20
+ {value?._archive ? <ArchiveProperty titleProps={{ elevation }} flexGrow={1} payload={value} path={archivePath} /> : null}
21
+ {value?._reportedHash ? (
22
+ <Property titleProps={{ elevation }} flexGrow={1} title="Reported Hash" value={value?._reportedHash ?? '<Unknown>'} tip="The has reported by the payload" />
23
+ ) : null}
24
+ {value?._timestamp ? (
25
+ <Property titleProps={{ elevation }} flexGrow={1} title="Timestamp" value={value?._timestamp ?? '<Unknown>'} tip="This timestamp of the payload" />
26
+ ) : null}
27
+ {value?._observeDuration ? (
28
+ <Property
29
+ titleProps={{ elevation }}
30
+ flexGrow={1}
31
+ title="Observation Duration"
32
+ value={value?._observeDuration ?? '<Unknown>'}
33
+ tip="This duration of time observed by the witness"
34
+ />
35
+ ) : null}
36
+ </PropertyGroup>
37
+ )
38
+ }
@@ -0,0 +1,55 @@
1
+ import { ComponentStory, Meta } from '@storybook/react'
2
+ import { BrowserRouter } from 'react-router-dom'
3
+
4
+ import { appThemeDecorator, samplePayload } from '../../../../../../.storybook'
5
+ import { PayloadDetails } from '../Details'
6
+ import { PayloadValidationDetails } from './ValidationDetails'
7
+
8
+ const StorybookEntry: Meta = {
9
+ argTypes: {},
10
+ args: {
11
+ value: {
12
+ schema: 'network.xyo.schema',
13
+ },
14
+ },
15
+ component: PayloadDetails,
16
+ decorators: [appThemeDecorator],
17
+ parameters: {
18
+ docs: {
19
+ page: null,
20
+ },
21
+ },
22
+ title: 'payload/ValidationDetails',
23
+ }
24
+
25
+ const Template: ComponentStory<typeof PayloadValidationDetails> = (args) => (
26
+ <BrowserRouter>
27
+ <PayloadValidationDetails {...args} />
28
+ </BrowserRouter>
29
+ )
30
+
31
+ const Default = Template.bind({})
32
+ Default.args = { skipBody: true }
33
+
34
+ const WithViewSchemaLink = Template.bind({})
35
+ WithViewSchemaLink.args = { viewSchemaUrl: 'http://beta.explore.xyo.network/6fe3f745b1179fefa74cc3c7eab58321bee1c9ca9e34d9585467364cc5d3bbe2/?huri=huri' }
36
+
37
+ const WithErrorsInToolTip = Template.bind({})
38
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
39
+ // @ts-ignore
40
+ WithErrorsInToolTip.args = { value: { ...samplePayload, ...{ _hash: '6fe3f745b1179fefa74cc3c7eab58321bee1c9ca9e34d9585467364cc5d3bbe2' } } }
41
+
42
+ const SkipBody = Template.bind({})
43
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
44
+ // @ts-ignore
45
+ SkipBody.args = { skipBody: true, value: { _hash: '44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a', _timestamp: new Date().getTime() } }
46
+
47
+ const SkipMeta = Template.bind({})
48
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
49
+ // @ts-ignore
50
+ SkipMeta.args = { skipMeta: true, value: { _hash: null, schema: 'network.xyo.schema' } }
51
+
52
+ export { Default, SkipBody, SkipMeta, WithErrorsInToolTip, WithViewSchemaLink }
53
+
54
+ // eslint-disable-next-line import/no-default-export
55
+ export default StorybookEntry
@@ -0,0 +1,42 @@
1
+ import { Typography } from '@mui/material'
2
+ import { FlexCol } from '@xylabs/react-flexbox'
3
+ import { XyoPayloadValidator, XyoPayloadWithMeta } from '@xyo-network/payload'
4
+ import { Property, PropertyGroup } from '@xyo-network/react-property'
5
+ import { SchemaProperty } from '@xyo-network/react-schema'
6
+
7
+ import { PayloadValidationDetailsProps } from './ValidationDetailsProps'
8
+
9
+ export const PayloadValidationDetails: React.FC<PayloadValidationDetailsProps> = ({ viewSchemaUrl, skipBody = false, value, ...props }) => {
10
+ const validator = value ? new XyoPayloadValidator(value as XyoPayloadWithMeta) : undefined
11
+
12
+ const bodyErrors = skipBody ? [] : validator?.body.validate() ?? []
13
+ const errors: Error[] = [...bodyErrors]
14
+
15
+ let elevation = 2
16
+ if (props.paper) {
17
+ elevation += props.elevation ?? 0
18
+ }
19
+
20
+ return (
21
+ <PropertyGroup titleProps={{ elevation }} title="Validation" tip="The results from validating the payload" {...props}>
22
+ <Property
23
+ titleProps={{ elevation }}
24
+ flexGrow={1}
25
+ title="Valid"
26
+ value={errors.length === 0 ? 'True' : 'False'}
27
+ tip={
28
+ errors.length > 0 ? (
29
+ <FlexCol>
30
+ {errors.map((error, index) => {
31
+ return <Typography key={index}>{error.toString()}</Typography>
32
+ })}
33
+ </FlexCol>
34
+ ) : (
35
+ <Typography>No Errors</Typography>
36
+ )
37
+ }
38
+ />
39
+ {value?.schema && <SchemaProperty flexGrow={1} titleProps={{ elevation }} value={value.schema} viewSchemaUrl={viewSchemaUrl} />}
40
+ </PropertyGroup>
41
+ )
42
+ }
@@ -0,0 +1,8 @@
1
+ import { XyoPayloadWithPartialMeta } from '@xyo-network/payload'
2
+ import { PropertyGroupProps } from '@xyo-network/react-property'
3
+
4
+ export type PayloadValidationDetailsProps = PropertyGroupProps & {
5
+ skipBody?: boolean
6
+ value?: XyoPayloadWithPartialMeta
7
+ viewSchemaUrl?: string
8
+ }
@@ -0,0 +1,2 @@
1
+ export * from './ValidationDetails'
2
+ export * from './ValidationDetailsProps'
@@ -0,0 +1,5 @@
1
+ export * from './DataDetails'
2
+ export * from './Details'
3
+ export * from './JsonDetails'
4
+ export * from './MetaDetails'
5
+ export * from './ValidationDetails'
@@ -0,0 +1,28 @@
1
+ export type PayloadTableColumnSlug = 'hash' | 'archive' | 'client' | 'date' | 'time' | 'schema' | 'valid'
2
+
3
+ export interface PayloadTableColumnConfig {
4
+ xs?: PayloadTableColumnSlug[]
5
+ sm?: PayloadTableColumnSlug[]
6
+ md?: PayloadTableColumnSlug[]
7
+ lg?: PayloadTableColumnSlug[]
8
+ xl?: PayloadTableColumnSlug[]
9
+ }
10
+
11
+ export const payloadColumnNames: Record<PayloadTableColumnSlug, string> = {
12
+ archive: 'Archive',
13
+ client: 'Client',
14
+ date: 'Date',
15
+ hash: 'Hash',
16
+ schema: 'Schema',
17
+ time: 'Time',
18
+ valid: 'Valid',
19
+ }
20
+
21
+ export const payloadTableColumnConfigDefaults = (): PayloadTableColumnConfig => {
22
+ const xs: PayloadTableColumnSlug[] = ['hash', 'time', 'valid']
23
+ const sm: PayloadTableColumnSlug[] = ['hash', 'time', 'archive', 'valid']
24
+ const md: PayloadTableColumnSlug[] = ['hash', 'schema', 'archive', 'time', 'valid']
25
+ const lg: PayloadTableColumnSlug[] = ['hash', 'schema', 'archive', 'date', 'time', 'valid']
26
+ const xl: PayloadTableColumnSlug[] = ['hash', 'schema', 'archive', 'client', 'date', 'time', 'valid']
27
+ return { lg, md, sm, xl, xs }
28
+ }
@@ -0,0 +1,43 @@
1
+ import { ComponentMeta, ComponentStory } from '@storybook/react'
2
+ import { BrowserRouter } from 'react-router-dom'
3
+
4
+ import { appThemeDecorator, samplePayload } from '../../../../../.storybook'
5
+ import { PayloadTable } from './Table'
6
+
7
+ const StorybookEntry = {
8
+ argTypes: {},
9
+ component: PayloadTable,
10
+ parameters: {
11
+ docs: {
12
+ page: null,
13
+ },
14
+ },
15
+ title: 'payload/Table',
16
+ } as ComponentMeta<typeof PayloadTable>
17
+
18
+ const Template: ComponentStory<typeof PayloadTable> = (args) => (
19
+ <BrowserRouter>
20
+ <PayloadTable {...args}></PayloadTable>
21
+ </BrowserRouter>
22
+ )
23
+
24
+ const Default = Template.bind({})
25
+ Default.args = {}
26
+ Default.decorators = [appThemeDecorator]
27
+
28
+ const WithData = Template.bind({})
29
+ WithData.args = { payloads: [samplePayload, samplePayload] }
30
+ WithData.decorators = [appThemeDecorator]
31
+
32
+ const WithError = Template.bind({})
33
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
34
+ const { _hash, ...badPayload } = samplePayload
35
+
36
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
37
+ //@ts-ignore
38
+ WithError.args = { payloads: [samplePayload, badPayload] }
39
+
40
+ export { Default, WithData, WithError }
41
+
42
+ // eslint-disable-next-line import/no-default-export
43
+ export default StorybookEntry
@@ -0,0 +1,60 @@
1
+ import { Alert, Table, TableBody, TableCell, TableHead, TableProps, TableRow, Typography } from '@mui/material'
2
+ import { useBreakpoint } from '@xylabs/react-shared'
3
+ import { XyoPayload, XyoPayloadWithPartialMeta } from '@xyo-network/payload'
4
+ import { XyoApiThrownErrorBoundary } from '@xyo-network/react-auth-service'
5
+
6
+ import { payloadColumnNames, PayloadTableColumnConfig, payloadTableColumnConfigDefaults } from './PayloadTableColumnConfig'
7
+ import { PayloadTableRow } from './TableRow'
8
+
9
+ export interface PayloadTableProps extends TableProps {
10
+ exploreDomain?: string
11
+ onRowClick?: (value: XyoPayload) => void
12
+ payloads?: XyoPayloadWithPartialMeta[] | null
13
+ columns?: PayloadTableColumnConfig
14
+ }
15
+
16
+ export const PayloadTable: React.FC<PayloadTableProps> = ({ exploreDomain, onRowClick, payloads, children, columns = payloadTableColumnConfigDefaults(), ...props }) => {
17
+ const breakPoint = useBreakpoint()
18
+ return breakPoint ? (
19
+ <Table {...props}>
20
+ <TableHead>
21
+ <TableRow>
22
+ {columns[breakPoint]?.map((column, index) => {
23
+ return (
24
+ <TableCell key={index} width={index === 0 ? '100%' : undefined} align={index === 0 ? 'left' : 'center'}>
25
+ <Typography variant="caption" noWrap>
26
+ <strong>{payloadColumnNames[column]}</strong>
27
+ </Typography>
28
+ </TableCell>
29
+ )
30
+ })}
31
+ </TableRow>
32
+ </TableHead>
33
+ <TableBody>
34
+ {payloads?.map((payload, index) => (
35
+ <XyoApiThrownErrorBoundary
36
+ key={`${payload._hash}-${payload._timestamp}-${index}`}
37
+ errorComponent={(e) => (
38
+ <Alert severity="error">
39
+ Error Loading Payload: <Typography fontWeight="bold">{e.message}</Typography>
40
+ </Alert>
41
+ )}
42
+ >
43
+ <PayloadTableRow
44
+ onClick={
45
+ onRowClick
46
+ ? () => {
47
+ onRowClick(payload)
48
+ }
49
+ : undefined
50
+ }
51
+ exploreDomain={exploreDomain}
52
+ payload={payload}
53
+ />
54
+ </XyoApiThrownErrorBoundary>
55
+ ))}
56
+ {children}
57
+ </TableBody>
58
+ </Table>
59
+ ) : null
60
+ }