@sanity/form-toolkit 1.2.1 → 2.0.0
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/README.md +8 -8
- package/dist/_chunks-cjs/create-handler.js +68 -0
- package/dist/_chunks-cjs/create-handler.js.map +1 -0
- package/dist/_chunks-es/create-handler.mjs +69 -0
- package/dist/_chunks-es/create-handler.mjs.map +1 -0
- package/dist/form-schema/index.d.mts +69 -0
- package/dist/form-schema/index.d.ts +69 -0
- package/dist/{index.js → form-schema/index.js} +1 -146
- package/dist/form-schema/index.js.map +1 -0
- package/dist/{index.mjs → form-schema/index.mjs} +2 -147
- package/dist/form-schema/index.mjs.map +1 -0
- package/dist/formium/index.d.mts +20 -0
- package/dist/formium/index.d.ts +20 -0
- package/dist/formium/index.js +28 -0
- package/dist/formium/index.js.map +1 -0
- package/dist/formium/index.mjs +30 -0
- package/dist/formium/index.mjs.map +1 -0
- package/dist/hubspot/index.d.mts +49 -0
- package/dist/hubspot/index.d.ts +49 -0
- package/dist/hubspot/index.js +44 -0
- package/dist/hubspot/index.js.map +1 -0
- package/dist/hubspot/index.mjs +48 -0
- package/dist/hubspot/index.mjs.map +1 -0
- package/dist/mailchimp/index.d.mts +45 -0
- package/dist/mailchimp/index.d.ts +45 -0
- package/dist/mailchimp/index.js +48 -0
- package/dist/mailchimp/index.js.map +1 -0
- package/dist/mailchimp/index.mjs +49 -0
- package/dist/mailchimp/index.mjs.map +1 -0
- package/package.json +36 -6
- package/src/form-schema/index.ts +2 -1
- package/src/hubspot/index.ts +5 -3
- package/src/index.ts +18 -18
- package/src/mailchimp/index.ts +5 -4
- package/dist/index.d.mts +0 -166
- package/dist/index.d.ts +0 -166
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ There's an "out of the box" handler for Next.js API routes:
|
|
|
24
24
|
|
|
25
25
|
```ts
|
|
26
26
|
// pages/api/hubspot.ts
|
|
27
|
-
import {hubSpotHandler} from '@sanity/form-toolkit'
|
|
27
|
+
import {hubSpotHandler} from '@sanity/form-toolkit/hubspot'
|
|
28
28
|
|
|
29
29
|
const handler = hubSpotHandler({
|
|
30
30
|
token: process.env.HUBSPOT_TOKEN ?? '',
|
|
@@ -37,7 +37,7 @@ Or add `fetchHubSpotData` to an API route in your non-Next framework
|
|
|
37
37
|
|
|
38
38
|
```ts
|
|
39
39
|
// my-nuxt-app/server/api/hubspot.ts
|
|
40
|
-
import {fetchHubSpotData} from '@sanity/form-toolkit'
|
|
40
|
+
import {fetchHubSpotData} from '@sanity/form-toolkit/hubspot'
|
|
41
41
|
|
|
42
42
|
export default defineEventHandler(async (event) => {
|
|
43
43
|
const req = event.node.req
|
|
@@ -54,7 +54,7 @@ Add it as a plugin in `sanity.config.ts` (or .js):
|
|
|
54
54
|
|
|
55
55
|
```ts
|
|
56
56
|
import {defineConfig} from 'sanity'
|
|
57
|
-
import {hubSpotInput} from '@sanity/form-toolkit'
|
|
57
|
+
import {hubSpotInput} from '@sanity/form-toolkit/hubspot'
|
|
58
58
|
|
|
59
59
|
export default defineConfig({
|
|
60
60
|
//...
|
|
@@ -96,7 +96,7 @@ There's an "out of the box" handler for Next.js API routes:
|
|
|
96
96
|
|
|
97
97
|
```ts
|
|
98
98
|
// pages/api/mailchimp.ts
|
|
99
|
-
import {mailchimpHandler} from '@sanity/form-toolkit'
|
|
99
|
+
import {mailchimpHandler} from '@sanity/form-toolkit/mailchimp'
|
|
100
100
|
|
|
101
101
|
const handler = mailchimpHandler({
|
|
102
102
|
key: process.env.MAILCHIMP_KEY ?? '',
|
|
@@ -110,7 +110,7 @@ Or add `fetchMailchimpData` to an API route in your non-Next framework
|
|
|
110
110
|
|
|
111
111
|
```ts
|
|
112
112
|
// my-nuxt-app/server/api/mailchimp.ts
|
|
113
|
-
import {fetchMailchimpData} from '@sanity/form-toolkit'
|
|
113
|
+
import {fetchMailchimpData} from '@sanity/form-toolkit/mailchimp'
|
|
114
114
|
|
|
115
115
|
export default defineEventHandler(async (event) => {
|
|
116
116
|
const req = event.node.req
|
|
@@ -128,7 +128,7 @@ Add it as a plugin in `sanity.config.ts` (or .js):
|
|
|
128
128
|
|
|
129
129
|
```ts
|
|
130
130
|
import {defineConfig} from 'sanity'
|
|
131
|
-
import {mailchimpInput} from '@sanity/form-toolkit'
|
|
131
|
+
import {mailchimpInput} from '@sanity/form-toolkit/mailchimp'
|
|
132
132
|
|
|
133
133
|
export default defineConfig({
|
|
134
134
|
//...
|
|
@@ -166,7 +166,7 @@ First add `formSchema` it as a plugin in `sanity.config.ts` (or .js):
|
|
|
166
166
|
|
|
167
167
|
```ts
|
|
168
168
|
import {defineConfig} from 'sanity'
|
|
169
|
-
import {formSchema} from '@sanity/form-toolkit'
|
|
169
|
+
import {formSchema} from '@sanity/form-toolkit/form-schema'
|
|
170
170
|
|
|
171
171
|
export default defineConfig({
|
|
172
172
|
//...
|
|
@@ -178,7 +178,7 @@ Then pass a `form` document to the `FormRenderer` component
|
|
|
178
178
|
|
|
179
179
|
```tsx
|
|
180
180
|
import React, {type FC} from 'react'
|
|
181
|
-
import {FormRenderer, type FormDataProps} from '@sanity/form-toolkit'
|
|
181
|
+
import {FormRenderer, type FormDataProps} from '@sanity/form-toolkit/form-schema'
|
|
182
182
|
|
|
183
183
|
interface NativeFormExampleProps {
|
|
184
184
|
formData: FormDataProps
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var h3 = require("h3");
|
|
3
|
+
const detectFramework = () => {
|
|
4
|
+
if (process.env.NEXT_RUNTIME)
|
|
5
|
+
return "nextjs";
|
|
6
|
+
if (process.env.NUXT_ENV)
|
|
7
|
+
return "nuxt";
|
|
8
|
+
if (process.env.SVELTEKIT_ENV)
|
|
9
|
+
return "sveltekit";
|
|
10
|
+
if (process.env.REMIX_ENV)
|
|
11
|
+
return "remix";
|
|
12
|
+
if (process.env.ASTRO_ENV)
|
|
13
|
+
return "astro";
|
|
14
|
+
throw new Error("Unable to detect framework.");
|
|
15
|
+
}, createHandler = (handlerFunc) => {
|
|
16
|
+
const framework = detectFramework(), handlerLogic = async ({
|
|
17
|
+
// eslint-disable-next-line
|
|
18
|
+
req,
|
|
19
|
+
res
|
|
20
|
+
}) => {
|
|
21
|
+
try {
|
|
22
|
+
const data = await handlerFunc();
|
|
23
|
+
return res && (res.writeHead(200, { "Content-Type": "application/json" }), res.end(JSON.stringify(data))), data;
|
|
24
|
+
} catch (error) {
|
|
25
|
+
return error instanceof Error ? (res && (res.writeHead(500, { "Content-Type": "application/json" }), res.end(JSON.stringify({ error: error.message }))), { error: error.message }) : (res && (res.writeHead(500, { "Content-Type": "application/json" }), res.end(JSON.stringify({ error: "An unexpected error occurred" }))), { error: "An unexpected error occurred" });
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
if (framework === "nextjs")
|
|
29
|
+
return async (req, res) => {
|
|
30
|
+
res.setHeader("Access-Control-Allow-Origin", "*"), res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"), res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"), await handlerLogic({ req, res });
|
|
31
|
+
};
|
|
32
|
+
if (framework === "nuxt")
|
|
33
|
+
return h3.defineEventHandler(async (event) => {
|
|
34
|
+
const req = event.node.req, res = event.node.res;
|
|
35
|
+
return handlerLogic({ req, res });
|
|
36
|
+
});
|
|
37
|
+
if (framework === "sveltekit")
|
|
38
|
+
return {
|
|
39
|
+
GET: async ({ request }) => {
|
|
40
|
+
const result = await handlerLogic({ req: request });
|
|
41
|
+
return new Response(JSON.stringify(result), {
|
|
42
|
+
headers: { "Content-Type": "application/json" }
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
if (framework === "remix")
|
|
47
|
+
return {
|
|
48
|
+
loader: async ({ request }) => {
|
|
49
|
+
const result = await handlerLogic({ req: request });
|
|
50
|
+
return new Response(JSON.stringify(result), {
|
|
51
|
+
headers: { "Content-Type": "application/json" }
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
if (framework === "astro")
|
|
56
|
+
return {
|
|
57
|
+
get: async ({ request }) => {
|
|
58
|
+
const result = await handlerLogic({ req: request });
|
|
59
|
+
return {
|
|
60
|
+
body: JSON.stringify(result),
|
|
61
|
+
headers: { "Content-Type": "application/json" }
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
throw new Error(`Unsupported framework: ${framework}`);
|
|
66
|
+
};
|
|
67
|
+
exports.createHandler = createHandler;
|
|
68
|
+
//# sourceMappingURL=create-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-handler.js","sources":["../../src/shared/create-handler.ts"],"sourcesContent":["import {defineEventHandler, type H3Event} from 'h3' // For Nuxt.js/Nitro\nimport type {IncomingMessage, ServerResponse} from 'http'\n\n// Utility function to detect the framework at runtime\nconst detectFramework = (): string => {\n if (process.env.NEXT_RUNTIME) {\n return 'nextjs'\n } else if (process.env.NUXT_ENV) {\n return 'nuxt'\n } else if (process.env.SVELTEKIT_ENV) {\n return 'sveltekit'\n } else if (process.env.REMIX_ENV) {\n return 'remix'\n } else if (process.env.ASTRO_ENV) {\n return 'astro'\n }\n throw new Error('Unable to detect framework.')\n}\n\n// Create a generic handler with predefined logic\nconst createHandler = (handlerFunc: () => Promise<unknown>) => {\n const framework = detectFramework()\n\n // Handler logic to fetch Mailchimp data\n const handlerLogic = async ({\n // eslint-disable-next-line\n req,\n res,\n }: {\n req: IncomingMessage | Request\n res?: ServerResponse\n }): Promise<unknown> => {\n try {\n const data = await handlerFunc()\n\n if (res) {\n // Send response directly for frameworks like Next.js and Nuxt.js\n res.writeHead(200, {'Content-Type': 'application/json'})\n res.end(JSON.stringify(data))\n }\n\n // Return the response for frameworks like SvelteKit, Remix, and Astro\n return data\n } catch (error) {\n if (error instanceof Error) {\n if (res) {\n res.writeHead(500, {'Content-Type': 'application/json'})\n res.end(JSON.stringify({error: error.message}))\n }\n return {error: error.message}\n }\n // Handle non-Error types (e.g., strings, objects)\n if (res) {\n res.writeHead(500, {'Content-Type': 'application/json'})\n res.end(JSON.stringify({error: 'An unexpected error occurred'}))\n }\n return {error: 'An unexpected error occurred'}\n }\n }\n\n // Framework-specific implementations\n if (framework === 'nextjs') {\n return async (req: IncomingMessage, res: ServerResponse) => {\n // Set CORS headers\n res.setHeader('Access-Control-Allow-Origin', '*') // Allow all origins\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS') // Allowed HTTP methods\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization') // Allowed headers\n\n await handlerLogic({req, res})\n }\n } else if (framework === 'nuxt') {\n return defineEventHandler(async (event: H3Event) => {\n const req = event.node.req\n const res = event.node.res\n return handlerLogic({req, res})\n })\n } else if (framework === 'sveltekit') {\n return {\n GET: async ({request}: {request: Request}) => {\n const result = await handlerLogic({req: request})\n return new Response(JSON.stringify(result), {\n headers: {'Content-Type': 'application/json'},\n })\n },\n }\n } else if (framework === 'remix') {\n return {\n loader: async ({request}: {request: Request}) => {\n const result = await handlerLogic({req: request})\n return new Response(JSON.stringify(result), {\n headers: {'Content-Type': 'application/json'},\n })\n },\n }\n } else if (framework === 'astro') {\n return {\n get: async ({request}: {request: Request}) => {\n const result = await handlerLogic({req: request})\n return {\n body: JSON.stringify(result),\n headers: {'Content-Type': 'application/json'},\n }\n },\n }\n }\n throw new Error(`Unsupported framework: ${framework}`)\n}\n\nexport default createHandler\n"],"names":["defineEventHandler"],"mappings":";;AAIA,MAAM,kBAAkB,MAAc;AACpC,MAAI,QAAQ,IAAI;AACP,WAAA;AACF,MAAI,QAAQ,IAAI;AACd,WAAA;AACF,MAAI,QAAQ,IAAI;AACd,WAAA;AACF,MAAI,QAAQ,IAAI;AACd,WAAA;AACF,MAAI,QAAQ,IAAI;AACd,WAAA;AAEH,QAAA,IAAI,MAAM,6BAA6B;AAC/C,GAGM,gBAAgB,CAAC,gBAAwC;AAC7D,QAAM,YAAY,mBAGZ,eAAe,OAAO;AAAA;AAAA,IAE1B;AAAA,IACA;AAAA,EAAA,MAIsB;AAClB,QAAA;AACI,YAAA,OAAO,MAAM,YAAY;AAE/B,aAAI,QAEF,IAAI,UAAU,KAAK,EAAC,gBAAgB,mBAAA,CAAmB,GACvD,IAAI,IAAI,KAAK,UAAU,IAAI,CAAC,IAIvB;AAAA,aACA,OAAO;AACV,aAAA,iBAAiB,SACf,QACF,IAAI,UAAU,KAAK,EAAC,gBAAgB,oBAAmB,GACvD,IAAI,IAAI,KAAK,UAAU,EAAC,OAAO,MAAM,QAAQ,CAAA,CAAC,IAEzC,EAAC,OAAO,MAAM,QAAO,MAG1B,QACF,IAAI,UAAU,KAAK,EAAC,gBAAgB,mBAAmB,CAAA,GACvD,IAAI,IAAI,KAAK,UAAU,EAAC,OAAO,+BAAA,CAA+B,CAAC,IAE1D,EAAC,OAAO;IAA8B;AAAA,EAEjD;AAGA,MAAI,cAAc;AACT,WAAA,OAAO,KAAsB,QAAwB;AAE1D,UAAI,UAAU,+BAA+B,GAAG,GAChD,IAAI,UAAU,gCAAgC,iCAAiC,GAC/E,IAAI,UAAU,gCAAgC,6BAA6B,GAE3E,MAAM,aAAa,EAAC,KAAK,KAAI;AAAA,IAC/B;AACK,MAAI,cAAc;AAChB,WAAAA,GAAAA,mBAAmB,OAAO,UAAmB;AAClD,YAAM,MAAM,MAAM,KAAK,KACjB,MAAM,MAAM,KAAK;AACvB,aAAO,aAAa,EAAC,KAAK,KAAI;AAAA,IAAA,CAC/B;AACI,MAAI,cAAc;AAChB,WAAA;AAAA,MACL,KAAK,OAAO,EAAC,cAAiC;AAC5C,cAAM,SAAS,MAAM,aAAa,EAAC,KAAK,SAAQ;AAChD,eAAO,IAAI,SAAS,KAAK,UAAU,MAAM,GAAG;AAAA,UAC1C,SAAS,EAAC,gBAAgB,mBAAkB;AAAA,QAAA,CAC7C;AAAA,MAAA;AAAA,IAEL;AACK,MAAI,cAAc;AAChB,WAAA;AAAA,MACL,QAAQ,OAAO,EAAC,cAAiC;AAC/C,cAAM,SAAS,MAAM,aAAa,EAAC,KAAK,SAAQ;AAChD,eAAO,IAAI,SAAS,KAAK,UAAU,MAAM,GAAG;AAAA,UAC1C,SAAS,EAAC,gBAAgB,mBAAkB;AAAA,QAAA,CAC7C;AAAA,MAAA;AAAA,IAEL;AACK,MAAI,cAAc;AAChB,WAAA;AAAA,MACL,KAAK,OAAO,EAAC,cAAiC;AAC5C,cAAM,SAAS,MAAM,aAAa,EAAC,KAAK,SAAQ;AACzC,eAAA;AAAA,UACL,MAAM,KAAK,UAAU,MAAM;AAAA,UAC3B,SAAS,EAAC,gBAAgB,mBAAkB;AAAA,QAC9C;AAAA,MAAA;AAAA,IAEJ;AAEF,QAAM,IAAI,MAAM,0BAA0B,SAAS,EAAE;AACvD;;"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { defineEventHandler } from "h3";
|
|
2
|
+
const detectFramework = () => {
|
|
3
|
+
if (process.env.NEXT_RUNTIME)
|
|
4
|
+
return "nextjs";
|
|
5
|
+
if (process.env.NUXT_ENV)
|
|
6
|
+
return "nuxt";
|
|
7
|
+
if (process.env.SVELTEKIT_ENV)
|
|
8
|
+
return "sveltekit";
|
|
9
|
+
if (process.env.REMIX_ENV)
|
|
10
|
+
return "remix";
|
|
11
|
+
if (process.env.ASTRO_ENV)
|
|
12
|
+
return "astro";
|
|
13
|
+
throw new Error("Unable to detect framework.");
|
|
14
|
+
}, createHandler = (handlerFunc) => {
|
|
15
|
+
const framework = detectFramework(), handlerLogic = async ({
|
|
16
|
+
// eslint-disable-next-line
|
|
17
|
+
req,
|
|
18
|
+
res
|
|
19
|
+
}) => {
|
|
20
|
+
try {
|
|
21
|
+
const data = await handlerFunc();
|
|
22
|
+
return res && (res.writeHead(200, { "Content-Type": "application/json" }), res.end(JSON.stringify(data))), data;
|
|
23
|
+
} catch (error) {
|
|
24
|
+
return error instanceof Error ? (res && (res.writeHead(500, { "Content-Type": "application/json" }), res.end(JSON.stringify({ error: error.message }))), { error: error.message }) : (res && (res.writeHead(500, { "Content-Type": "application/json" }), res.end(JSON.stringify({ error: "An unexpected error occurred" }))), { error: "An unexpected error occurred" });
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
if (framework === "nextjs")
|
|
28
|
+
return async (req, res) => {
|
|
29
|
+
res.setHeader("Access-Control-Allow-Origin", "*"), res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"), res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"), await handlerLogic({ req, res });
|
|
30
|
+
};
|
|
31
|
+
if (framework === "nuxt")
|
|
32
|
+
return defineEventHandler(async (event) => {
|
|
33
|
+
const req = event.node.req, res = event.node.res;
|
|
34
|
+
return handlerLogic({ req, res });
|
|
35
|
+
});
|
|
36
|
+
if (framework === "sveltekit")
|
|
37
|
+
return {
|
|
38
|
+
GET: async ({ request }) => {
|
|
39
|
+
const result = await handlerLogic({ req: request });
|
|
40
|
+
return new Response(JSON.stringify(result), {
|
|
41
|
+
headers: { "Content-Type": "application/json" }
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
if (framework === "remix")
|
|
46
|
+
return {
|
|
47
|
+
loader: async ({ request }) => {
|
|
48
|
+
const result = await handlerLogic({ req: request });
|
|
49
|
+
return new Response(JSON.stringify(result), {
|
|
50
|
+
headers: { "Content-Type": "application/json" }
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
if (framework === "astro")
|
|
55
|
+
return {
|
|
56
|
+
get: async ({ request }) => {
|
|
57
|
+
const result = await handlerLogic({ req: request });
|
|
58
|
+
return {
|
|
59
|
+
body: JSON.stringify(result),
|
|
60
|
+
headers: { "Content-Type": "application/json" }
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
throw new Error(`Unsupported framework: ${framework}`);
|
|
65
|
+
};
|
|
66
|
+
export {
|
|
67
|
+
createHandler
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=create-handler.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-handler.mjs","sources":["../../src/shared/create-handler.ts"],"sourcesContent":["import {defineEventHandler, type H3Event} from 'h3' // For Nuxt.js/Nitro\nimport type {IncomingMessage, ServerResponse} from 'http'\n\n// Utility function to detect the framework at runtime\nconst detectFramework = (): string => {\n if (process.env.NEXT_RUNTIME) {\n return 'nextjs'\n } else if (process.env.NUXT_ENV) {\n return 'nuxt'\n } else if (process.env.SVELTEKIT_ENV) {\n return 'sveltekit'\n } else if (process.env.REMIX_ENV) {\n return 'remix'\n } else if (process.env.ASTRO_ENV) {\n return 'astro'\n }\n throw new Error('Unable to detect framework.')\n}\n\n// Create a generic handler with predefined logic\nconst createHandler = (handlerFunc: () => Promise<unknown>) => {\n const framework = detectFramework()\n\n // Handler logic to fetch Mailchimp data\n const handlerLogic = async ({\n // eslint-disable-next-line\n req,\n res,\n }: {\n req: IncomingMessage | Request\n res?: ServerResponse\n }): Promise<unknown> => {\n try {\n const data = await handlerFunc()\n\n if (res) {\n // Send response directly for frameworks like Next.js and Nuxt.js\n res.writeHead(200, {'Content-Type': 'application/json'})\n res.end(JSON.stringify(data))\n }\n\n // Return the response for frameworks like SvelteKit, Remix, and Astro\n return data\n } catch (error) {\n if (error instanceof Error) {\n if (res) {\n res.writeHead(500, {'Content-Type': 'application/json'})\n res.end(JSON.stringify({error: error.message}))\n }\n return {error: error.message}\n }\n // Handle non-Error types (e.g., strings, objects)\n if (res) {\n res.writeHead(500, {'Content-Type': 'application/json'})\n res.end(JSON.stringify({error: 'An unexpected error occurred'}))\n }\n return {error: 'An unexpected error occurred'}\n }\n }\n\n // Framework-specific implementations\n if (framework === 'nextjs') {\n return async (req: IncomingMessage, res: ServerResponse) => {\n // Set CORS headers\n res.setHeader('Access-Control-Allow-Origin', '*') // Allow all origins\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS') // Allowed HTTP methods\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization') // Allowed headers\n\n await handlerLogic({req, res})\n }\n } else if (framework === 'nuxt') {\n return defineEventHandler(async (event: H3Event) => {\n const req = event.node.req\n const res = event.node.res\n return handlerLogic({req, res})\n })\n } else if (framework === 'sveltekit') {\n return {\n GET: async ({request}: {request: Request}) => {\n const result = await handlerLogic({req: request})\n return new Response(JSON.stringify(result), {\n headers: {'Content-Type': 'application/json'},\n })\n },\n }\n } else if (framework === 'remix') {\n return {\n loader: async ({request}: {request: Request}) => {\n const result = await handlerLogic({req: request})\n return new Response(JSON.stringify(result), {\n headers: {'Content-Type': 'application/json'},\n })\n },\n }\n } else if (framework === 'astro') {\n return {\n get: async ({request}: {request: Request}) => {\n const result = await handlerLogic({req: request})\n return {\n body: JSON.stringify(result),\n headers: {'Content-Type': 'application/json'},\n }\n },\n }\n }\n throw new Error(`Unsupported framework: ${framework}`)\n}\n\nexport default createHandler\n"],"names":[],"mappings":";AAIA,MAAM,kBAAkB,MAAc;AACpC,MAAI,QAAQ,IAAI;AACP,WAAA;AACF,MAAI,QAAQ,IAAI;AACd,WAAA;AACF,MAAI,QAAQ,IAAI;AACd,WAAA;AACF,MAAI,QAAQ,IAAI;AACd,WAAA;AACF,MAAI,QAAQ,IAAI;AACd,WAAA;AAEH,QAAA,IAAI,MAAM,6BAA6B;AAC/C,GAGM,gBAAgB,CAAC,gBAAwC;AAC7D,QAAM,YAAY,mBAGZ,eAAe,OAAO;AAAA;AAAA,IAE1B;AAAA,IACA;AAAA,EAAA,MAIsB;AAClB,QAAA;AACI,YAAA,OAAO,MAAM,YAAY;AAE/B,aAAI,QAEF,IAAI,UAAU,KAAK,EAAC,gBAAgB,mBAAA,CAAmB,GACvD,IAAI,IAAI,KAAK,UAAU,IAAI,CAAC,IAIvB;AAAA,aACA,OAAO;AACV,aAAA,iBAAiB,SACf,QACF,IAAI,UAAU,KAAK,EAAC,gBAAgB,oBAAmB,GACvD,IAAI,IAAI,KAAK,UAAU,EAAC,OAAO,MAAM,QAAQ,CAAA,CAAC,IAEzC,EAAC,OAAO,MAAM,QAAO,MAG1B,QACF,IAAI,UAAU,KAAK,EAAC,gBAAgB,mBAAmB,CAAA,GACvD,IAAI,IAAI,KAAK,UAAU,EAAC,OAAO,+BAAA,CAA+B,CAAC,IAE1D,EAAC,OAAO;IAA8B;AAAA,EAEjD;AAGA,MAAI,cAAc;AACT,WAAA,OAAO,KAAsB,QAAwB;AAE1D,UAAI,UAAU,+BAA+B,GAAG,GAChD,IAAI,UAAU,gCAAgC,iCAAiC,GAC/E,IAAI,UAAU,gCAAgC,6BAA6B,GAE3E,MAAM,aAAa,EAAC,KAAK,KAAI;AAAA,IAC/B;AACK,MAAI,cAAc;AAChB,WAAA,mBAAmB,OAAO,UAAmB;AAClD,YAAM,MAAM,MAAM,KAAK,KACjB,MAAM,MAAM,KAAK;AACvB,aAAO,aAAa,EAAC,KAAK,KAAI;AAAA,IAAA,CAC/B;AACI,MAAI,cAAc;AAChB,WAAA;AAAA,MACL,KAAK,OAAO,EAAC,cAAiC;AAC5C,cAAM,SAAS,MAAM,aAAa,EAAC,KAAK,SAAQ;AAChD,eAAO,IAAI,SAAS,KAAK,UAAU,MAAM,GAAG;AAAA,UAC1C,SAAS,EAAC,gBAAgB,mBAAkB;AAAA,QAAA,CAC7C;AAAA,MAAA;AAAA,IAEL;AACK,MAAI,cAAc;AAChB,WAAA;AAAA,MACL,QAAQ,OAAO,EAAC,cAAiC;AAC/C,cAAM,SAAS,MAAM,aAAa,EAAC,KAAK,SAAQ;AAChD,eAAO,IAAI,SAAS,KAAK,UAAU,MAAM,GAAG;AAAA,UAC1C,SAAS,EAAC,gBAAgB,mBAAkB;AAAA,QAAA,CAC7C;AAAA,MAAA;AAAA,IAEL;AACK,MAAI,cAAc;AAChB,WAAA;AAAA,MACL,KAAK,OAAO,EAAC,cAAiC;AAC5C,cAAM,SAAS,MAAM,aAAa,EAAC,KAAK,SAAQ;AACzC,eAAA;AAAA,UACL,MAAM,KAAK,UAAU,MAAM;AAAA,UAC3B,SAAS,EAAC,gBAAgB,mBAAkB;AAAA,QAC9C;AAAA,MAAA;AAAA,IAEJ;AAEF,QAAM,IAAI,MAAM,0BAA0B,SAAS,EAAE;AACvD;"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type {ComponentType} from 'react'
|
|
2
|
+
import type {FC} from 'react'
|
|
3
|
+
import type {HTMLProps} from 'react'
|
|
4
|
+
import {Plugin as Plugin_2} from 'sanity'
|
|
5
|
+
|
|
6
|
+
declare type FieldChoice = {
|
|
7
|
+
label: string
|
|
8
|
+
value: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
declare interface FieldComponentProps {
|
|
12
|
+
field: FormField
|
|
13
|
+
fieldState: FieldState
|
|
14
|
+
error?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
declare type FieldOptions = {
|
|
18
|
+
placeholder?: string
|
|
19
|
+
defaultValue?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
declare interface FieldState {
|
|
23
|
+
value?: string | number | readonly string[]
|
|
24
|
+
onChange: (value: unknown) => void
|
|
25
|
+
onBlur?: () => void
|
|
26
|
+
ref?: unknown
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export declare type FormDataProps = {
|
|
30
|
+
title: string
|
|
31
|
+
id: {
|
|
32
|
+
current: string
|
|
33
|
+
}
|
|
34
|
+
fields?: FormField[]
|
|
35
|
+
submitButton?: {
|
|
36
|
+
text: string
|
|
37
|
+
position: 'left' | 'center' | 'right'
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
declare type FormField = {
|
|
42
|
+
type: string
|
|
43
|
+
label?: string
|
|
44
|
+
name: string
|
|
45
|
+
required: boolean
|
|
46
|
+
validation?: ValidationRule[]
|
|
47
|
+
options?: FieldOptions
|
|
48
|
+
choices?: FieldChoice[]
|
|
49
|
+
_key: string
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export declare const FormRenderer: FC<FormRendererProps>
|
|
53
|
+
|
|
54
|
+
declare interface FormRendererProps extends HTMLProps<HTMLFormElement> {
|
|
55
|
+
formData?: FormDataProps
|
|
56
|
+
getFieldState?: (fieldName: string) => FieldState
|
|
57
|
+
getFieldError?: (fieldName: string) => string | undefined
|
|
58
|
+
fieldComponents?: Record<string, ComponentType<FieldComponentProps>>
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export declare const formSchema: Plugin_2<void>
|
|
62
|
+
|
|
63
|
+
declare type ValidationRule = {
|
|
64
|
+
type: string
|
|
65
|
+
value: string
|
|
66
|
+
message: string
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export {}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type {ComponentType} from 'react'
|
|
2
|
+
import type {FC} from 'react'
|
|
3
|
+
import type {HTMLProps} from 'react'
|
|
4
|
+
import {Plugin as Plugin_2} from 'sanity'
|
|
5
|
+
|
|
6
|
+
declare type FieldChoice = {
|
|
7
|
+
label: string
|
|
8
|
+
value: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
declare interface FieldComponentProps {
|
|
12
|
+
field: FormField
|
|
13
|
+
fieldState: FieldState
|
|
14
|
+
error?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
declare type FieldOptions = {
|
|
18
|
+
placeholder?: string
|
|
19
|
+
defaultValue?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
declare interface FieldState {
|
|
23
|
+
value?: string | number | readonly string[]
|
|
24
|
+
onChange: (value: unknown) => void
|
|
25
|
+
onBlur?: () => void
|
|
26
|
+
ref?: unknown
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export declare type FormDataProps = {
|
|
30
|
+
title: string
|
|
31
|
+
id: {
|
|
32
|
+
current: string
|
|
33
|
+
}
|
|
34
|
+
fields?: FormField[]
|
|
35
|
+
submitButton?: {
|
|
36
|
+
text: string
|
|
37
|
+
position: 'left' | 'center' | 'right'
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
declare type FormField = {
|
|
42
|
+
type: string
|
|
43
|
+
label?: string
|
|
44
|
+
name: string
|
|
45
|
+
required: boolean
|
|
46
|
+
validation?: ValidationRule[]
|
|
47
|
+
options?: FieldOptions
|
|
48
|
+
choices?: FieldChoice[]
|
|
49
|
+
_key: string
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export declare const FormRenderer: FC<FormRendererProps>
|
|
53
|
+
|
|
54
|
+
declare interface FormRendererProps extends HTMLProps<HTMLFormElement> {
|
|
55
|
+
formData?: FormDataProps
|
|
56
|
+
getFieldState?: (fieldName: string) => FieldState
|
|
57
|
+
getFieldError?: (fieldName: string) => string | undefined
|
|
58
|
+
fieldComponents?: Record<string, ComponentType<FieldComponentProps>>
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export declare const formSchema: Plugin_2<void>
|
|
62
|
+
|
|
63
|
+
declare type ValidationRule = {
|
|
64
|
+
type: string
|
|
65
|
+
value: string
|
|
66
|
+
message: string
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export {}
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: !0 });
|
|
3
|
-
var sanity = require("sanity"),
|
|
4
|
-
function _interopDefaultCompat(e) {
|
|
5
|
-
return e && typeof e == "object" && "default" in e ? e : { default: e };
|
|
6
|
-
}
|
|
7
|
-
var mailchimp__default = /* @__PURE__ */ _interopDefaultCompat(mailchimp);
|
|
3
|
+
var sanity = require("sanity"), jsxRuntime = require("react/jsx-runtime"), fa = require("react-icons/fa"), lu = require("react-icons/lu");
|
|
8
4
|
const DefaultField = ({ field, fieldState, error }) => {
|
|
9
5
|
const { type, label, name, options = {}, choices = [] } = field;
|
|
10
6
|
if (!type || !name) return null;
|
|
@@ -333,148 +329,7 @@ const DefaultField = ({ field, fieldState, error }) => {
|
|
|
333
329
|
name: "form-toolkit_form-schema",
|
|
334
330
|
schema
|
|
335
331
|
// plugins: [structureTool({defaultDocumentNode})],
|
|
336
|
-
})), Option$1 = (option) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Card, { "data-as": "button", padding: 3, radius: 2, tone: "inherit", children: [
|
|
337
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 2, textOverflow: "ellipsis", children: option.name }),
|
|
338
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Card, { paddingTop: 2, tone: "inherit", style: { background: "inherit" }, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, textOverflow: "ellipsis", children: `ID: ${option.value}` }) })
|
|
339
|
-
] }), hubSpotInput = sanity.definePlugin((options) => ({
|
|
340
|
-
name: "sanity-plugin-form-toolkit_hubspot-input",
|
|
341
|
-
plugins: [
|
|
342
|
-
sanityPluginAsyncList.asyncList({
|
|
343
|
-
schemaType: "hubSpotForm",
|
|
344
|
-
loader: async () => await (await fetch(options.url)).json(),
|
|
345
|
-
autocompleteProps: {
|
|
346
|
-
renderOption: (option) => Option$1(option),
|
|
347
|
-
renderValue(value, option) {
|
|
348
|
-
return option?.name ?? value;
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
})
|
|
352
|
-
]
|
|
353
|
-
})), detectFramework = () => {
|
|
354
|
-
if (process.env.NEXT_RUNTIME)
|
|
355
|
-
return "nextjs";
|
|
356
|
-
if (process.env.NUXT_ENV)
|
|
357
|
-
return "nuxt";
|
|
358
|
-
if (process.env.SVELTEKIT_ENV)
|
|
359
|
-
return "sveltekit";
|
|
360
|
-
if (process.env.REMIX_ENV)
|
|
361
|
-
return "remix";
|
|
362
|
-
if (process.env.ASTRO_ENV)
|
|
363
|
-
return "astro";
|
|
364
|
-
throw new Error("Unable to detect framework.");
|
|
365
|
-
}, createHandler = (handlerFunc) => {
|
|
366
|
-
const framework = detectFramework(), handlerLogic = async ({
|
|
367
|
-
// eslint-disable-next-line
|
|
368
|
-
req,
|
|
369
|
-
res
|
|
370
|
-
}) => {
|
|
371
|
-
try {
|
|
372
|
-
const data = await handlerFunc();
|
|
373
|
-
return res && (res.writeHead(200, { "Content-Type": "application/json" }), res.end(JSON.stringify(data))), data;
|
|
374
|
-
} catch (error) {
|
|
375
|
-
return error instanceof Error ? (res && (res.writeHead(500, { "Content-Type": "application/json" }), res.end(JSON.stringify({ error: error.message }))), { error: error.message }) : (res && (res.writeHead(500, { "Content-Type": "application/json" }), res.end(JSON.stringify({ error: "An unexpected error occurred" }))), { error: "An unexpected error occurred" });
|
|
376
|
-
}
|
|
377
|
-
};
|
|
378
|
-
if (framework === "nextjs")
|
|
379
|
-
return async (req, res) => {
|
|
380
|
-
res.setHeader("Access-Control-Allow-Origin", "*"), res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"), res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"), await handlerLogic({ req, res });
|
|
381
|
-
};
|
|
382
|
-
if (framework === "nuxt")
|
|
383
|
-
return h3.defineEventHandler(async (event) => {
|
|
384
|
-
const req = event.node.req, res = event.node.res;
|
|
385
|
-
return handlerLogic({ req, res });
|
|
386
|
-
});
|
|
387
|
-
if (framework === "sveltekit")
|
|
388
|
-
return {
|
|
389
|
-
GET: async ({ request }) => {
|
|
390
|
-
const result = await handlerLogic({ req: request });
|
|
391
|
-
return new Response(JSON.stringify(result), {
|
|
392
|
-
headers: { "Content-Type": "application/json" }
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
};
|
|
396
|
-
if (framework === "remix")
|
|
397
|
-
return {
|
|
398
|
-
loader: async ({ request }) => {
|
|
399
|
-
const result = await handlerLogic({ req: request });
|
|
400
|
-
return new Response(JSON.stringify(result), {
|
|
401
|
-
headers: { "Content-Type": "application/json" }
|
|
402
|
-
});
|
|
403
|
-
}
|
|
404
|
-
};
|
|
405
|
-
if (framework === "astro")
|
|
406
|
-
return {
|
|
407
|
-
get: async ({ request }) => {
|
|
408
|
-
const result = await handlerLogic({ req: request });
|
|
409
|
-
return {
|
|
410
|
-
body: JSON.stringify(result),
|
|
411
|
-
headers: { "Content-Type": "application/json" }
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
};
|
|
415
|
-
throw new Error(`Unsupported framework: ${framework}`);
|
|
416
|
-
};
|
|
417
|
-
async function fetchHubSpotData({ token }) {
|
|
418
|
-
try {
|
|
419
|
-
const apiResponse = await fetch("https://api.hubapi.com/marketing/v3/forms/?limit=9999", {
|
|
420
|
-
headers: {
|
|
421
|
-
Authorization: `Bearer ${token}`
|
|
422
|
-
}
|
|
423
|
-
});
|
|
424
|
-
if (!apiResponse.ok)
|
|
425
|
-
return console.error(`Failed to fetch data: ${apiResponse.statusText}`), null;
|
|
426
|
-
const { results } = await apiResponse.json();
|
|
427
|
-
return results.map((result) => ({
|
|
428
|
-
...result,
|
|
429
|
-
value: result.id
|
|
430
|
-
}));
|
|
431
|
-
} catch (e) {
|
|
432
|
-
return console.error(e), null;
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
const hubSpotHandler = ({ token }) => createHandler(() => fetchHubSpotData({ token })), Option = (option) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Card, { "data-as": "button", padding: 3, radius: 2, tone: "inherit", children: [
|
|
436
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 2, textOverflow: "ellipsis", children: `${option.form.header.text ? `${option.form.header.text} - ` : ""}${option.value}` }),
|
|
437
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Card, { paddingTop: 2, tone: "inherit", style: { background: "inherit" }, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, textOverflow: "ellipsis", children: `${option.list.name} - ${option.list.stats.member_count} member${option.list.stats.member_count == 1 ? "" : "s"}` }) })
|
|
438
|
-
] }), mailchimpInput = sanity.definePlugin((options) => ({
|
|
439
|
-
name: "sanity-plugin-form-toolkit_mailchimp-input",
|
|
440
|
-
plugins: [
|
|
441
|
-
sanityPluginAsyncList.asyncList({
|
|
442
|
-
schemaType: "mailchimpForm",
|
|
443
|
-
loader: async () => await (await fetch(options.url)).json(),
|
|
444
|
-
autocompleteProps: {
|
|
445
|
-
//@ts-expect-error incorrect typing on props?
|
|
446
|
-
renderOption: (option) => Option(option)
|
|
447
|
-
}
|
|
448
|
-
})
|
|
449
|
-
]
|
|
450
332
|
}));
|
|
451
|
-
async function fetchMailchimpData({
|
|
452
|
-
key,
|
|
453
|
-
server
|
|
454
|
-
}) {
|
|
455
|
-
mailchimp__default.default.setConfig({
|
|
456
|
-
apiKey: key,
|
|
457
|
-
server
|
|
458
|
-
});
|
|
459
|
-
const signupForms = [], { lists } = await mailchimp__default.default.lists.getAllLists();
|
|
460
|
-
for (const list of lists) {
|
|
461
|
-
const { signup_forms } = await mailchimp__default.default.lists.getListSignupForms(list.id);
|
|
462
|
-
for (const form of signup_forms)
|
|
463
|
-
signupForms.push({
|
|
464
|
-
list,
|
|
465
|
-
form,
|
|
466
|
-
value: form.signup_form_url
|
|
467
|
-
});
|
|
468
|
-
}
|
|
469
|
-
return signupForms;
|
|
470
|
-
}
|
|
471
|
-
const mailchimpHandler = (keys) => createHandler(() => fetchMailchimpData(keys));
|
|
472
333
|
exports.FormRenderer = FormRenderer;
|
|
473
|
-
exports.fetchHubSpotData = fetchHubSpotData;
|
|
474
|
-
exports.fetchMailchimpData = fetchMailchimpData;
|
|
475
334
|
exports.formSchema = formSchema;
|
|
476
|
-
exports.hubSpotHandler = hubSpotHandler;
|
|
477
|
-
exports.hubSpotInput = hubSpotInput;
|
|
478
|
-
exports.mailchimpHandler = mailchimpHandler;
|
|
479
|
-
exports.mailchimpInput = mailchimpInput;
|
|
480
335
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/form-schema/components/default-field.tsx","../../src/form-schema/components/form-renderer.tsx","../../src/form-schema/schema-types/form.ts","../../src/form-schema/schema-types/form-field.ts","../../src/form-schema/schema-types/index.ts","../../src/form-schema/index.ts"],"sourcesContent":["import type {ChangeEvent, FC, LegacyRef} from 'react'\n\nimport type {FieldComponentProps} from './types'\n\nexport const DefaultField: FC<FieldComponentProps> = ({field, fieldState, error}) => {\n const {type, label, name, options = {}, choices = []} = field\n if (!type || !name) return null\n\n const {value, onChange, onBlur, ref} = fieldState\n\n const handleChange = (\n e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>,\n ) => {\n onChange(e.target.value)\n }\n\n const handleCheckboxChange = (e: ChangeEvent<HTMLInputElement>, choiceValue: string) => {\n if (Array.isArray(value)) {\n const newValue = e.target.checked\n ? [...value, choiceValue]\n : value.filter((v: string) => v !== choiceValue)\n onChange(newValue)\n } else {\n onChange(e.target.checked ? choiceValue : '')\n }\n }\n\n const renderInput = () => {\n switch (type) {\n case 'textarea':\n return (\n <textarea\n ref={ref as LegacyRef<HTMLTextAreaElement>}\n name={name}\n value={value ?? ''}\n onChange={handleChange}\n onBlur={onBlur}\n placeholder={options.placeholder}\n />\n )\n\n case 'select':\n return (\n <select\n ref={ref as LegacyRef<HTMLSelectElement>}\n name={name}\n value={value ?? ''}\n onChange={handleChange}\n onBlur={onBlur}\n >\n {choices?.map((choice, i) => (\n <option key={i} value={choice.value}>\n {choice.label}\n </option>\n ))}\n </select>\n )\n\n case 'radio':\n return choices?.map((choice, i) => (\n <label key={i}>\n <input\n type=\"radio\"\n name={name}\n ref={ref as LegacyRef<HTMLInputElement>}\n value={choice.value}\n checked={value === choice.value}\n onChange={handleChange}\n onBlur={onBlur}\n />\n {choice.label}\n </label>\n ))\n\n case 'checkbox':\n return choices?.map((choice, i) => (\n <label key={i}>\n <input\n type=\"checkbox\"\n name={name}\n ref={ref as LegacyRef<HTMLInputElement>}\n value={choice.value}\n checked={Array.isArray(value) ? value.includes(choice.value) : value === choice.value}\n onChange={(e) => handleCheckboxChange(e, choice.value)}\n onBlur={onBlur}\n />\n {choice.label}\n </label>\n ))\n\n default:\n return (\n <input\n type={type}\n ref={ref as LegacyRef<HTMLInputElement>}\n name={name}\n value={value ?? options.defaultValue ?? ''}\n onChange={handleChange}\n onBlur={onBlur}\n placeholder={options.placeholder}\n />\n )\n }\n }\n\n return (\n <>\n {label && type != 'hidden' && <label htmlFor={name}>{label}</label>}\n {renderInput()}\n {error && <span className=\"error\">{error}</span>}\n </>\n )\n}\n","import type {ComponentType, FC, HTMLProps} from 'react'\n\nimport {DefaultField} from './default-field'\nimport type {FieldComponentProps, FieldState, FormDataProps, FormField} from './types'\n\ninterface FormRendererProps extends HTMLProps<HTMLFormElement> {\n formData?: FormDataProps\n // Function to get field state for a given field name\n getFieldState?: (fieldName: string) => FieldState\n // Function to get field error for a given field name\n getFieldError?: (fieldName: string) => string | undefined\n // Override default field components\n fieldComponents?: Record<string, ComponentType<FieldComponentProps>>\n}\n\nexport const FormRenderer: FC<FormRendererProps> = (props) => {\n const {\n formData,\n getFieldState = (name) => ({\n value: undefined,\n onChange: () => {},\n name, // Pass name to field for native form handling\n }),\n getFieldError,\n fieldComponents = {},\n children,\n } = props\n const renderField = (field: FormField) => {\n const CustomComponent = fieldComponents[field.type]\n const fieldState = getFieldState(field.name)\n const error = getFieldError?.(field.name)\n\n if (CustomComponent) {\n return <CustomComponent field={field} fieldState={fieldState} error={error} />\n }\n\n return <DefaultField field={field} fieldState={fieldState} error={error} />\n }\n const elProps = Object.assign({}, props)\n delete elProps.formData\n delete elProps.getFieldState\n delete elProps.getFieldError\n delete elProps.fieldComponents\n\n return (\n <form {...elProps} id={elProps.id ?? formData?.id?.current}>\n {formData?.fields?.map((field) => (\n <div key={field._key} className=\"form-field\">\n {renderField(field)}\n </div>\n ))}\n\n {children}\n\n <button type=\"submit\">{formData?.submitButton?.text || 'Submit'}</button>\n </form>\n )\n}\n","import {FaWpforms} from 'react-icons/fa'\nimport {defineField, defineType} from 'sanity'\n\nexport const formType = defineType({\n name: 'form',\n title: 'Form',\n type: 'document',\n icon: FaWpforms,\n fields: [\n defineField({\n name: 'title',\n title: 'Form Title',\n type: 'string',\n description: 'Internal title for the form',\n validation: (Rule) => Rule.required(),\n }),\n defineField({\n name: 'id',\n title: 'Form ID',\n type: 'slug',\n options: {\n source: 'title',\n },\n // validation: (Rule) => Rule.required(),\n }),\n defineField({\n name: 'fields',\n title: 'Form Fields',\n type: 'array',\n of: [{type: 'formField'}],\n }),\n defineField({\n name: 'submitButton',\n title: 'Submit Button',\n type: 'object',\n fields: [\n defineField({\n name: 'text',\n title: 'Button Text',\n type: 'string',\n initialValue: 'Submit',\n }),\n // defineField({\n // name: 'position',\n // title: 'Button Position',\n // type: 'string',\n // options: {\n // list: ['left', 'center', 'right'],\n // },\n // initialValue: 'center',\n // }),\n ],\n }),\n ],\n})\n","import {LuTextCursorInput} from 'react-icons/lu'\nimport {defineField, defineType} from 'sanity'\n\ninterface ValidationContextDocument {\n fields?: Array<{\n name: string\n type?: string\n }>\n}\n// Validation options by field type\nexport const validationTypesByFieldType = {\n checkbox: ['minSelectedCount', 'maxSelectedCount', 'custom'],\n color: ['custom'],\n date: ['minDate', 'maxDate', 'custom'],\n 'datetime-local': ['minDate', 'maxDate', 'custom'],\n email: ['pattern', 'custom'],\n file: ['maxSize', 'fileType', 'custom'],\n hidden: ['custom'],\n number: ['min', 'max', 'custom'],\n // password: ['minLength', 'pattern', 'custom'],\n radio: ['custom'],\n range: ['min', 'max', 'step', 'custom'],\n select: ['custom'],\n tel: ['pattern', 'custom'],\n text: ['minLength', 'maxLength', 'pattern', 'custom'],\n textarea: ['minLength', 'maxLength', 'custom'],\n time: ['custom'],\n url: ['pattern', 'custom'],\n}\nexport const formFieldType = defineType({\n name: 'formField',\n title: 'Form Field',\n type: 'object',\n icon: LuTextCursorInput,\n fields: [\n defineField({\n name: 'type',\n title: 'Field Type',\n type: 'string',\n options: {\n list: Object.keys(validationTypesByFieldType).map((type) => {\n const title = (fieldType: string) => {\n switch (fieldType) {\n case 'datetime-local':\n return 'Date & Time'\n case 'textarea':\n return 'Text Area'\n case 'tel':\n return 'Phone Number'\n default:\n return fieldType.charAt(0).toUpperCase() + fieldType.slice(1)\n }\n }\n return {title: title(type), value: type}\n }),\n },\n }),\n defineField({\n name: 'label',\n title: 'Field Label',\n type: 'string',\n }),\n defineField({\n name: 'name',\n title: 'Field Name',\n type: 'string',\n description:\n 'Must start with a letter and contain only letters, numbers, underscores, or hyphens. Must be unique within the form.',\n validation: (Rule) =>\n Rule.required().custom((name, context) => {\n if (!name) {\n return 'Required'\n }\n // Check format (HTML ID/name rules)\n if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name)) {\n return 'Field name must start with a letter and contain only letters, numbers, underscores, or hyphens'\n }\n\n // Check uniqueness across all fields\n const doc = context.document as ValidationContextDocument\n const allFieldNames = doc?.fields?.map((field) => field.name) || []\n\n // Count occurrences of this name\n const nameCount = allFieldNames.filter((n) => n === name).length\n\n // If we find more than one occurrence (including current field), it's not unique\n if (nameCount > 1) {\n return 'Field name must be unique across all form fields'\n }\n\n // Check for reserved HTML form attributes\n const reservedNames = [\n 'action',\n 'method',\n 'target',\n 'enctype',\n 'accept-charset',\n 'autocomplete',\n 'novalidate',\n 'rel',\n 'submit',\n 'reset',\n ]\n if (reservedNames.includes(name.toLowerCase())) {\n return 'This name is reserved for HTML form attributes. Please choose a different name.'\n }\n\n return true\n }),\n }),\n defineField({\n name: 'required',\n title: 'Required',\n type: 'boolean',\n initialValue: false,\n }),\n // defineField({\n // name: 'validation',\n // title: 'Validation Rules',\n // type: 'array',\n // of: [\n // {\n // type: 'object',\n // fields: [\n // defineField({\n // name: 'type',\n // title: 'Validation Type',\n // type: 'string',\n\n // hidden: ({parent}) => !parent?.type,\n // options: {\n // // TODO: I think this needs to be a custom input component?\n // // list: ({parent}) => (parent?.type ? validationTypesByFieldType[parent.type] : []),\n // list: [],\n // },\n // }),\n // defineField({\n // name: 'value',\n // title: 'Value',\n // type: 'string',\n // }),\n // defineField({\n // name: 'message',\n // title: 'Error Message',\n // type: 'string',\n // }),\n // ],\n // },\n // ],\n // }),\n defineField({\n name: 'choices',\n title: 'Choices',\n type: 'array',\n hidden: ({parent}) => {\n return !['select', 'radio', 'checkbox'].includes(parent?.type)\n },\n of: [\n {\n type: 'object',\n fields: [\n defineField({\n name: 'label',\n title: 'Label',\n type: 'string',\n }),\n defineField({\n name: 'value',\n title: 'Value',\n type: 'string',\n }),\n ],\n },\n ],\n }),\n defineField({\n name: 'options',\n title: 'Field Options',\n type: 'object',\n hidden: ({parent}) => {\n return ['select', 'radio', 'checkbox', 'file'].includes(parent?.type)\n },\n fields: [\n defineField({\n name: 'placeholder',\n title: 'Placeholder',\n type: 'string',\n }),\n defineField({\n name: 'defaultValue',\n title: 'Default Value',\n type: 'string',\n }),\n ],\n }),\n ],\n preview: {\n select: {\n label: 'label',\n name: 'name',\n type: 'type',\n },\n prepare({label, name, type}) {\n return {\n title: label || name,\n subtitle: type,\n }\n },\n },\n})\n","import type {SchemaTypeDefinition} from 'sanity'\n\nimport {formType} from './form'\nimport {formFieldType} from './form-field'\n\nexport const schema: {types: SchemaTypeDefinition[]} = {\n types: [formType, formFieldType],\n}\n","import {definePlugin} from 'sanity'\n\n// import {structureTool} from 'sanity/structure'\nimport {FormRenderer} from './components/form-renderer'\nimport {schema} from './schema-types'\n// import {defaultDocumentNode} from './structure'\n\n/**\n * Usage in `sanity.config.ts` (or .js)\n *\n * ```ts\n * import {defineConfig} from 'sanity'\n * import {formSchema} from '@sanity/form-toolkit'\n *\n * export default defineConfig({\n * // ...\n * plugins: [formSchema()],\n * })\n * ```\n */\nexport type {FormDataProps} from './components/types'\nexport {FormRenderer}\nexport const formSchema = definePlugin(() => {\n return {\n name: 'form-toolkit_form-schema',\n schema,\n // plugins: [structureTool({defaultDocumentNode})],\n }\n})\n"],"names":["jsx","jsxs","Fragment","defineType","FaWpforms","defineField","LuTextCursorInput","definePlugin"],"mappings":"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"}
|