@uptrademedia/site-kit 1.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 +305 -0
- package/dist/analytics/index.js +88 -0
- package/dist/analytics/index.js.map +1 -0
- package/dist/analytics/index.mjs +70 -0
- package/dist/analytics/index.mjs.map +1 -0
- package/dist/api-N35S3EES.js +57 -0
- package/dist/api-N35S3EES.js.map +1 -0
- package/dist/api-SYBTK7Z7.mjs +4 -0
- package/dist/api-SYBTK7Z7.mjs.map +1 -0
- package/dist/blog/index.js +200 -0
- package/dist/blog/index.js.map +1 -0
- package/dist/blog/index.mjs +194 -0
- package/dist/blog/index.mjs.map +1 -0
- package/dist/chunk-3MUOUXHV.js +3721 -0
- package/dist/chunk-3MUOUXHV.js.map +1 -0
- package/dist/chunk-4HVYXYQL 2.mjs +255 -0
- package/dist/chunk-4HVYXYQL.mjs +255 -0
- package/dist/chunk-4HVYXYQL.mjs.map +1 -0
- package/dist/chunk-7H6I3ECV.mjs +120 -0
- package/dist/chunk-7H6I3ECV.mjs.map +1 -0
- package/dist/chunk-COI6GOX2.mjs +3679 -0
- package/dist/chunk-COI6GOX2.mjs.map +1 -0
- package/dist/chunk-EQCVQC35.js +35 -0
- package/dist/chunk-EQCVQC35.js 2.map +1 -0
- package/dist/chunk-EQCVQC35.js.map +1 -0
- package/dist/chunk-FEBYQGY4 2.mjs +251 -0
- package/dist/chunk-FEBYQGY4.mjs +251 -0
- package/dist/chunk-FEBYQGY4.mjs.map +1 -0
- package/dist/chunk-FKVJOT2F.mjs +796 -0
- package/dist/chunk-FKVJOT2F.mjs.map +1 -0
- package/dist/chunk-GQ6ZOU2N.mjs +134 -0
- package/dist/chunk-GQ6ZOU2N.mjs.map +1 -0
- package/dist/chunk-HCFPU7TU.js +137 -0
- package/dist/chunk-HCFPU7TU.js.map +1 -0
- package/dist/chunk-NYKRE2FL 2.mjs +31 -0
- package/dist/chunk-NYKRE2FL.mjs +31 -0
- package/dist/chunk-NYKRE2FL.mjs 2.map +1 -0
- package/dist/chunk-NYKRE2FL.mjs.map +1 -0
- package/dist/chunk-QP5NCO2E.js +133 -0
- package/dist/chunk-QP5NCO2E.js.map +1 -0
- package/dist/chunk-RV7H3I6J.js +255 -0
- package/dist/chunk-RV7H3I6J.js 2.map +1 -0
- package/dist/chunk-RV7H3I6J.js.map +1 -0
- package/dist/chunk-SBVEYCSV.js +140 -0
- package/dist/chunk-SBVEYCSV.js.map +1 -0
- package/dist/chunk-TUKGA3UK.js +257 -0
- package/dist/chunk-TUKGA3UK.js 2.map +1 -0
- package/dist/chunk-TUKGA3UK.js.map +1 -0
- package/dist/chunk-V3F5J6CV.js +801 -0
- package/dist/chunk-V3F5J6CV.js.map +1 -0
- package/dist/chunk-WPSRS352.mjs +135 -0
- package/dist/chunk-WPSRS352.mjs.map +1 -0
- package/dist/commerce/index.js +157 -0
- package/dist/commerce/index.js.map +1 -0
- package/dist/commerce/index.mjs +4 -0
- package/dist/commerce/index.mjs.map +1 -0
- package/dist/commerce/server.js +186 -0
- package/dist/commerce/server.js.map +1 -0
- package/dist/commerce/server.mjs +176 -0
- package/dist/commerce/server.mjs.map +1 -0
- package/dist/engage/index.js +50 -0
- package/dist/engage/index.js.map +1 -0
- package/dist/engage/index.mjs +44 -0
- package/dist/engage/index.mjs.map +1 -0
- package/dist/forms/index.js +1053 -0
- package/dist/forms/index.js.map +1 -0
- package/dist/forms/index.mjs +1035 -0
- package/dist/forms/index.mjs.map +1 -0
- package/dist/generators-7Y5ABRYV 2.mjs +161 -0
- package/dist/generators-7Y5ABRYV.mjs +161 -0
- package/dist/generators-7Y5ABRYV.mjs 2.map +1 -0
- package/dist/generators-7Y5ABRYV.mjs.map +1 -0
- package/dist/generators-GWIYCA5M.js +171 -0
- package/dist/generators-GWIYCA5M.js 2.map +1 -0
- package/dist/generators-GWIYCA5M.js.map +1 -0
- package/dist/index 2.mjs +74 -0
- package/dist/index.js +326 -0
- package/dist/index.js 2.map +1 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +222 -0
- package/dist/index.mjs.map +1 -0
- package/dist/migrator-V6KS75EA 2.mjs +265 -0
- package/dist/migrator-V6KS75EA.mjs +265 -0
- package/dist/migrator-V6KS75EA.mjs 2.map +1 -0
- package/dist/migrator-V6KS75EA.mjs.map +1 -0
- package/dist/migrator-XKM7YQCY.js +272 -0
- package/dist/migrator-XKM7YQCY.js 2.map +1 -0
- package/dist/migrator-XKM7YQCY.js.map +1 -0
- package/dist/scanner-MF7P3CDE 2.mjs +14386 -0
- package/dist/scanner-MF7P3CDE.mjs +14386 -0
- package/dist/scanner-MF7P3CDE.mjs 2.map +1 -0
- package/dist/scanner-MF7P3CDE.mjs.map +1 -0
- package/dist/scanner-NT6YG4TD 2.js +14397 -0
- package/dist/scanner-NT6YG4TD.js +14397 -0
- package/dist/scanner-NT6YG4TD.js 2.map +1 -0
- package/dist/scanner-NT6YG4TD.js.map +1 -0
- package/dist/seo/index.js +447 -0
- package/dist/seo/index.js.map +1 -0
- package/dist/seo/index.mjs +411 -0
- package/dist/seo/index.mjs.map +1 -0
- package/dist/seo/server.js +66 -0
- package/dist/seo/server.js.map +1 -0
- package/dist/seo/server.mjs +5 -0
- package/dist/seo/server.mjs.map +1 -0
- package/dist/setup/index.js +1050 -0
- package/dist/setup/index.js.map +1 -0
- package/dist/setup/index.mjs +1046 -0
- package/dist/setup/index.mjs.map +1 -0
- package/dist/sitemap/index.js +212 -0
- package/dist/sitemap/index.js.map +1 -0
- package/dist/sitemap/index.mjs +206 -0
- package/dist/sitemap/index.mjs.map +1 -0
- package/dist/web-vitals-BH55V7EJ.js +252 -0
- package/dist/web-vitals-BH55V7EJ.js 2.map +1 -0
- package/dist/web-vitals-BH55V7EJ.js.map +1 -0
- package/dist/web-vitals-RJYPWAR3 2.mjs +241 -0
- package/dist/web-vitals-RJYPWAR3.mjs +241 -0
- package/dist/web-vitals-RJYPWAR3.mjs 2.map +1 -0
- package/dist/web-vitals-RJYPWAR3.mjs.map +1 -0
- package/package.json +118 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
10
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
11
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
30
|
+
|
|
31
|
+
exports.__commonJS = __commonJS;
|
|
32
|
+
exports.__publicField = __publicField;
|
|
33
|
+
exports.__toESM = __toESM;
|
|
34
|
+
//# sourceMappingURL=chunk-EQCVQC35.js.map
|
|
35
|
+
//# sourceMappingURL=chunk-EQCVQC35.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-EQCVQC35.js"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-EQCVQC35.js"}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
// src/forms/formsApi.ts
|
|
2
|
+
var config = null;
|
|
3
|
+
function configureFormsApi(options) {
|
|
4
|
+
config = options;
|
|
5
|
+
}
|
|
6
|
+
function getConfig() {
|
|
7
|
+
if (config) return config;
|
|
8
|
+
if (typeof window !== "undefined") {
|
|
9
|
+
const apiUrl = window.__SITE_KIT_API_URL__;
|
|
10
|
+
const apiKey = window.__SITE_KIT_API_KEY__;
|
|
11
|
+
if (apiUrl && apiKey) {
|
|
12
|
+
return { baseUrl: apiUrl, apiKey };
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
throw new Error(
|
|
16
|
+
"Forms API not configured. Either wrap your app in SiteKitProvider or call configureFormsApi() first."
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
async function apiRequest(method, path, body) {
|
|
20
|
+
const { baseUrl, apiKey, getAuthToken } = getConfig();
|
|
21
|
+
const headers = {
|
|
22
|
+
"Content-Type": "application/json"
|
|
23
|
+
};
|
|
24
|
+
if (apiKey) {
|
|
25
|
+
headers["x-api-key"] = apiKey;
|
|
26
|
+
} else if (getAuthToken) {
|
|
27
|
+
const token = await getAuthToken();
|
|
28
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
29
|
+
}
|
|
30
|
+
const response = await fetch(`${baseUrl}${path}`, {
|
|
31
|
+
method,
|
|
32
|
+
headers,
|
|
33
|
+
body: body ? JSON.stringify(body) : void 0
|
|
34
|
+
});
|
|
35
|
+
if (!response.ok) {
|
|
36
|
+
const error = await response.json().catch(() => ({ message: response.statusText }));
|
|
37
|
+
throw new Error(error.message || `API error: ${response.status}`);
|
|
38
|
+
}
|
|
39
|
+
if (response.status === 204) {
|
|
40
|
+
return void 0;
|
|
41
|
+
}
|
|
42
|
+
return response.json();
|
|
43
|
+
}
|
|
44
|
+
var formsApi = {
|
|
45
|
+
/**
|
|
46
|
+
* List all forms for a project
|
|
47
|
+
*/
|
|
48
|
+
async list(options = {}) {
|
|
49
|
+
const params = new URLSearchParams();
|
|
50
|
+
if (options.projectId) params.set("projectId", options.projectId);
|
|
51
|
+
if (options.formType) params.set("formType", options.formType);
|
|
52
|
+
if (options.isActive !== void 0) params.set("isActive", String(options.isActive));
|
|
53
|
+
if (options.search) params.set("search", options.search);
|
|
54
|
+
const query = params.toString();
|
|
55
|
+
const result = await apiRequest("GET", `/forms${query ? `?${query}` : ""}`);
|
|
56
|
+
return result.data;
|
|
57
|
+
},
|
|
58
|
+
/**
|
|
59
|
+
* Get a single form by ID or slug
|
|
60
|
+
*/
|
|
61
|
+
async get(idOrSlug) {
|
|
62
|
+
return apiRequest("GET", `/forms/${idOrSlug}`);
|
|
63
|
+
},
|
|
64
|
+
/**
|
|
65
|
+
* Create a new form
|
|
66
|
+
*/
|
|
67
|
+
async create(input) {
|
|
68
|
+
return apiRequest("POST", "/forms", input);
|
|
69
|
+
},
|
|
70
|
+
/**
|
|
71
|
+
* Update an existing form
|
|
72
|
+
*/
|
|
73
|
+
async update(id, input) {
|
|
74
|
+
return apiRequest("PUT", `/forms/${id}`, input);
|
|
75
|
+
},
|
|
76
|
+
/**
|
|
77
|
+
* Delete a form
|
|
78
|
+
*/
|
|
79
|
+
async delete(id) {
|
|
80
|
+
return apiRequest("DELETE", `/forms/${id}`);
|
|
81
|
+
},
|
|
82
|
+
/**
|
|
83
|
+
* Add a field to an existing form
|
|
84
|
+
*/
|
|
85
|
+
async addField(formId, field2) {
|
|
86
|
+
const form = await formsApi.get(formId);
|
|
87
|
+
const maxSortOrder = Math.max(0, ...(form.fields || []).map((f) => f.sortOrder || 0));
|
|
88
|
+
return formsApi.update(formId, {
|
|
89
|
+
fields: [
|
|
90
|
+
...form.fields || [],
|
|
91
|
+
{ ...field2, sortOrder: field2.sortOrder ?? maxSortOrder + 1 }
|
|
92
|
+
]
|
|
93
|
+
});
|
|
94
|
+
},
|
|
95
|
+
/**
|
|
96
|
+
* Update a field in an existing form
|
|
97
|
+
*/
|
|
98
|
+
async updateField(formId, fieldSlug, updates) {
|
|
99
|
+
const form = await formsApi.get(formId);
|
|
100
|
+
return formsApi.update(formId, {
|
|
101
|
+
fields: (form.fields || []).map(
|
|
102
|
+
(f) => f.slug === fieldSlug ? { ...f, ...updates } : f
|
|
103
|
+
)
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
/**
|
|
107
|
+
* Remove a field from a form
|
|
108
|
+
*/
|
|
109
|
+
async removeField(formId, fieldSlug) {
|
|
110
|
+
const form = await formsApi.get(formId);
|
|
111
|
+
return formsApi.update(formId, {
|
|
112
|
+
fields: (form.fields || []).filter((f) => f.slug !== fieldSlug)
|
|
113
|
+
});
|
|
114
|
+
},
|
|
115
|
+
/**
|
|
116
|
+
* Reorder fields in a form
|
|
117
|
+
*/
|
|
118
|
+
async reorderFields(formId, fieldSlugs) {
|
|
119
|
+
const form = await formsApi.get(formId);
|
|
120
|
+
const fieldsMap = new Map((form.fields || []).map((f) => [f.slug, f]));
|
|
121
|
+
const orderedFields = fieldSlugs.map((slug, index) => {
|
|
122
|
+
const field2 = fieldsMap.get(slug);
|
|
123
|
+
if (!field2) throw new Error(`Field not found: ${slug}`);
|
|
124
|
+
return { ...field2, sortOrder: index };
|
|
125
|
+
});
|
|
126
|
+
return formsApi.update(formId, { fields: orderedFields });
|
|
127
|
+
},
|
|
128
|
+
/**
|
|
129
|
+
* Clone a form
|
|
130
|
+
*/
|
|
131
|
+
async clone(formId, newSlug, newName) {
|
|
132
|
+
const form = await formsApi.get(formId);
|
|
133
|
+
return formsApi.create({
|
|
134
|
+
projectId: form.projectId,
|
|
135
|
+
slug: newSlug,
|
|
136
|
+
name: newName || `${form.name} (Copy)`,
|
|
137
|
+
description: form.description,
|
|
138
|
+
formType: form.formType,
|
|
139
|
+
successMessage: form.successMessage,
|
|
140
|
+
redirectUrl: form.redirectUrl,
|
|
141
|
+
notificationEmails: form.notificationEmails,
|
|
142
|
+
submitButtonText: form.submitButtonText,
|
|
143
|
+
layout: form.layout,
|
|
144
|
+
showProgress: form.showProgress,
|
|
145
|
+
enableSaveDraft: form.enableSaveDraft,
|
|
146
|
+
isActive: false,
|
|
147
|
+
// Clone as inactive
|
|
148
|
+
fields: (form.fields || []).map(({ id, ...field2 }) => field2),
|
|
149
|
+
// Remove IDs
|
|
150
|
+
steps: (form.steps || []).map(({ id, ...step }) => step)
|
|
151
|
+
// Remove IDs
|
|
152
|
+
});
|
|
153
|
+
},
|
|
154
|
+
/**
|
|
155
|
+
* Activate or deactivate a form
|
|
156
|
+
*/
|
|
157
|
+
async setActive(formId, isActive) {
|
|
158
|
+
return formsApi.update(formId, { isActive });
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
var field = {
|
|
162
|
+
text: (slug, label, options) => ({
|
|
163
|
+
slug,
|
|
164
|
+
label,
|
|
165
|
+
fieldType: "text",
|
|
166
|
+
...options
|
|
167
|
+
}),
|
|
168
|
+
email: (slug, label, options) => ({
|
|
169
|
+
slug,
|
|
170
|
+
label,
|
|
171
|
+
fieldType: "email",
|
|
172
|
+
isRequired: true,
|
|
173
|
+
...options
|
|
174
|
+
}),
|
|
175
|
+
phone: (slug, label, options) => ({
|
|
176
|
+
slug,
|
|
177
|
+
label,
|
|
178
|
+
fieldType: "phone",
|
|
179
|
+
...options
|
|
180
|
+
}),
|
|
181
|
+
textarea: (slug, label, options) => ({
|
|
182
|
+
slug,
|
|
183
|
+
label,
|
|
184
|
+
fieldType: "textarea",
|
|
185
|
+
...options
|
|
186
|
+
}),
|
|
187
|
+
select: (slug, label, choices, options) => ({
|
|
188
|
+
slug,
|
|
189
|
+
label,
|
|
190
|
+
fieldType: "select",
|
|
191
|
+
options: choices,
|
|
192
|
+
...options
|
|
193
|
+
}),
|
|
194
|
+
radio: (slug, label, choices, options) => ({
|
|
195
|
+
slug,
|
|
196
|
+
label,
|
|
197
|
+
fieldType: "radio",
|
|
198
|
+
options: choices,
|
|
199
|
+
...options
|
|
200
|
+
}),
|
|
201
|
+
checkbox: (slug, label, options) => ({
|
|
202
|
+
slug,
|
|
203
|
+
label,
|
|
204
|
+
fieldType: "checkbox",
|
|
205
|
+
...options
|
|
206
|
+
}),
|
|
207
|
+
date: (slug, label, options) => ({
|
|
208
|
+
slug,
|
|
209
|
+
label,
|
|
210
|
+
fieldType: "date",
|
|
211
|
+
...options
|
|
212
|
+
}),
|
|
213
|
+
number: (slug, label, options) => ({
|
|
214
|
+
slug,
|
|
215
|
+
label,
|
|
216
|
+
fieldType: "number",
|
|
217
|
+
...options
|
|
218
|
+
}),
|
|
219
|
+
rating: (slug, label, options) => ({
|
|
220
|
+
slug,
|
|
221
|
+
label,
|
|
222
|
+
fieldType: "rating",
|
|
223
|
+
...options
|
|
224
|
+
}),
|
|
225
|
+
file: (slug, label, options) => ({
|
|
226
|
+
slug,
|
|
227
|
+
label,
|
|
228
|
+
fieldType: "file",
|
|
229
|
+
...options
|
|
230
|
+
}),
|
|
231
|
+
hidden: (slug, defaultValue) => ({
|
|
232
|
+
slug,
|
|
233
|
+
label: "",
|
|
234
|
+
fieldType: "hidden",
|
|
235
|
+
defaultValue
|
|
236
|
+
}),
|
|
237
|
+
heading: (slug, label) => ({
|
|
238
|
+
slug,
|
|
239
|
+
label,
|
|
240
|
+
fieldType: "heading"
|
|
241
|
+
}),
|
|
242
|
+
paragraph: (slug, label) => ({
|
|
243
|
+
slug,
|
|
244
|
+
label,
|
|
245
|
+
fieldType: "paragraph"
|
|
246
|
+
})
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
export { configureFormsApi, field, formsApi };
|
|
250
|
+
//# sourceMappingURL=chunk-FEBYQGY4.mjs.map
|
|
251
|
+
//# sourceMappingURL=chunk-FEBYQGY4.mjs.map
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
// src/forms/formsApi.ts
|
|
2
|
+
var config = null;
|
|
3
|
+
function configureFormsApi(options) {
|
|
4
|
+
config = options;
|
|
5
|
+
}
|
|
6
|
+
function getConfig() {
|
|
7
|
+
if (config) return config;
|
|
8
|
+
if (typeof window !== "undefined") {
|
|
9
|
+
const apiUrl = window.__SITE_KIT_API_URL__;
|
|
10
|
+
const apiKey = window.__SITE_KIT_API_KEY__;
|
|
11
|
+
if (apiUrl && apiKey) {
|
|
12
|
+
return { baseUrl: apiUrl, apiKey };
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
throw new Error(
|
|
16
|
+
"Forms API not configured. Either wrap your app in SiteKitProvider or call configureFormsApi() first."
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
async function apiRequest(method, path, body) {
|
|
20
|
+
const { baseUrl, apiKey, getAuthToken } = getConfig();
|
|
21
|
+
const headers = {
|
|
22
|
+
"Content-Type": "application/json"
|
|
23
|
+
};
|
|
24
|
+
if (apiKey) {
|
|
25
|
+
headers["x-api-key"] = apiKey;
|
|
26
|
+
} else if (getAuthToken) {
|
|
27
|
+
const token = await getAuthToken();
|
|
28
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
29
|
+
}
|
|
30
|
+
const response = await fetch(`${baseUrl}${path}`, {
|
|
31
|
+
method,
|
|
32
|
+
headers,
|
|
33
|
+
body: body ? JSON.stringify(body) : void 0
|
|
34
|
+
});
|
|
35
|
+
if (!response.ok) {
|
|
36
|
+
const error = await response.json().catch(() => ({ message: response.statusText }));
|
|
37
|
+
throw new Error(error.message || `API error: ${response.status}`);
|
|
38
|
+
}
|
|
39
|
+
if (response.status === 204) {
|
|
40
|
+
return void 0;
|
|
41
|
+
}
|
|
42
|
+
return response.json();
|
|
43
|
+
}
|
|
44
|
+
var formsApi = {
|
|
45
|
+
/**
|
|
46
|
+
* List all forms for a project
|
|
47
|
+
*/
|
|
48
|
+
async list(options = {}) {
|
|
49
|
+
const params = new URLSearchParams();
|
|
50
|
+
if (options.projectId) params.set("projectId", options.projectId);
|
|
51
|
+
if (options.formType) params.set("formType", options.formType);
|
|
52
|
+
if (options.isActive !== void 0) params.set("isActive", String(options.isActive));
|
|
53
|
+
if (options.search) params.set("search", options.search);
|
|
54
|
+
const query = params.toString();
|
|
55
|
+
const result = await apiRequest("GET", `/forms${query ? `?${query}` : ""}`);
|
|
56
|
+
return result.data;
|
|
57
|
+
},
|
|
58
|
+
/**
|
|
59
|
+
* Get a single form by ID or slug
|
|
60
|
+
*/
|
|
61
|
+
async get(idOrSlug) {
|
|
62
|
+
return apiRequest("GET", `/forms/${idOrSlug}`);
|
|
63
|
+
},
|
|
64
|
+
/**
|
|
65
|
+
* Create a new form
|
|
66
|
+
*/
|
|
67
|
+
async create(input) {
|
|
68
|
+
return apiRequest("POST", "/forms", input);
|
|
69
|
+
},
|
|
70
|
+
/**
|
|
71
|
+
* Update an existing form
|
|
72
|
+
*/
|
|
73
|
+
async update(id, input) {
|
|
74
|
+
return apiRequest("PUT", `/forms/${id}`, input);
|
|
75
|
+
},
|
|
76
|
+
/**
|
|
77
|
+
* Delete a form
|
|
78
|
+
*/
|
|
79
|
+
async delete(id) {
|
|
80
|
+
return apiRequest("DELETE", `/forms/${id}`);
|
|
81
|
+
},
|
|
82
|
+
/**
|
|
83
|
+
* Add a field to an existing form
|
|
84
|
+
*/
|
|
85
|
+
async addField(formId, field2) {
|
|
86
|
+
const form = await formsApi.get(formId);
|
|
87
|
+
const maxSortOrder = Math.max(0, ...(form.fields || []).map((f) => f.sortOrder || 0));
|
|
88
|
+
return formsApi.update(formId, {
|
|
89
|
+
fields: [
|
|
90
|
+
...form.fields || [],
|
|
91
|
+
{ ...field2, sortOrder: field2.sortOrder ?? maxSortOrder + 1 }
|
|
92
|
+
]
|
|
93
|
+
});
|
|
94
|
+
},
|
|
95
|
+
/**
|
|
96
|
+
* Update a field in an existing form
|
|
97
|
+
*/
|
|
98
|
+
async updateField(formId, fieldSlug, updates) {
|
|
99
|
+
const form = await formsApi.get(formId);
|
|
100
|
+
return formsApi.update(formId, {
|
|
101
|
+
fields: (form.fields || []).map(
|
|
102
|
+
(f) => f.slug === fieldSlug ? { ...f, ...updates } : f
|
|
103
|
+
)
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
/**
|
|
107
|
+
* Remove a field from a form
|
|
108
|
+
*/
|
|
109
|
+
async removeField(formId, fieldSlug) {
|
|
110
|
+
const form = await formsApi.get(formId);
|
|
111
|
+
return formsApi.update(formId, {
|
|
112
|
+
fields: (form.fields || []).filter((f) => f.slug !== fieldSlug)
|
|
113
|
+
});
|
|
114
|
+
},
|
|
115
|
+
/**
|
|
116
|
+
* Reorder fields in a form
|
|
117
|
+
*/
|
|
118
|
+
async reorderFields(formId, fieldSlugs) {
|
|
119
|
+
const form = await formsApi.get(formId);
|
|
120
|
+
const fieldsMap = new Map((form.fields || []).map((f) => [f.slug, f]));
|
|
121
|
+
const orderedFields = fieldSlugs.map((slug, index) => {
|
|
122
|
+
const field2 = fieldsMap.get(slug);
|
|
123
|
+
if (!field2) throw new Error(`Field not found: ${slug}`);
|
|
124
|
+
return { ...field2, sortOrder: index };
|
|
125
|
+
});
|
|
126
|
+
return formsApi.update(formId, { fields: orderedFields });
|
|
127
|
+
},
|
|
128
|
+
/**
|
|
129
|
+
* Clone a form
|
|
130
|
+
*/
|
|
131
|
+
async clone(formId, newSlug, newName) {
|
|
132
|
+
const form = await formsApi.get(formId);
|
|
133
|
+
return formsApi.create({
|
|
134
|
+
projectId: form.projectId,
|
|
135
|
+
slug: newSlug,
|
|
136
|
+
name: newName || `${form.name} (Copy)`,
|
|
137
|
+
description: form.description,
|
|
138
|
+
formType: form.formType,
|
|
139
|
+
successMessage: form.successMessage,
|
|
140
|
+
redirectUrl: form.redirectUrl,
|
|
141
|
+
notificationEmails: form.notificationEmails,
|
|
142
|
+
submitButtonText: form.submitButtonText,
|
|
143
|
+
layout: form.layout,
|
|
144
|
+
showProgress: form.showProgress,
|
|
145
|
+
enableSaveDraft: form.enableSaveDraft,
|
|
146
|
+
isActive: false,
|
|
147
|
+
// Clone as inactive
|
|
148
|
+
fields: (form.fields || []).map(({ id, ...field2 }) => field2),
|
|
149
|
+
// Remove IDs
|
|
150
|
+
steps: (form.steps || []).map(({ id, ...step }) => step)
|
|
151
|
+
// Remove IDs
|
|
152
|
+
});
|
|
153
|
+
},
|
|
154
|
+
/**
|
|
155
|
+
* Activate or deactivate a form
|
|
156
|
+
*/
|
|
157
|
+
async setActive(formId, isActive) {
|
|
158
|
+
return formsApi.update(formId, { isActive });
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
var field = {
|
|
162
|
+
text: (slug, label, options) => ({
|
|
163
|
+
slug,
|
|
164
|
+
label,
|
|
165
|
+
fieldType: "text",
|
|
166
|
+
...options
|
|
167
|
+
}),
|
|
168
|
+
email: (slug, label, options) => ({
|
|
169
|
+
slug,
|
|
170
|
+
label,
|
|
171
|
+
fieldType: "email",
|
|
172
|
+
isRequired: true,
|
|
173
|
+
...options
|
|
174
|
+
}),
|
|
175
|
+
phone: (slug, label, options) => ({
|
|
176
|
+
slug,
|
|
177
|
+
label,
|
|
178
|
+
fieldType: "phone",
|
|
179
|
+
...options
|
|
180
|
+
}),
|
|
181
|
+
textarea: (slug, label, options) => ({
|
|
182
|
+
slug,
|
|
183
|
+
label,
|
|
184
|
+
fieldType: "textarea",
|
|
185
|
+
...options
|
|
186
|
+
}),
|
|
187
|
+
select: (slug, label, choices, options) => ({
|
|
188
|
+
slug,
|
|
189
|
+
label,
|
|
190
|
+
fieldType: "select",
|
|
191
|
+
options: choices,
|
|
192
|
+
...options
|
|
193
|
+
}),
|
|
194
|
+
radio: (slug, label, choices, options) => ({
|
|
195
|
+
slug,
|
|
196
|
+
label,
|
|
197
|
+
fieldType: "radio",
|
|
198
|
+
options: choices,
|
|
199
|
+
...options
|
|
200
|
+
}),
|
|
201
|
+
checkbox: (slug, label, options) => ({
|
|
202
|
+
slug,
|
|
203
|
+
label,
|
|
204
|
+
fieldType: "checkbox",
|
|
205
|
+
...options
|
|
206
|
+
}),
|
|
207
|
+
date: (slug, label, options) => ({
|
|
208
|
+
slug,
|
|
209
|
+
label,
|
|
210
|
+
fieldType: "date",
|
|
211
|
+
...options
|
|
212
|
+
}),
|
|
213
|
+
number: (slug, label, options) => ({
|
|
214
|
+
slug,
|
|
215
|
+
label,
|
|
216
|
+
fieldType: "number",
|
|
217
|
+
...options
|
|
218
|
+
}),
|
|
219
|
+
rating: (slug, label, options) => ({
|
|
220
|
+
slug,
|
|
221
|
+
label,
|
|
222
|
+
fieldType: "rating",
|
|
223
|
+
...options
|
|
224
|
+
}),
|
|
225
|
+
file: (slug, label, options) => ({
|
|
226
|
+
slug,
|
|
227
|
+
label,
|
|
228
|
+
fieldType: "file",
|
|
229
|
+
...options
|
|
230
|
+
}),
|
|
231
|
+
hidden: (slug, defaultValue) => ({
|
|
232
|
+
slug,
|
|
233
|
+
label: "",
|
|
234
|
+
fieldType: "hidden",
|
|
235
|
+
defaultValue
|
|
236
|
+
}),
|
|
237
|
+
heading: (slug, label) => ({
|
|
238
|
+
slug,
|
|
239
|
+
label,
|
|
240
|
+
fieldType: "heading"
|
|
241
|
+
}),
|
|
242
|
+
paragraph: (slug, label) => ({
|
|
243
|
+
slug,
|
|
244
|
+
label,
|
|
245
|
+
fieldType: "paragraph"
|
|
246
|
+
})
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
export { configureFormsApi, field, formsApi };
|
|
250
|
+
//# sourceMappingURL=chunk-FEBYQGY4.mjs.map
|
|
251
|
+
//# sourceMappingURL=chunk-FEBYQGY4.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/forms/formsApi.ts"],"names":["field"],"mappings":"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","file":"chunk-FEBYQGY4.mjs","sourcesContent":["/**\n * @uptrade/site-kit/forms - Forms API Client\n * \n * Full API client for form management. Allows developers to create, update,\n * and delete forms programmatically. Changes sync to Portal automatically.\n * \n * @example\n * ```tsx\n * import { formsApi } from '@uptrade/site-kit/forms'\n * \n * // Create a new form\n * const form = await formsApi.create({\n * projectId: 'xxx',\n * slug: 'contact-us',\n * name: 'Contact Form',\n * formType: 'prospect',\n * fields: [\n * { slug: 'name', label: 'Name', fieldType: 'text', isRequired: true },\n * { slug: 'email', label: 'Email', fieldType: 'email', isRequired: true },\n * { slug: 'message', label: 'Message', fieldType: 'textarea' },\n * ]\n * })\n * \n * // Update fields\n * await formsApi.update(form.id, {\n * fields: [...form.fields, { slug: 'phone', label: 'Phone', fieldType: 'phone' }]\n * })\n * ```\n */\n\n// ============================================\n// Types\n// ============================================\n\nexport type FormType = \n | 'prospect' // → CRM leads\n | 'contact' // → Contact form\n | 'support' // → Support tickets\n | 'feedback' // → Feedback entries\n | 'newsletter' // → Email subscribers\n | 'custom' // → Custom webhook\n\nexport type FieldType =\n | 'text'\n | 'email'\n | 'phone'\n | 'number'\n | 'textarea'\n | 'select'\n | 'multi_select'\n | 'radio'\n | 'checkbox'\n | 'date'\n | 'time'\n | 'datetime'\n | 'url'\n | 'file'\n | 'rating'\n | 'slider'\n | 'hidden'\n | 'heading'\n | 'paragraph'\n\nexport type FieldWidth = 'full' | 'half' | 'third' | 'quarter'\n\nexport interface FieldOption {\n value: string\n label: string\n disabled?: boolean\n}\n\nexport interface FieldValidation {\n min?: number\n max?: number\n minLength?: number\n maxLength?: number\n pattern?: string\n patternMessage?: string\n}\n\nexport interface FieldConditional {\n field: string\n operator: 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'is_empty' | 'not_empty' | 'greater_than' | 'less_than'\n value?: string | number | boolean\n}\n\nexport interface FormField {\n id?: string\n slug: string\n label: string\n fieldType: FieldType\n placeholder?: string\n helpText?: string\n defaultValue?: string\n isRequired?: boolean\n validation?: FieldValidation\n options?: FieldOption[]\n conditional?: FieldConditional\n width?: FieldWidth\n sortOrder?: number\n destinationField?: string\n stepId?: string\n}\n\nexport interface FormStep {\n id?: string\n stepNumber: number\n title?: string\n description?: string\n condition?: FieldConditional\n}\n\nexport interface Form {\n id: string\n projectId: string\n slug: string\n name: string\n description?: string\n formType: FormType\n successMessage: string\n redirectUrl?: string\n notificationEmails?: string[]\n submitButtonText: string\n layout: 'stacked' | 'inline' | 'grid'\n showProgress: boolean\n enableSaveDraft: boolean\n isActive: boolean\n createdAt: string\n updatedAt: string\n fields?: FormField[]\n steps?: FormStep[]\n}\n\nexport interface CreateFormInput {\n projectId: string\n slug: string\n name: string\n description?: string\n formType?: FormType\n successMessage?: string\n redirectUrl?: string\n notificationEmails?: string[]\n submitButtonText?: string\n layout?: 'stacked' | 'inline' | 'grid'\n showProgress?: boolean\n enableSaveDraft?: boolean\n isActive?: boolean\n fields?: FormField[]\n steps?: FormStep[]\n}\n\nexport interface UpdateFormInput {\n slug?: string\n name?: string\n description?: string\n formType?: FormType\n successMessage?: string\n redirectUrl?: string\n notificationEmails?: string[]\n submitButtonText?: string\n layout?: 'stacked' | 'inline' | 'grid'\n showProgress?: boolean\n enableSaveDraft?: boolean\n isActive?: boolean\n fields?: FormField[]\n steps?: FormStep[]\n}\n\nexport interface FormsListOptions {\n projectId?: string\n formType?: FormType\n isActive?: boolean\n search?: string\n}\n\n// ============================================\n// API Client Configuration\n// ============================================\n\ninterface FormsApiConfig {\n baseUrl: string\n apiKey?: string\n getAuthToken?: () => Promise<string> | string\n}\n\nlet config: FormsApiConfig | null = null\n\n/**\n * Configure the forms API client\n */\nexport function configureFormsApi(options: FormsApiConfig) {\n config = options\n}\n\n/**\n * Get API config, falling back to SiteKitProvider globals\n */\nfunction getConfig(): FormsApiConfig {\n if (config) return config\n \n // Try to get from window globals (set by SiteKitProvider)\n if (typeof window !== 'undefined') {\n const apiUrl = (window as any).__SITE_KIT_API_URL__\n const apiKey = (window as any).__SITE_KIT_API_KEY__\n \n if (apiUrl && apiKey) {\n return { baseUrl: apiUrl, apiKey }\n }\n }\n \n throw new Error(\n 'Forms API not configured. Either wrap your app in SiteKitProvider or call configureFormsApi() first.'\n )\n}\n\n// ============================================\n// HTTP Helpers\n// ============================================\n\nasync function apiRequest<T>(\n method: 'GET' | 'POST' | 'PUT' | 'DELETE',\n path: string,\n body?: any\n): Promise<T> {\n const { baseUrl, apiKey, getAuthToken } = getConfig()\n \n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n \n // Use API key for public endpoints, auth token for admin endpoints\n if (apiKey) {\n headers['x-api-key'] = apiKey\n } else if (getAuthToken) {\n const token = await getAuthToken()\n headers['Authorization'] = `Bearer ${token}`\n }\n \n const response = await fetch(`${baseUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n })\n \n if (!response.ok) {\n const error = await response.json().catch(() => ({ message: response.statusText }))\n throw new Error(error.message || `API error: ${response.status}`)\n }\n \n if (response.status === 204) {\n return undefined as T\n }\n \n return response.json()\n}\n\n// ============================================\n// Forms API\n// ============================================\n\nexport const formsApi = {\n /**\n * List all forms for a project\n */\n async list(options: FormsListOptions = {}): Promise<Form[]> {\n const params = new URLSearchParams()\n if (options.projectId) params.set('projectId', options.projectId)\n if (options.formType) params.set('formType', options.formType)\n if (options.isActive !== undefined) params.set('isActive', String(options.isActive))\n if (options.search) params.set('search', options.search)\n \n const query = params.toString()\n const result = await apiRequest<{ data: Form[] }>('GET', `/forms${query ? `?${query}` : ''}`)\n return result.data\n },\n \n /**\n * Get a single form by ID or slug\n */\n async get(idOrSlug: string): Promise<Form> {\n return apiRequest<Form>('GET', `/forms/${idOrSlug}`)\n },\n \n /**\n * Create a new form\n */\n async create(input: CreateFormInput): Promise<Form> {\n return apiRequest<Form>('POST', '/forms', input)\n },\n \n /**\n * Update an existing form\n */\n async update(id: string, input: UpdateFormInput): Promise<Form> {\n return apiRequest<Form>('PUT', `/forms/${id}`, input)\n },\n \n /**\n * Delete a form\n */\n async delete(id: string): Promise<void> {\n return apiRequest<void>('DELETE', `/forms/${id}`)\n },\n \n /**\n * Add a field to an existing form\n */\n async addField(formId: string, field: FormField): Promise<Form> {\n const form = await formsApi.get(formId)\n const maxSortOrder = Math.max(0, ...(form.fields || []).map(f => f.sortOrder || 0))\n \n return formsApi.update(formId, {\n fields: [\n ...(form.fields || []),\n { ...field, sortOrder: field.sortOrder ?? maxSortOrder + 1 }\n ]\n })\n },\n \n /**\n * Update a field in an existing form\n */\n async updateField(formId: string, fieldSlug: string, updates: Partial<FormField>): Promise<Form> {\n const form = await formsApi.get(formId)\n \n return formsApi.update(formId, {\n fields: (form.fields || []).map(f => \n f.slug === fieldSlug ? { ...f, ...updates } : f\n )\n })\n },\n \n /**\n * Remove a field from a form\n */\n async removeField(formId: string, fieldSlug: string): Promise<Form> {\n const form = await formsApi.get(formId)\n \n return formsApi.update(formId, {\n fields: (form.fields || []).filter(f => f.slug !== fieldSlug)\n })\n },\n \n /**\n * Reorder fields in a form\n */\n async reorderFields(formId: string, fieldSlugs: string[]): Promise<Form> {\n const form = await formsApi.get(formId)\n const fieldsMap = new Map((form.fields || []).map(f => [f.slug, f]))\n \n const orderedFields = fieldSlugs.map((slug, index) => {\n const field = fieldsMap.get(slug)\n if (!field) throw new Error(`Field not found: ${slug}`)\n return { ...field, sortOrder: index }\n })\n \n return formsApi.update(formId, { fields: orderedFields })\n },\n \n /**\n * Clone a form\n */\n async clone(formId: string, newSlug: string, newName?: string): Promise<Form> {\n const form = await formsApi.get(formId)\n \n return formsApi.create({\n projectId: form.projectId,\n slug: newSlug,\n name: newName || `${form.name} (Copy)`,\n description: form.description,\n formType: form.formType,\n successMessage: form.successMessage,\n redirectUrl: form.redirectUrl,\n notificationEmails: form.notificationEmails,\n submitButtonText: form.submitButtonText,\n layout: form.layout,\n showProgress: form.showProgress,\n enableSaveDraft: form.enableSaveDraft,\n isActive: false, // Clone as inactive\n fields: (form.fields || []).map(({ id, ...field }) => field), // Remove IDs\n steps: (form.steps || []).map(({ id, ...step }) => step), // Remove IDs\n })\n },\n \n /**\n * Activate or deactivate a form\n */\n async setActive(formId: string, isActive: boolean): Promise<Form> {\n return formsApi.update(formId, { isActive })\n },\n}\n\n// ============================================\n// Field Builder Helpers\n// ============================================\n\n/**\n * Helper functions to build field definitions\n */\nexport const field = {\n text: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'text',\n ...options,\n }),\n \n email: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'email',\n isRequired: true,\n ...options,\n }),\n \n phone: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'phone',\n ...options,\n }),\n \n textarea: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'textarea',\n ...options,\n }),\n \n select: (slug: string, label: string, choices: Array<{ value: string; label: string }>, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'select',\n options: choices,\n ...options,\n }),\n \n radio: (slug: string, label: string, choices: Array<{ value: string; label: string }>, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'radio',\n options: choices,\n ...options,\n }),\n \n checkbox: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'checkbox',\n ...options,\n }),\n \n date: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'date',\n ...options,\n }),\n \n number: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'number',\n ...options,\n }),\n \n rating: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'rating',\n ...options,\n }),\n \n file: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'file',\n ...options,\n }),\n \n hidden: (slug: string, defaultValue: string): FormField => ({\n slug,\n label: '',\n fieldType: 'hidden',\n defaultValue,\n }),\n \n heading: (slug: string, label: string): FormField => ({\n slug,\n label,\n fieldType: 'heading',\n }),\n \n paragraph: (slug: string, label: string): FormField => ({\n slug,\n label,\n fieldType: 'paragraph',\n }),\n}\n"]}
|