@graphcommerce/hygraph-dynamic-rows-ui 8.1.0-canary.8 → 9.0.0-canary.100

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/CHANGELOG.md CHANGED
@@ -1,5 +1,205 @@
1
1
  # @graphcommerce/hygraph-dynamic-rows-ui
2
2
 
3
+ ## 9.0.0-canary.100
4
+
5
+ ## 9.0.0-canary.99
6
+
7
+ ## 9.0.0-canary.98
8
+
9
+ ## 9.0.0-canary.97
10
+
11
+ ### Patch Changes
12
+
13
+ - [#2410](https://github.com/graphcommerce-org/graphcommerce/pull/2410) [`2a425b3`](https://github.com/graphcommerce-org/graphcommerce/commit/2a425b323ddaf0918c549e93b598888db7328d66) - Allow attributes with deprecationReasons (e.g. custom attributes) as PropertyPicker value ([@carlocarels90](https://github.com/carlocarels90))
14
+
15
+ ## 9.0.0-canary.96
16
+
17
+ ## 9.0.0-canary.95
18
+
19
+ ## 9.0.0-canary.94
20
+
21
+ ## 9.0.0-canary.93
22
+
23
+ ## 9.0.0-canary.92
24
+
25
+ ## 9.0.0-canary.91
26
+
27
+ ## 9.0.0-canary.90
28
+
29
+ ## 9.0.0-canary.89
30
+
31
+ ## 9.0.0-canary.88
32
+
33
+ ## 9.0.0-canary.87
34
+
35
+ ## 9.0.0-canary.86
36
+
37
+ ## 9.0.0-canary.85
38
+
39
+ ## 9.0.0-canary.84
40
+
41
+ ## 9.0.0-canary.83
42
+
43
+ ## 9.0.0-canary.82
44
+
45
+ ## 9.0.0-canary.81
46
+
47
+ ## 9.0.0-canary.80
48
+
49
+ ## 9.0.0-canary.79
50
+
51
+ ## 9.0.0-canary.78
52
+
53
+ ## 9.0.0-canary.77
54
+
55
+ ## 9.0.0-canary.76
56
+
57
+ ## 9.0.0-canary.75
58
+
59
+ ## 9.0.0-canary.74
60
+
61
+ ## 9.0.0-canary.73
62
+
63
+ ## 9.0.0-canary.72
64
+
65
+ ## 9.0.0-canary.71
66
+
67
+ ## 9.0.0-canary.70
68
+
69
+ ### Patch Changes
70
+
71
+ - [#2347](https://github.com/graphcommerce-org/graphcommerce/pull/2347) [`7fa50a2`](https://github.com/graphcommerce-org/graphcommerce/commit/7fa50a2f21ee9edbc67d06d7694316f101f9415f) - Resolve issue where the dynamic rows UI wouldn’t load any definitions ([@paales](https://github.com/paales))
72
+
73
+ ## 9.0.0-canary.69
74
+
75
+ ## 9.0.0-canary.68
76
+
77
+ ## 9.0.0-canary.67
78
+
79
+ ## 9.0.0-canary.66
80
+
81
+ ## 9.0.0-canary.65
82
+
83
+ ## 9.0.0-canary.64
84
+
85
+ ## 9.0.0-canary.63
86
+
87
+ ## 9.0.0-canary.62
88
+
89
+ ## 9.0.0-canary.61
90
+
91
+ ## 9.0.0-canary.60
92
+
93
+ ## 9.0.0-canary.59
94
+
95
+ ## 9.0.0-canary.58
96
+
97
+ ## 9.0.0-canary.57
98
+
99
+ ## 9.0.0-canary.56
100
+
101
+ ## 9.0.0-canary.55
102
+
103
+ ## 9.0.0-canary.54
104
+
105
+ ## 8.1.0-canary.53
106
+
107
+ ## 8.1.0-canary.52
108
+
109
+ ## 8.1.0-canary.51
110
+
111
+ ## 8.1.0-canary.50
112
+
113
+ ## 8.1.0-canary.49
114
+
115
+ ## 8.1.0-canary.48
116
+
117
+ ## 8.1.0-canary.47
118
+
119
+ ## 8.1.0-canary.46
120
+
121
+ ### Patch Changes
122
+
123
+ - [#2316](https://github.com/graphcommerce-org/graphcommerce/pull/2316) [`28d4708`](https://github.com/graphcommerce-org/graphcommerce/commit/28d470861a10a38690d565d236ce573905038d2b) - fix hygraph studio bugs in Dynamic Row UI module. Style config screen DR UI app. ([@JoshuaS98](https://github.com/JoshuaS98))
124
+
125
+ ## 8.1.0-canary.45
126
+
127
+ ## 8.1.0-canary.44
128
+
129
+ ## 8.1.0-canary.43
130
+
131
+ ## 8.1.0-canary.42
132
+
133
+ ### Patch Changes
134
+
135
+ - [#2308](https://github.com/graphcommerce-org/graphcommerce/pull/2308) [`8faa5ac`](https://github.com/graphcommerce-org/graphcommerce/commit/8faa5ac618ecfdacd6d5eb751b4110c423aef97f) - Added Draft Mode support. When enabled it will be shown. ([@paales](https://github.com/paales))
136
+
137
+ ## 8.1.0-canary.41
138
+
139
+ ## 8.1.0-canary.40
140
+
141
+ ## 8.1.0-canary.39
142
+
143
+ ## 8.1.0-canary.38
144
+
145
+ ## 8.1.0-canary.37
146
+
147
+ ## 8.1.0-canary.36
148
+
149
+ ## 8.1.0-canary.35
150
+
151
+ ## 8.1.0-canary.34
152
+
153
+ ## 8.1.0-canary.33
154
+
155
+ ## 8.1.0-canary.32
156
+
157
+ ## 8.1.0-canary.31
158
+
159
+ ## 8.1.0-canary.30
160
+
161
+ ## 8.1.0-canary.29
162
+
163
+ ## 8.1.0-canary.28
164
+
165
+ ## 8.1.0-canary.27
166
+
167
+ ## 8.1.0-canary.26
168
+
169
+ ## 8.1.0-canary.25
170
+
171
+ ## 8.1.0-canary.24
172
+
173
+ ## 8.1.0-canary.23
174
+
175
+ ## 8.1.0-canary.22
176
+
177
+ ## 8.1.0-canary.21
178
+
179
+ ## 8.1.0-canary.20
180
+
181
+ ## 8.1.0-canary.19
182
+
183
+ ## 8.1.0-canary.18
184
+
185
+ ## 8.1.0-canary.17
186
+
187
+ ## 8.1.0-canary.16
188
+
189
+ ## 8.1.0-canary.15
190
+
191
+ ## 8.1.0-canary.14
192
+
193
+ ## 8.1.0-canary.13
194
+
195
+ ## 8.1.0-canary.12
196
+
197
+ ## 8.1.0-canary.11
198
+
199
+ ## 8.1.0-canary.10
200
+
201
+ ## 8.1.0-canary.9
202
+
3
203
  ## 8.1.0-canary.8
4
204
 
5
205
  ## 8.1.0-canary.7
@@ -90,8 +290,7 @@
90
290
 
91
291
  ### Minor Changes
92
292
 
93
- - [#2100](https://github.com/graphcommerce-org/graphcommerce/pull/2100) [`4df891a`](https://github.com/graphcommerce-org/graphcommerce/commit/4df891a4c18b29cc52447eab3a97c66948b6c18f) - Add Dynamic Row UI for property UI field through a custom Hygraph application
94
- ([@JoshuaS98](https://github.com/JoshuaS98))
293
+ - [#2100](https://github.com/graphcommerce-org/graphcommerce/pull/2100) [`4df891a`](https://github.com/graphcommerce-org/graphcommerce/commit/4df891a4c18b29cc52447eab3a97c66948b6c18f) - Add Dynamic Row UI for property UI field through a custom Hygraph application ([@JoshuaS98](https://github.com/JoshuaS98))
95
294
 
96
295
  ## 8.0.0-canary.100
97
296
 
@@ -1,91 +1,59 @@
1
- import { ApolloClient, InMemoryCache } from '@apollo/client'
2
- import { useFieldExtension } from '@hygraph/app-sdk-react'
3
- // eslint-disable-next-line @typescript-eslint/no-restricted-imports
1
+ import { ApolloClient, gql, InMemoryCache, useQuery } from '@apollo/client'
2
+ import { FieldExtensionProps, useFieldExtension } from '@hygraph/app-sdk-react'
4
3
  import { TextField } from '@mui/material'
4
+ import { getIntrospectionQuery, IntrospectionQuery } from 'graphql'
5
5
  import { useEffect, useMemo, useState } from 'react'
6
- import { createOptionsFromInterfaceObject, objectifyGraphQLInterface } from '../lib'
7
- import { fetchGraphQLInterface } from '../lib/fetchGraphQLInterface'
8
- import { __Field } from '../types'
6
+ import { getFieldPaths } from '../lib/getFieldPaths'
7
+
8
+ function useClient(extension: FieldExtensionProps['extension']) {
9
+ return useMemo(
10
+ () =>
11
+ new ApolloClient({
12
+ uri:
13
+ typeof extension.config.backend === 'string'
14
+ ? extension.config.backend
15
+ : 'https://graphcommerce.vercel.app/api/graphql', // fallback on the standard GraphCommerce Schema
16
+ cache: new InMemoryCache(),
17
+ }),
18
+ [extension.config.backend],
19
+ )
20
+ }
9
21
 
10
22
  export function PropertyPicker() {
11
- const { value, onChange, field, extension } = useFieldExtension()
23
+ const fieldExtension = useFieldExtension()
24
+
25
+ const { value, onChange, extension } = fieldExtension
12
26
  const [localValue, setLocalValue] = useState<string | undefined | null>(
13
27
  typeof value === 'string' ? value : undefined,
14
28
  )
15
- const [fields, setFields] = useState<__Field[] | null>(null)
29
+
30
+ const client = useClient(extension)
31
+ const { data, loading, error } = useQuery<IntrospectionQuery>(gql(getIntrospectionQuery()), {
32
+ client,
33
+ })
34
+ // eslint-disable-next-line no-underscore-dangle
35
+ const schema = data?.__schema
16
36
 
17
37
  useEffect(() => {
18
38
  onChange(localValue).catch((err) => err)
19
39
  }, [localValue, onChange])
20
40
 
21
- const graphQLInterfaceQuery = useMemo(() => {
22
- const client = new ApolloClient({
23
- uri:
24
- typeof extension.config.backend === 'string'
25
- ? extension.config.backend
26
- : 'https://graphcommerce.vercel.app/api/graphql', // fallback on the standard GraphCommerce Schema
27
- cache: new InMemoryCache(),
28
- })
29
- return fetchGraphQLInterface(client)
30
- }, [extension.config.backend])
31
-
32
- // Prepare options
33
- const numberOptions = useMemo(
34
- () =>
35
- createOptionsFromInterfaceObject(
36
- objectifyGraphQLInterface(fields, 'number', ['ProductInterface']),
37
- ),
38
- [fields],
39
- )
40
- const textOptions = useMemo(
41
- () =>
42
- createOptionsFromInterfaceObject(
43
- objectifyGraphQLInterface(fields, 'text', ['ProductInterface']),
44
- ),
45
- [fields],
46
- )
47
- const allOptions = useMemo(
48
- () => ({
49
- text: [...textOptions, { label: 'url', id: 'url' }].sort((a, b) => {
50
- if (!a.label.includes('.') && !b.label.includes('.')) {
51
- return a.label.localeCompare(b.label)
52
- }
53
- if (a.label.includes('.')) {
54
- return 1
55
- }
56
- return -1
57
- }),
58
- number: [...numberOptions, { label: 'url', id: 'url' }],
59
- }),
60
- [numberOptions, textOptions],
61
- )
62
-
63
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
64
- // @ts-ignore - outdated types from @hygraph/app-sdk-react
65
- const fieldType = field.parent.apiId ?? 'ConditionText'
66
- const options = fieldType === 'ConditionNumber' ? allOptions.number : allOptions.text
67
-
68
- if (!fields) {
69
- Promise.resolve(graphQLInterfaceQuery)
70
- .then((res) => {
71
- const newFields: __Field[] = res?.data.__type?.fields
72
-
73
- setFields(newFields)
74
- })
75
- .catch((err) => err)
76
-
77
- return <div>Loading fields...</div>
78
- }
79
- if (options.length < 1) return <div>No properties available</div>
80
- if (options.length > 10000) return <div>Too many properties to display</div>
41
+ const fieldPaths = useMemo(() => {
42
+ if (!schema) return []
43
+ return getFieldPaths(schema, ['ProductInterface'])
44
+ .sort((a, b) => a.depth() - b.depth())
45
+ .map((fp) => fp.stringify())
46
+ .filter<string>((v) => v !== undefined)
47
+ }, [schema])
81
48
 
82
49
  return (
83
50
  <TextField
84
51
  id='property-selector'
85
- select
52
+ select={!!fieldPaths.length}
53
+ variant='outlined'
54
+ size='small'
86
55
  SelectProps={{
87
56
  native: true,
88
- variant: 'outlined',
89
57
  }}
90
58
  value={localValue}
91
59
  onChange={(v) => {
@@ -95,6 +63,7 @@ export function PropertyPicker() {
95
63
  fullWidth
96
64
  sx={{
97
65
  mt: '4px',
66
+ fontSize: '0.8em',
98
67
  '& .MuiInputBase-root': {
99
68
  borderRadius: { xs: '2px!important' },
100
69
  },
@@ -119,11 +88,18 @@ export function PropertyPicker() {
119
88
  },
120
89
  }}
121
90
  >
122
- {options.map((o) => (
123
- <option key={o.id} value={o.id}>
124
- {o.label}
125
- </option>
126
- ))}
91
+ {fieldPaths.length > 0 ? (
92
+ <>
93
+ <option value='url'>url</option>
94
+ {fieldPaths.map((fp) => (
95
+ <option key={fp} value={fp}>
96
+ {fp}
97
+ </option>
98
+ ))}
99
+ </>
100
+ ) : (
101
+ <>{loading ? 'Loading..' : error?.message}</>
102
+ )}
127
103
  </TextField>
128
104
  )
129
105
  }
@@ -1,15 +1,14 @@
1
1
  import { useApp, Wrapper } from '@hygraph/app-sdk-react'
2
+ import Image from 'next/image'
2
3
  import { useState } from 'react'
3
4
  import styles from './setup.module.css'
4
5
 
5
6
  function Install() {
6
- // @ts-expect-error - outdated types from @hygraph/app-sdk-react
7
- const { updateInstallation, installation, showToast, extension } = useApp()
7
+ const { updateInstallation, installation, showToast } = useApp()
8
+
8
9
  const installed = installation.status === 'COMPLETED'
9
10
  const [gqlUri, setGqlUri] = useState('')
10
11
 
11
- const changedUri = extension.config.backend !== gqlUri
12
-
13
12
  const saveOnClick = () =>
14
13
  updateInstallation({
15
14
  config: { backend: gqlUri },
@@ -64,10 +63,8 @@ function Install() {
64
63
 
65
64
  let buttonText: string
66
65
  let buttonAction: typeof uninstallOnClick | typeof installOnClick
67
- if (changedUri) {
68
- buttonText = 'Save'
69
- buttonAction = saveOnClick
70
- } else if (installed) {
66
+
67
+ if (installed) {
71
68
  buttonText = 'Disable app'
72
69
  buttonAction = uninstallOnClick
73
70
  } else {
@@ -78,17 +75,30 @@ function Install() {
78
75
  return (
79
76
  <>
80
77
  <>
81
- <span>GraphQL API URI</span>
78
+ <span>
79
+ <strong>GraphQL API URI</strong>
80
+ </span>
82
81
  <input
83
82
  name='gql-uri'
84
- defaultValue={extension.config.backend}
83
+ className={styles.textInput}
84
+ defaultValue={(installation.config.backend as string) ?? ''}
85
85
  onChange={(e) => setGqlUri(e.target.value)}
86
86
  />
87
87
  </>
88
88
 
89
- <button type='button' className={styles.button} onClick={buttonAction}>
90
- {buttonText}
91
- </button>
89
+ <div className={styles.buttonsContainer}>
90
+ <button type='button' className={styles.button} onClick={saveOnClick} data-save-button>
91
+ Save
92
+ </button>
93
+ <button
94
+ type='button'
95
+ className={styles.button}
96
+ onClick={buttonAction}
97
+ aria-disabled={installed}
98
+ >
99
+ {buttonText}
100
+ </button>
101
+ </div>
92
102
  </>
93
103
  )
94
104
  }
@@ -96,16 +106,28 @@ function Install() {
96
106
  export function Page() {
97
107
  return (
98
108
  <div className={styles.container}>
99
- <h1 className={styles.title}>Dynamic Rows Property Selector</h1>
100
- <p className={styles.description}>
101
- Enhance your content management experience with Dynamic Rows, specifically designed to
102
- integrate seamlessly with our Dynamic Row module. It features an intuitive property picker
103
- field, allowing for effortless selection and organization of properties to customize your
104
- content layout. Press install to get started!
105
- </p>
106
- <Wrapper>
107
- <Install />
108
- </Wrapper>
109
+ <div className={styles.contentWrapper}>
110
+ <div className={styles.logoWrapper}>
111
+ <Image
112
+ src='https://www.graphcommerce.org/_next/static/media/graphcommerce.a8fe7e28.svg'
113
+ layout='fill'
114
+ alt='GraphCommerce logo'
115
+ />
116
+ </div>
117
+
118
+ <h1 className={styles.title}>
119
+ Dynamic Rows Property Selector <span className={styles.author}>by Joshua Bolk</span>
120
+ </h1>
121
+ <p className={styles.description}>
122
+ Enhance your content management experience with Dynamic Rows, specifically designed to
123
+ integrate seamlessly with our Dynamic Row module. It features an intuitive property picker
124
+ field, allowing for effortless selection and organization of properties to customize your
125
+ content layout. Enable the app and put your graphQL URI to get started.
126
+ </p>
127
+ <Wrapper>
128
+ <Install />
129
+ </Wrapper>
130
+ </div>
109
131
  </div>
110
132
  )
111
133
  }
@@ -1,11 +1,28 @@
1
1
  .container {
2
- display: flex;
3
- flex-direction: column;
4
- align-items: center;
5
- justify-content: center;
6
2
  height: 100%;
7
3
  max-width: 1200px;
8
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
4
+ font-family: 'Roboto', sans-serif;
5
+ line-height: 1.3;
6
+ font-size: 18px;
7
+ background-color: aliceblue;
8
+ padding: 32px 24px;
9
+ border-radius: 8px;
10
+ margin: 0 auto;
11
+ }
12
+
13
+ .contentWrapper {
14
+ max-width: 700px;
15
+ display: flex;
16
+ flex-direction: column;
17
+ align-items: left;
18
+ margin: 0 auto;
19
+ }
20
+
21
+ .logoWrapper {
22
+ position: relative;
23
+ height: 60px;
24
+ width: 50%;
25
+ margin-bottom: 32px;
9
26
  }
10
27
 
11
28
  .title {
@@ -15,6 +32,12 @@
15
32
  margin-bottom: 16px;
16
33
  }
17
34
 
35
+ .author {
36
+ font-size: 12px;
37
+ font-weight: 300;
38
+ line-height: 16px;
39
+ }
40
+
18
41
  .desciption {
19
42
  font-size: 14px;
20
43
  font-weight: 300;
@@ -40,19 +63,51 @@
40
63
  text-decoration: none;
41
64
  font-weight: 500;
42
65
  border: 0px;
43
- margin: 16px 0px 0px;
66
+ margin: 16px 0 0 0;
44
67
  border-radius: 4px;
45
- font-size: 12px;
68
+ font-size: 18px;
46
69
  line-height: 16px;
47
- height: 24px;
70
+ height: 40px;
48
71
  min-width: 24px;
49
- padding-left: 8px;
50
- padding-right: 8px;
72
+ padding-left: 16px;
73
+ padding-right: 16px;
51
74
  color: rgb(255, 255, 255);
52
- background-color: rgb(90, 92, 236);
75
+ background-color: #2563eb;
76
+ transition: background-color 0.2s ease 0s;
53
77
  }
54
78
 
55
79
  .button:hover {
56
80
  cursor: pointer;
57
- background-color: rgb(58, 48, 166);
81
+ background-color: #1d4ed8;
82
+ }
83
+
84
+ .button[aria-disabled='true'] {
85
+ background-color: rgb(200, 200, 200);
86
+ }
87
+
88
+ .button[aria-disabled='true']:hover {
89
+ background-color: rgb(192, 192, 192);
90
+ }
91
+
92
+ .button[aria-disabled='false'] {
93
+ background-color: #16a34a;
94
+ }
95
+
96
+ .button[aria-disabled='false']:hover {
97
+ background-color: #15803d;
98
+ }
99
+
100
+ .buttonsContainer {
101
+ display: flex;
102
+ align-items: center;
103
+ justify-content: space-between;
104
+ margin-top: 8px;
105
+ column-gap: 24px;
106
+ }
107
+
108
+ .textInput {
109
+ display: inline;
110
+ margin: 24px 0;
111
+ font-size: 18px;
112
+ padding: 12px 6px;
58
113
  }
@@ -0,0 +1,66 @@
1
+ import { IntrospectionField, IntrospectionOutputTypeRef, IntrospectionSchema } from 'graphql'
2
+
3
+ function getType(type: IntrospectionOutputTypeRef) {
4
+ switch (type.kind) {
5
+ case 'NON_NULL':
6
+ case 'LIST':
7
+ return getType(type.ofType)
8
+ default:
9
+ return type
10
+ }
11
+ }
12
+
13
+ class FieldPath {
14
+ constructor(
15
+ public field: IntrospectionField,
16
+ private prev: FieldPath | undefined,
17
+ ) {}
18
+
19
+ stringify(filter?: string[]): string | undefined {
20
+ if (this.field.type.kind === 'SCALAR' && filter && !filter.includes(this.field.type.name)) {
21
+ return undefined
22
+ }
23
+
24
+ const prevStr = this.prev?.stringify(filter)
25
+ return prevStr ? `${prevStr}.${this.field.name}` : this.field.name
26
+ }
27
+
28
+ depth = () => (this?.prev?.depth() ?? 0) + 1
29
+ }
30
+
31
+ export function getFieldPaths(
32
+ schema: IntrospectionSchema,
33
+ types: string[],
34
+ prevPath: FieldPath | undefined = undefined,
35
+ ): FieldPath[] {
36
+ const typeName = types[types.length - 1]
37
+
38
+ const paths: FieldPath[] = []
39
+ const type = schema.types.find((t) => t.name === typeName)
40
+
41
+ if (!type) return paths
42
+
43
+ if ((prevPath?.depth() ?? 0) > 3) return paths
44
+
45
+ if (type.kind === 'OBJECT' || type.kind === 'INTERFACE') {
46
+ type.fields.forEach((field) => {
47
+ const t = getType(field.type)
48
+
49
+ if (!types.includes(t.name)) {
50
+ const newTypes = [...types, t.name]
51
+
52
+ const newPath = new FieldPath(field, prevPath)
53
+
54
+ if (t.kind === 'OBJECT' || t.kind === 'INTERFACE') {
55
+ paths.push(...getFieldPaths(schema, newTypes, newPath))
56
+ } else if (t.kind === 'SCALAR' || t.kind === 'ENUM') {
57
+ paths.push(newPath)
58
+ } else if (t.kind === 'UNION') {
59
+ // not supported currently
60
+ }
61
+ }
62
+ })
63
+ }
64
+
65
+ return paths
66
+ }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@graphcommerce/hygraph-dynamic-rows-ui",
3
3
  "homepage": "https://www.graphcommerce.org/",
4
4
  "repository": "github:graphcommerce-org/graphcommerce",
5
- "version": "8.1.0-canary.8",
5
+ "version": "9.0.0-canary.100",
6
6
  "sideEffects": false,
7
7
  "type": "commonjs",
8
8
  "prettier": "@graphcommerce/prettier-config-pwa",
@@ -16,29 +16,29 @@
16
16
  "dev": "next dev"
17
17
  },
18
18
  "dependencies": {
19
- "@apollo/client": "~3.8.10",
20
- "@graphcommerce/next-config": "8.1.0-canary.8",
21
- "@hygraph/app-sdk-react": "^0.0.3",
22
- "@lingui/core": "^4.7.0",
23
- "@lingui/macro": "^4.7.0",
24
- "@lingui/react": "^4.7.0",
25
- "@mui/material": "5.15.5",
19
+ "@apollo/client": "~3.10.8",
20
+ "@graphcommerce/next-config": "9.0.0-canary.100",
21
+ "@hygraph/app-sdk-react": "^0.0.4",
22
+ "@lingui/core": "^4.11.2",
23
+ "@lingui/macro": "^4.11.2",
24
+ "@lingui/react": "^4.11.2",
25
+ "@mui/material": "5.16.4",
26
26
  "cross-env": "^7.0.3",
27
- "dotenv": "16.3.1",
28
- "graphql": "^16.8.1",
29
- "next": "14.1.0",
30
- "react": "^18.2.0",
31
- "react-dom": "^18.2.0",
32
- "webpack": "5.89.0"
27
+ "dotenv": "16.4.5",
28
+ "graphql": "^16.9.0",
29
+ "next": "14.2.5",
30
+ "react": "^18.3.1",
31
+ "react-dom": "^18.3.1",
32
+ "webpack": "~5.93.0"
33
33
  },
34
34
  "devDependencies": {
35
- "@graphcommerce/eslint-config-pwa": "8.1.0-canary.8",
36
- "@graphcommerce/prettier-config-pwa": "8.1.0-canary.8",
37
- "@graphcommerce/typescript-config-pwa": "8.1.0-canary.8",
38
- "@types/react-is": "^18.2.4",
35
+ "@graphcommerce/eslint-config-pwa": "9.0.0-canary.100",
36
+ "@graphcommerce/prettier-config-pwa": "9.0.0-canary.100",
37
+ "@graphcommerce/typescript-config-pwa": "9.0.0-canary.100",
38
+ "@types/react-is": "^18.3.0",
39
39
  "babel-plugin-macros": "^3.1.0",
40
- "eslint": "8.56.0",
41
- "prettier": "3.2.4",
42
- "typescript": "5.3.3"
40
+ "eslint": "^8",
41
+ "prettier": "3.3.3",
42
+ "typescript": "5.5.3"
43
43
  }
44
44
  }
@@ -1,15 +1,14 @@
1
1
  import { Wrapper } from '@hygraph/app-sdk-react'
2
- import React from 'react'
3
- import { PropertyPicker } from '..'
2
+ import React, { useEffect } from 'react'
3
+ import { PropertyPicker } from '../components/PropertyPicker'
4
4
 
5
5
  export default function DRPropertyPicker() {
6
6
  const fieldContainer = React.useRef<HTMLDivElement | null>(null)
7
7
 
8
- React.useEffect(() => {
8
+ useEffect(() => {
9
9
  /**
10
10
  * Some styling is being undone here to resolve conflicts between Hygraph App SDK and CssAndFramerMotionProvider.
11
11
  */
12
-
13
12
  const frameBox1 = fieldContainer?.current?.parentElement
14
13
  if (frameBox1) {
15
14
  frameBox1.style.position = 'static'
package/pages/setup.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import React from 'react'
1
+ import React, { useEffect } from 'react'
2
2
  import { Page } from '..'
3
3
 
4
4
  export default function Setup() {
@@ -8,7 +8,7 @@ export default function Setup() {
8
8
  * This is a hack to fix the height of the iframe, which was malfunctioning because of a conflict
9
9
  * with FramerNextPages
10
10
  */
11
- React.useEffect(() => {
11
+ useEffect(() => {
12
12
  const framerParent = appContainer?.current?.parentElement
13
13
  if (framerParent) {
14
14
  framerParent.style.position = 'static'
@@ -1,42 +0,0 @@
1
- import { ProductProperty } from '../types'
2
-
3
- export const createOptionsFromInterfaceObject = (
4
- obj: object,
5
- path = '',
6
- inputs: ProductProperty[] = [],
7
- parent = '',
8
- ): ProductProperty[] => {
9
- for (const [key, value] of Object.entries(obj)) {
10
- /** Keep count of the current path and parent */
11
- const currentPath: string = path ? `${path}.${key}` : key
12
- const currentParent: string = parent ? `${parent}/` : ''
13
-
14
- /**
15
- * If the value is a string, number or boolean, add it to the inputs array. If the value is an
16
- * array, recurse on the first item. If the value is an object, recurse on all it's keys.
17
- */
18
- if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
19
- inputs.push({
20
- label: currentPath,
21
- id: currentPath,
22
- })
23
- } else if (Array.isArray(value) && value.length > 0) {
24
- createOptionsFromInterfaceObject(
25
- value[0] as object,
26
- `${currentPath}[0]`,
27
- inputs,
28
- `${currentParent}${key}`,
29
- )
30
- } else if (typeof value === 'object' && value !== null) {
31
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
32
- createOptionsFromInterfaceObject(
33
- value as object,
34
- currentPath,
35
- inputs,
36
- `${currentParent}${key}`,
37
- )
38
- }
39
- }
40
-
41
- return inputs
42
- }
@@ -1,13 +0,0 @@
1
- export const createRecursiveIntrospectionQuery = (type: string, depth: number) => {
2
- let baseQuery = `__type(name: "${type}") { name fields { name `
3
- let endQuery = ' } }'
4
-
5
- for (let i = 0; i < depth; i++) {
6
- baseQuery += 'type { name ofType { name fields { name isDeprecated '
7
- endQuery += ' } } }'
8
- }
9
-
10
- const result = baseQuery + endQuery
11
-
12
- return result
13
- }
@@ -1,14 +0,0 @@
1
- import { ApolloClient, NormalizedCacheObject, gql } from '@apollo/client'
2
- import { createRecursiveIntrospectionQuery } from './createRecursiveIntrospectionQuery'
3
-
4
- export const fetchGraphQLInterface = (client: ApolloClient<NormalizedCacheObject>) => {
5
- const introspectionQuery = createRecursiveIntrospectionQuery('ProductInterface', 4)
6
-
7
- return client.query({
8
- query: gql`
9
- query getSchema {
10
- ${introspectionQuery}
11
- }
12
- `,
13
- })
14
- }
package/lib/index.ts DELETED
@@ -1,4 +0,0 @@
1
- export * from './createOptionsFromInterfaceObject'
2
- export * from './createRecursiveIntrospectionQuery'
3
- export * from './fetchGraphQLInterface'
4
- export * from './objectifyGraphQLInterface'
@@ -1,62 +0,0 @@
1
- import { __Field } from '../types'
2
-
3
- /**
4
- * In this function we create an object from the GraphQL interface.
5
- * We need this so we can map out the properties of an interface that is needed
6
- * for the Dynamic Rows Autocomplete.
7
- * @param fields - The GraphQL interface object that is read from the schema.
8
- * @returns
9
- */
10
- export const objectifyGraphQLInterface = (
11
- fields: __Field[] | null,
12
- conditionType: 'text' | 'number' | 'all',
13
- skip: string[],
14
- ): object => {
15
- let objectifiedInterface: object = {}
16
-
17
- if (!fields) return objectifiedInterface
18
-
19
- for (const [, value] of Object.entries(fields)) {
20
- const nestedFields = value?.type?.ofType?.fields
21
- const { isDeprecated } = value
22
- const typeOf = value?.type?.name
23
- const typeName = value?.type?.ofType?.name ?? ''
24
-
25
- /**
26
- * With typevalue we can know of which type a property is, so we for example can determine to to hide string values in ConditionNumbers.
27
- */
28
- let typeValue: 'number' | 'text' | 'boolean'
29
- switch (typeOf) {
30
- case 'Float' || 'Int':
31
- typeValue = 'number'
32
- break
33
- case 'Boolean':
34
- typeValue = 'text' // Seperate booleans are not supported yet.
35
- break
36
- default:
37
- typeValue = 'text'
38
- break
39
- }
40
-
41
- if (skip.includes(typeName) || isDeprecated || !value?.name) {
42
- // do nothing
43
- } else if (nestedFields) {
44
- objectifiedInterface = {
45
- ...objectifiedInterface,
46
- [value.name]: objectifyGraphQLInterface(nestedFields, conditionType, [...skip, typeName]),
47
- }
48
- } else if (typeOf && conditionType === 'all') {
49
- objectifiedInterface = {
50
- ...objectifiedInterface,
51
- [value.name]: typeValue,
52
- }
53
- } else if (conditionType === typeValue) {
54
- objectifiedInterface = {
55
- ...objectifiedInterface,
56
- [value.name]: typeValue,
57
- }
58
- }
59
- }
60
-
61
- return objectifiedInterface
62
- }