@graphcommerce/graphcms-ui 2.106.39 → 3.0.2

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.
@@ -0,0 +1,92 @@
1
+ import { SxProps, Theme } from '@mui/material'
2
+ import { LiteralUnion } from 'type-fest'
3
+
4
+ type BaseElementTypes =
5
+ | 'heading-one'
6
+ | 'heading-two'
7
+ | 'heading-three'
8
+ | 'heading-four'
9
+ | 'heading-five'
10
+ | 'heading-six'
11
+ | 'paragraph'
12
+ | 'numbered-list'
13
+ | 'bulleted-list'
14
+ | 'block-quote'
15
+ | 'paragraph'
16
+ | 'list-item'
17
+ | 'list-item-child'
18
+ | 'table'
19
+ | 'table_head'
20
+ | 'table_header_cell'
21
+ | 'table_body'
22
+ | 'table_row'
23
+ | 'table_cell'
24
+ | 'code'
25
+
26
+ type SimpleElement = {
27
+ children: ElementOrTextNode[]
28
+ type: LiteralUnion<BaseElementTypes, string>
29
+ }
30
+
31
+ export type TextNode = {
32
+ text: string
33
+ bold?: true
34
+ italic?: true
35
+ underlined?: true
36
+ [key: string]: unknown
37
+ }
38
+
39
+ type LinkElement = {
40
+ type: 'link'
41
+ children: ElementOrTextNode[]
42
+ href: string
43
+ }
44
+
45
+ type ImageElement = {
46
+ type: 'image'
47
+ children: ElementOrTextNode[]
48
+ src: string
49
+ title: string
50
+ width: number
51
+ height: number
52
+ mimeType: string
53
+ }
54
+
55
+ type VideoElement = {
56
+ type: 'image'
57
+ children: ElementOrTextNode[]
58
+ src: string
59
+ title: string
60
+ width: number
61
+ height: number
62
+ mimeType: string
63
+ }
64
+
65
+ type IframeElement = {
66
+ type: 'iframe'
67
+ children: ElementOrTextNode[]
68
+ src: string
69
+ }
70
+
71
+ export type ElementNode = SimpleElement | LinkElement | ImageElement | VideoElement | IframeElement
72
+ export type ElementOrTextNode = ElementNode | TextNode
73
+
74
+ type RendererBase = { sx?: SxProps<Theme>; children?: React.ReactNode }
75
+ type Renderer<P extends ElementNode> = (
76
+ props: Omit<P, 'children'> & RendererBase,
77
+ ) => React.ReactElement | null
78
+
79
+ export type Renderers = {
80
+ [k in BaseElementTypes]: Renderer<SimpleElement>
81
+ } & {
82
+ link: Renderer<LinkElement>
83
+ image: Renderer<ImageElement>
84
+ video: Renderer<VideoElement>
85
+ iframe: Renderer<IframeElement>
86
+ }
87
+
88
+ export type SxRenderer = {
89
+ [k in keyof Renderers | 'all']?: SxProps<Theme>
90
+ }
91
+
92
+ export type AdditionalProps = { renderers: Renderers; sxRenderer: SxRenderer }
package/index.ts CHANGED
@@ -1 +1,2 @@
1
- export {}
1
+ export * from './components/RichText'
2
+ export * from './components/Asset'
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "@graphcommerce/graphcms-ui",
3
- "version": "2.106.39",
3
+ "homepage": "https://www.graphcommerce.org/",
4
+ "repository": "github:graphcommerce-org/graphcommerce",
5
+ "version": "3.0.2",
4
6
  "sideEffects": false,
5
7
  "prettier": "@graphcommerce/prettier-config-pwa",
6
- "browserslist": [
7
- "extends @graphcommerce/browserslist-config-pwa"
8
- ],
9
8
  "eslintConfig": {
10
9
  "extends": "@graphcommerce/eslint-config-pwa",
11
10
  "parserOptions": {
@@ -13,22 +12,21 @@
13
12
  }
14
13
  },
15
14
  "devDependencies": {
16
- "@graphcommerce/browserslist-config-pwa": "^3.0.3",
17
- "@graphcommerce/eslint-config-pwa": "^3.1.10",
18
- "@graphcommerce/prettier-config-pwa": "^3.0.5",
19
- "@graphcommerce/typescript-config-pwa": "^3.1.2",
20
- "@playwright/test": "^1.17.1"
15
+ "@graphcommerce/eslint-config-pwa": "^4.0.2",
16
+ "@graphcommerce/prettier-config-pwa": "^4.0.1",
17
+ "@graphcommerce/typescript-config-pwa": "^4.0.1",
18
+ "@playwright/test": "^1.19.1"
21
19
  },
22
20
  "dependencies": {
23
- "@apollo/client": "^3.5.6",
24
- "@graphcommerce/image": "^2.105.13",
25
- "@graphcommerce/next-ui": "^3.25.3",
26
- "@material-ui/core": "^4.12.3",
27
- "@material-ui/lab": "^4.0.0-alpha.60",
28
- "next": "^12.0.7",
29
- "react": "^17.0.2",
30
- "react-dom": "^17.0.2",
31
- "type-fest": "^2.8.0"
21
+ "@graphcommerce/graphql": "^3.0.2",
22
+ "@graphcommerce/image": "^3.0.2",
23
+ "@graphcommerce/next-ui": "^4.1.1",
24
+ "type-fest": "^2.11.2"
32
25
  },
33
- "gitHead": "41e42c8cd6f565ab0cbba81a1954a0041dc46768"
26
+ "peerDependencies": {
27
+ "@mui/material": "^5.4.1",
28
+ "next": "^12.0.10",
29
+ "react": "^17.0.2",
30
+ "react-dom": "^17.0.2"
31
+ }
34
32
  }
@@ -1,22 +0,0 @@
1
- import { UseStyles } from '@graphcommerce/next-ui'
2
- import { makeStyles, Theme } from '@material-ui/core'
3
- import React from 'react'
4
- import RichText, { RichTextProps } from '.'
5
-
6
- type StyleProps = { columnCount: number }
7
-
8
- const useStyles = makeStyles(({ spacings, breakpoints }: Theme) => ({
9
- paragraph: {
10
- [breakpoints.up('md')]: {
11
- columnCount: ({ columnCount }: StyleProps) => columnCount,
12
- columnGap: spacings.md,
13
- },
14
- },
15
- }))
16
-
17
- type RichTextColumnsProps = UseStyles<typeof useStyles> & StyleProps & RichTextProps
18
-
19
- export default function RichTextColumns(props: RichTextColumnsProps) {
20
- const classes = useStyles(props)
21
- return <RichText classes={classes} {...props} />
22
- }
@@ -1,18 +0,0 @@
1
- import { withStyles, Theme } from '@material-ui/core'
2
- import RichText from '.'
3
-
4
- const RichTextDoubleSpread = withStyles((theme: Theme) => ({
5
- h2: theme.typography.h4,
6
- paragraph: {
7
- [theme.breakpoints.up('sm')]: {
8
- columnCount: 2,
9
- columnGap: theme.spacings.md,
10
- },
11
- [theme.breakpoints.up('lg')]: {
12
- columnCount: 3,
13
- columnGap: theme.spacings.md,
14
- },
15
- },
16
- }))(RichText)
17
-
18
- export default RichTextDoubleSpread
@@ -1,22 +0,0 @@
1
- import { breakpointVal } from '@graphcommerce/next-ui'
2
- import { Theme, withStyles } from '@material-ui/core'
3
- import RichText from '.'
4
-
5
- const RichTextHeadingStrongStroked = withStyles((theme: Theme) => ({
6
- h2: {
7
- ...theme.typography.h1,
8
- textTransform: 'uppercase',
9
- color: theme.palette.text.primary,
10
- [theme.breakpoints.up('sm')]: {
11
- ...breakpointVal('fontSize', 36, 82, theme.breakpoints.values),
12
- },
13
- '& strong': {
14
- // https://github.com/rsms/inter/issues/292#issuecomment-674993644
15
- color: theme.palette.background.default,
16
- textShadow: `1.2px 0 0 ${theme.palette.text.primary},0 1.2px 0 ${theme.palette.text.primary},-1.2px 0 0 ${theme.palette.text.primary},0 -1.2px 0 ${theme.palette.text.primary}`,
17
- },
18
- [theme.breakpoints.up('md')]: {},
19
- },
20
- }))(RichText)
21
-
22
- export default RichTextHeadingStrongStroked
@@ -1,27 +0,0 @@
1
- import { breakpointVal } from '@graphcommerce/next-ui'
2
- import { Theme, withStyles } from '@material-ui/core'
3
- import RichText from '.'
4
-
5
- const RichTextHero = withStyles((theme: Theme) => ({
6
- h1: {
7
- ...theme.typography.h1,
8
- textTransform: 'uppercase',
9
- maxWidth: '70%',
10
- textAlign: 'center',
11
- margin: 0,
12
- marginBottom: theme.spacings.md,
13
- [theme.breakpoints.up('sm')]: {
14
- ...breakpointVal('fontSize', 36, 82, theme.breakpoints.values),
15
- },
16
- [theme.breakpoints.up('md')]: {
17
- textAlign: 'left',
18
- maxWidth: '100%',
19
- },
20
- '& strong': {
21
- WebkitTextFillColor: 'transparent',
22
- WebkitTextStroke: `1.2px #fff`,
23
- },
24
- },
25
- }))(RichText)
26
-
27
- export default RichTextHero
@@ -1,23 +0,0 @@
1
- import { Theme, withStyles } from '@material-ui/core'
2
- import RichText from '.'
3
-
4
- const RichTextParagraphStrongStroked = withStyles((theme: Theme) => ({
5
- paragraph: {
6
- ...theme.typography.body2,
7
- textTransform: 'uppercase',
8
- maxWidth: '100%',
9
- fontWeight: 600,
10
- textAlign: 'left',
11
- [theme.breakpoints.up('md')]: {
12
- ...theme.typography.h3,
13
- fontWeight: 600,
14
- maxWidth: '100%',
15
- },
16
- '& strong': {
17
- color: 'transparent',
18
- WebkitTextStroke: '1.2px #fff',
19
- },
20
- },
21
- }))(RichText)
22
-
23
- export default RichTextParagraphStrongStroked
@@ -1,21 +0,0 @@
1
- import { Theme, withStyles } from '@material-ui/core'
2
- import RichText from '.'
3
-
4
- const RichTextQuote = withStyles((theme: Theme) => ({
5
- paragraph: {
6
- ...theme.typography.h4,
7
- fontWeight: 600,
8
- '@supports (font-variation-settings: normal)': {
9
- fontVariationSettings: "'wght' 620",
10
- },
11
- textTransform: 'uppercase',
12
- maxWidth: '60%',
13
- textAlign: 'center',
14
- margin: '0 auto',
15
- [theme.breakpoints.up('lg')]: {
16
- maxWidth: '80%',
17
- },
18
- },
19
- }))(RichText)
20
-
21
- export default RichTextQuote
@@ -1,14 +0,0 @@
1
- import { withStyles, Theme } from '@material-ui/core'
2
- import RichText from '.'
3
-
4
- const RichTextSpread = withStyles((theme: Theme) => ({
5
- h2: theme.typography.h4,
6
- paragraph: {
7
- [theme.breakpoints.up('md')]: {
8
- columnCount: 2,
9
- columnGap: theme.spacings.md,
10
- },
11
- },
12
- }))(RichText)
13
-
14
- export default RichTextSpread
@@ -1,325 +0,0 @@
1
- import { Image } from '@graphcommerce/image'
2
- import { Link, Typography } from '@material-ui/core'
3
- import PageLink from 'next/link'
4
- import React from 'react'
5
- import useRichTextStyles, { UseRichTextStyles } from './useRichTextStyles'
6
-
7
- export interface Element {
8
- children: Node[]
9
- type:
10
- | 'heading-one'
11
- | 'heading-two'
12
- | 'heading-three'
13
- | 'heading-four'
14
- | 'heading-five'
15
- | 'heading-six'
16
- | 'paragraph'
17
- | 'numbered-list'
18
- | 'bulleted-list'
19
- | 'block-quote'
20
- | 'paragraph'
21
- | 'list-item'
22
- | 'list-item-child'
23
- | 'table'
24
- | 'table_head'
25
- | 'table_header_cell'
26
- | 'table_body'
27
- | 'table_row'
28
- | 'table_cell'
29
- | string
30
- [key: string]: unknown
31
- }
32
-
33
- export interface Text {
34
- text: string
35
- bold?: true
36
- italic?: true
37
- underlined?: true
38
- [key: string]: unknown
39
- }
40
-
41
- interface LinkElement extends Element {
42
- type: 'link'
43
- href: string
44
- }
45
-
46
- interface ImageElement extends Element {
47
- type: 'image'
48
- src: string
49
- title: string
50
- width: number
51
- height: number
52
- mimeType: string
53
- }
54
-
55
- interface VideoElement extends Element {
56
- type: 'image'
57
- src: string
58
- title: string
59
- width: number
60
- height: number
61
- mimeType: string
62
- }
63
-
64
- interface LinkElement extends Element {
65
- type: 'link'
66
- href: string
67
- }
68
-
69
- interface IframeElement extends Element {
70
- type: 'iframe'
71
- src: string
72
- }
73
-
74
- export type ElementNode =
75
- | Element
76
- | LinkElement
77
- | ImageElement
78
- | VideoElement
79
- | IframeElement
80
- | LinkElement
81
-
82
- export type Node = ElementNode | Text
83
-
84
- const RenderText = ({ classes, text, ...textProps }: Text & Required<UseRichTextStyles>) => {
85
- let result = <>{text}</>
86
- if (textProps.bold) result = <strong>{result}</strong>
87
- if (textProps.italic) result = <em>{result}</em>
88
- if (textProps.underlined) result = <em>{result}</em>
89
-
90
- return result
91
- }
92
-
93
- export function isTextNode(node: Node): node is Text {
94
- return (node as Text).text !== undefined
95
- }
96
-
97
- export function isElementNode(node: Node): node is ElementNode {
98
- return (node as ElementNode).children !== undefined
99
- }
100
-
101
- function RenderNode({ classes, ...node }: Node & Required<UseRichTextStyles>) {
102
- if (isTextNode(node)) {
103
- return <RenderText {...node} classes={classes} />
104
- }
105
- if (isElementNode(node)) {
106
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
107
- return <RenderElement {...node} classes={classes} />
108
- }
109
-
110
- console.error(node)
111
- throw Error(`RichText: Node not recognized`)
112
- }
113
-
114
- function RenderChildren({ children, classes }: { children: Node[] } & Required<UseRichTextStyles>) {
115
- return (
116
- <>
117
- {children.map((node, key) => (
118
- // Since we don't know any unique identifiers of the element and since this doesn't rerender often this is fine.
119
- // eslint-disable-next-line react/no-array-index-key
120
- <RenderNode {...node} key={key} classes={classes} />
121
- ))}
122
- </>
123
- )
124
- }
125
-
126
- function RenderElement({ classes, ...element }: ElementNode & Required<UseRichTextStyles>) {
127
- const {
128
- root,
129
- asset,
130
- h1,
131
- h2,
132
- h3,
133
- h4,
134
- h5,
135
- h6,
136
- paragraph,
137
- ul,
138
- ol,
139
- blockQuote,
140
- code,
141
- iframe,
142
- aspectContainer,
143
- table,
144
- link,
145
- } = classes
146
-
147
- switch (element.type) {
148
- case 'heading-one':
149
- return (
150
- <Typography variant='h1' classes={{ root, h1 }}>
151
- <RenderChildren {...element} classes={classes} />
152
- </Typography>
153
- )
154
- case 'heading-two':
155
- return (
156
- <Typography variant='h2' classes={{ root, h2 }}>
157
- <RenderChildren {...element} classes={classes} />
158
- </Typography>
159
- )
160
- case 'heading-three':
161
- return (
162
- <Typography variant='h3' classes={{ root, h3 }}>
163
- <RenderChildren {...element} classes={classes} />
164
- </Typography>
165
- )
166
- case 'heading-four':
167
- return (
168
- <Typography variant='h4' classes={{ root, h4 }}>
169
- <RenderChildren {...element} classes={classes} />
170
- </Typography>
171
- )
172
- case 'heading-five':
173
- return (
174
- <Typography variant='h5' classes={{ root, h5 }}>
175
- <RenderChildren {...element} classes={classes} />
176
- </Typography>
177
- )
178
- case 'heading-six':
179
- return (
180
- <Typography variant='h6' classes={{ root, h6 }}>
181
- <RenderChildren {...element} classes={classes} />
182
- </Typography>
183
- )
184
- case 'paragraph':
185
- return element.children[0].code ? (
186
- <pre className={classes.code}>
187
- <code>
188
- <RenderChildren {...element} classes={classes} />
189
- </code>
190
- </pre>
191
- ) : (
192
- <Typography variant='body1' paragraph classes={{ root, paragraph }}>
193
- <RenderChildren {...element} classes={classes} />
194
- </Typography>
195
- )
196
-
197
- case 'bulleted-list':
198
- return (
199
- <Typography component='ul' classes={{ root: ul }}>
200
- <RenderChildren {...element} classes={classes} />
201
- </Typography>
202
- )
203
- case 'numbered-list':
204
- return (
205
- <Typography component='ol' classes={{ root: ol }}>
206
- <RenderChildren {...element} classes={classes} />
207
- </Typography>
208
- )
209
- case 'list-item':
210
- return (
211
- <li>
212
- <RenderChildren {...element} classes={classes} />
213
- </li>
214
- )
215
- case 'list-item-child':
216
- return <RenderChildren {...element} classes={classes} />
217
- case 'block-quote':
218
- return (
219
- <Typography component='blockquote' classes={{ root: blockQuote }}>
220
- <RenderChildren {...element} classes={classes} />
221
- </Typography>
222
- )
223
- case 'iframe':
224
- // eslint-disable-next-line no-case-declarations
225
- const iframeElement = element as IframeElement
226
- // todo(paales) add security attributes to iframe
227
- // todo(paales) make iframe responsive
228
- return (
229
- <div className={aspectContainer}>
230
- <iframe
231
- src={iframeElement.src}
232
- title='embedded content'
233
- className={iframe}
234
- loading='lazy'
235
- />
236
- </div>
237
- )
238
- case 'image':
239
- // eslint-disable-next-line no-case-declarations
240
- const imageElement = element as ImageElement
241
- return (
242
- <Image
243
- src={imageElement.src}
244
- width={imageElement.width}
245
- height={imageElement.height}
246
- alt={imageElement.title}
247
- className={asset}
248
- />
249
- )
250
- case 'video':
251
- // eslint-disable-next-line no-case-declarations
252
- const videoElement = element as VideoElement
253
- return (
254
- <div>IMPLEMENT VIDEO</div>
255
- // <Asset
256
- // asset={{ url: videoElement.src, mimeType: videoElement.mimeType }}
257
- // autoPlay
258
- // loop
259
- // muted
260
- // playsInline
261
- // width={380}
262
- // className={asset}
263
- // />
264
- )
265
- case 'link':
266
- // eslint-disable-next-line no-case-declarations
267
- const linkElement = element as LinkElement
268
- return (
269
- <PageLink href={linkElement.href} passHref>
270
- <Link classes={{ root: link }}>
271
- <RenderChildren {...element} classes={classes} />
272
- </Link>
273
- </PageLink>
274
- )
275
- case 'table':
276
- return (
277
- <table className={table}>
278
- <RenderChildren {...element} classes={classes} />
279
- </table>
280
- )
281
- case 'table_head':
282
- return (
283
- <thead>
284
- <RenderChildren {...element} classes={classes} />
285
- </thead>
286
- )
287
- case 'table_header_cell':
288
- return (
289
- <th>
290
- <RenderChildren {...element} classes={classes} />
291
- </th>
292
- )
293
- case 'table_body':
294
- return (
295
- <tbody>
296
- <RenderChildren {...element} classes={classes} />
297
- </tbody>
298
- )
299
- case 'table_row':
300
- return (
301
- <tr>
302
- <RenderChildren {...element} classes={classes} />
303
- </tr>
304
- )
305
- case 'table_cell':
306
- return (
307
- <td>
308
- <RenderChildren {...element} classes={classes} />
309
- </td>
310
- )
311
- default:
312
- if (process.env.NODE_ENV !== 'production') {
313
- console.error(element)
314
- throw Error(`RichText: Unknown Element: ${element.type}`)
315
- }
316
- return <RenderChildren {...element} classes={classes} />
317
- }
318
- }
319
-
320
- export type RichTextProps = { raw: ElementNode } & UseRichTextStyles
321
-
322
- export default function RichText({ raw, ...props }: RichTextProps) {
323
- const classes = useRichTextStyles(props)
324
- return <RenderChildren classes={classes} {...raw} />
325
- }