Loading fields...
+ }
+ if (options.length < 1) return
+
Dynamic Rows Property Selector
+
+ Enhance your content management experience with Dynamic Rows, specifically designed to
+ integrate seamlessly with our Dynamic Row module. It features an intuitive property picker
+ field, allowing for effortless selection and organization of properties to customize your
+ content layout. Press install to get started!
+
+
+
+
+
+ )
+}
diff --git a/packages/hygraph-dynamic-rows-ui/components/index.ts b/packages/hygraph-dynamic-rows-ui/components/index.ts
new file mode 100644
index 0000000000..5036257032
--- /dev/null
+++ b/packages/hygraph-dynamic-rows-ui/components/index.ts
@@ -0,0 +1 @@
+export * from './PropertyPicker'
diff --git a/packages/hygraph-dynamic-rows-ui/components/setup.module.css b/packages/hygraph-dynamic-rows-ui/components/setup.module.css
new file mode 100644
index 0000000000..7608f37b65
--- /dev/null
+++ b/packages/hygraph-dynamic-rows-ui/components/setup.module.css
@@ -0,0 +1,58 @@
+.container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ max-width: 1200px;
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+}
+
+.title {
+ font-size: 24px;
+ font-weight: 600;
+ line-height: 32px;
+ margin-bottom: 16px;
+}
+
+.desciption {
+ font-size: 14px;
+ font-weight: 300;
+ line-height: 20px;
+ margin-bottom: 16px;
+}
+
+.input {
+ display: inline;
+}
+
+.button {
+ user-select: none;
+ box-sizing: border-box;
+ appearance: none;
+ position: relative;
+ display: inline-flex;
+ -webkit-box-align: center;
+ align-items: center;
+ text-align: center;
+ vertical-align: middle;
+ align-self: center;
+ text-decoration: none;
+ font-weight: 500;
+ border: 0px;
+ margin: 16px 0px 0px;
+ border-radius: 4px;
+ font-size: 12px;
+ line-height: 16px;
+ height: 24px;
+ min-width: 24px;
+ padding-left: 8px;
+ padding-right: 8px;
+ color: rgb(255, 255, 255);
+ background-color: rgb(90, 92, 236);
+}
+
+.button:hover {
+ cursor: pointer;
+ background-color: rgb(58, 48, 166);
+}
diff --git a/packages/hygraph-dynamic-rows-ui/index.ts b/packages/hygraph-dynamic-rows-ui/index.ts
new file mode 100644
index 0000000000..6801e650e2
--- /dev/null
+++ b/packages/hygraph-dynamic-rows-ui/index.ts
@@ -0,0 +1,2 @@
+export * from './components/Setup'
+export * from './components'
diff --git a/packages/hygraph-dynamic-rows-ui/lib/createOptionsFromInterfaceObject.ts b/packages/hygraph-dynamic-rows-ui/lib/createOptionsFromInterfaceObject.ts
new file mode 100644
index 0000000000..c62b33fd88
--- /dev/null
+++ b/packages/hygraph-dynamic-rows-ui/lib/createOptionsFromInterfaceObject.ts
@@ -0,0 +1,42 @@
+import { ProductProperty } from '../types'
+
+export const createOptionsFromInterfaceObject = (
+ obj: object,
+ path = '',
+ inputs: ProductProperty[] = [],
+ parent = '',
+): ProductProperty[] => {
+ for (const [key, value] of Object.entries(obj)) {
+ /** Keep count of the current path and parent */
+ const currentPath: string = path ? `${path}.${key}` : key
+ const currentParent: string = parent ? `${parent}/` : ''
+
+ /**
+ * If the value is a string, number or boolean, add it to the inputs array. If the value is an
+ * array, recurse on the first item. If the value is an object, recurse on all it's keys.
+ */
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
+ inputs.push({
+ label: currentPath,
+ id: currentPath,
+ })
+ } else if (Array.isArray(value) && value.length > 0) {
+ createOptionsFromInterfaceObject(
+ value[0] as object,
+ `${currentPath}[0]`,
+ inputs,
+ `${currentParent}${key}`,
+ )
+ } else if (typeof value === 'object' && value !== null) {
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
+ createOptionsFromInterfaceObject(
+ value as object,
+ currentPath,
+ inputs,
+ `${currentParent}${key}`,
+ )
+ }
+ }
+
+ return inputs
+}
diff --git a/packages/hygraph-dynamic-rows-ui/lib/createRecursiveIntrospectionQuery.ts b/packages/hygraph-dynamic-rows-ui/lib/createRecursiveIntrospectionQuery.ts
new file mode 100644
index 0000000000..4d5ce310df
--- /dev/null
+++ b/packages/hygraph-dynamic-rows-ui/lib/createRecursiveIntrospectionQuery.ts
@@ -0,0 +1,13 @@
+export const createRecursiveIntrospectionQuery = (type: string, depth: number) => {
+ let baseQuery = `__type(name: "${type}") { name fields { name `
+ let endQuery = ' } }'
+
+ for (let i = 0; i < depth; i++) {
+ baseQuery += 'type { name ofType { name fields { name isDeprecated '
+ endQuery += ' } } }'
+ }
+
+ const result = baseQuery + endQuery
+
+ return result
+}
diff --git a/packages/hygraph-dynamic-rows-ui/lib/fetchGraphQLInterface.ts b/packages/hygraph-dynamic-rows-ui/lib/fetchGraphQLInterface.ts
new file mode 100644
index 0000000000..c1d3047ffb
--- /dev/null
+++ b/packages/hygraph-dynamic-rows-ui/lib/fetchGraphQLInterface.ts
@@ -0,0 +1,14 @@
+import { ApolloClient, NormalizedCacheObject, gql } from '@apollo/client'
+import { createRecursiveIntrospectionQuery } from './createRecursiveIntrospectionQuery'
+
+export const fetchGraphQLInterface = (client: ApolloClient