@aifeatures/admin-react 0.1.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/dist/index.cjs ADDED
@@ -0,0 +1,1345 @@
1
+ "use client";
2
+ "use strict";
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 __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/index.ts
32
+ var index_exports = {};
33
+ __export(index_exports, {
34
+ AifeaturesApiError: () => AifeaturesApiError,
35
+ AifeaturesProvider: () => AifeaturesProvider,
36
+ FormSettings: () => FormSettings,
37
+ FormSubmissions: () => FormSubmissions,
38
+ FormsDashboard: () => FormsDashboard,
39
+ FormsList: () => FormsList,
40
+ SubmissionDetail: () => SubmissionDetail,
41
+ createApiClient: () => createApiClient,
42
+ useAifeatures: () => useAifeaturesContext,
43
+ useAifeaturesContext: () => useAifeaturesContext,
44
+ useForms: () => useForms,
45
+ useSubmissions: () => useSubmissions
46
+ });
47
+ module.exports = __toCommonJS(index_exports);
48
+
49
+ // src/provider/AifeaturesProvider.tsx
50
+ var React = __toESM(require("react"), 1);
51
+
52
+ // src/lib/api.ts
53
+ var AifeaturesApiError = class extends Error {
54
+ constructor(message, status, details) {
55
+ super(message);
56
+ this.status = status;
57
+ this.details = details;
58
+ this.name = "AifeaturesApiError";
59
+ }
60
+ };
61
+ function createApiClient(siteToken, apiUrl = "https://aifeatures.dev") {
62
+ async function request(path, options = {}) {
63
+ const url = `${apiUrl}${path}`;
64
+ const response = await fetch(url, {
65
+ ...options,
66
+ headers: {
67
+ "Authorization": `Bearer ${siteToken}`,
68
+ "Content-Type": "application/json",
69
+ ...options.headers
70
+ }
71
+ });
72
+ if (!response.ok) {
73
+ let details;
74
+ try {
75
+ details = await response.json();
76
+ } catch {
77
+ }
78
+ throw new AifeaturesApiError(
79
+ details?.error || `Request failed with status ${response.status}`,
80
+ response.status,
81
+ details
82
+ );
83
+ }
84
+ if (response.status === 204) {
85
+ return void 0;
86
+ }
87
+ return response.json();
88
+ }
89
+ return {
90
+ // Forms
91
+ async getForms() {
92
+ const data = await request("/api/v1/forms");
93
+ return data.forms;
94
+ },
95
+ async getForm(formId) {
96
+ return request(`/api/v1/forms/${formId}`);
97
+ },
98
+ async createForm(input) {
99
+ return request("/api/v1/forms", {
100
+ method: "POST",
101
+ body: JSON.stringify(input)
102
+ });
103
+ },
104
+ async updateForm(formId, input) {
105
+ return request(`/api/v1/forms/${formId}`, {
106
+ method: "PATCH",
107
+ body: JSON.stringify(input)
108
+ });
109
+ },
110
+ async deleteForm(formId) {
111
+ await request(`/api/v1/forms/${formId}`, {
112
+ method: "DELETE"
113
+ });
114
+ },
115
+ // Submissions
116
+ async getSubmissions(formId, options = {}) {
117
+ const params = new URLSearchParams();
118
+ if (options.limit !== void 0) {
119
+ params.set("limit", String(options.limit));
120
+ }
121
+ if (options.offset !== void 0) {
122
+ params.set("offset", String(options.offset));
123
+ }
124
+ const query = params.toString();
125
+ const path = `/api/v1/forms/${formId}/submissions${query ? `?${query}` : ""}`;
126
+ return request(path);
127
+ },
128
+ async getSubmission(submissionId) {
129
+ return request(`/api/v1/submissions/${submissionId}`);
130
+ },
131
+ async deleteSubmission(submissionId) {
132
+ await request(`/api/v1/submissions/${submissionId}`, {
133
+ method: "DELETE"
134
+ });
135
+ },
136
+ // Attachments
137
+ async downloadAttachment(submissionId, filename) {
138
+ const url = `${apiUrl}/api/v1/submissions/${submissionId}/attachments/${encodeURIComponent(filename)}`;
139
+ const response = await fetch(url, {
140
+ headers: {
141
+ "Authorization": `Bearer ${siteToken}`
142
+ }
143
+ });
144
+ if (!response.ok) {
145
+ let details;
146
+ try {
147
+ details = await response.json();
148
+ } catch {
149
+ }
150
+ throw new AifeaturesApiError(
151
+ details?.error || `Download failed with status ${response.status}`,
152
+ response.status,
153
+ details
154
+ );
155
+ }
156
+ const blob = await response.blob();
157
+ const blobUrl = URL.createObjectURL(blob);
158
+ const link = document.createElement("a");
159
+ link.href = blobUrl;
160
+ link.download = filename;
161
+ document.body.appendChild(link);
162
+ link.click();
163
+ document.body.removeChild(link);
164
+ URL.revokeObjectURL(blobUrl);
165
+ }
166
+ };
167
+ }
168
+
169
+ // src/provider/AifeaturesProvider.tsx
170
+ var import_jsx_runtime = require("react/jsx-runtime");
171
+ var AifeaturesContext = React.createContext(
172
+ null
173
+ );
174
+ function validateToken(token) {
175
+ if (!token) {
176
+ return "No siteToken provided to AifeaturesProvider";
177
+ }
178
+ if (token.startsWith("sk_")) {
179
+ return "Invalid token type: You passed an organization API key (sk_xxx) but AifeaturesProvider requires a site token (st_xxx). Site tokens are returned when you create a site via the API.";
180
+ }
181
+ if (!token.startsWith("st_")) {
182
+ return `Invalid token format: Expected a site token starting with "st_" but got "${token.slice(0, 10)}...". Site tokens are returned when you create a site via the API.`;
183
+ }
184
+ return null;
185
+ }
186
+ function AifeaturesProvider({
187
+ siteToken,
188
+ apiUrl = "https://aifeatures.dev",
189
+ dark = false,
190
+ className,
191
+ children
192
+ }) {
193
+ const tokenError = React.useMemo(() => validateToken(siteToken), [siteToken]);
194
+ const api = React.useMemo(
195
+ () => createApiClient(siteToken, apiUrl),
196
+ [siteToken, apiUrl]
197
+ );
198
+ const value = React.useMemo(
199
+ () => ({
200
+ siteToken,
201
+ apiUrl,
202
+ api
203
+ }),
204
+ [siteToken, apiUrl, api]
205
+ );
206
+ if (tokenError) {
207
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `aifeatures-admin ${dark ? "dark" : ""} ${className || ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "af-rounded-md af-border af-border-destructive af-bg-destructive/10 af-p-4", children: [
208
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "af-text-sm af-font-semibold af-text-destructive af-mb-2", children: "AifeaturesProvider Configuration Error" }),
209
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "af-text-sm af-text-destructive", children: tokenError })
210
+ ] }) });
211
+ }
212
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AifeaturesContext.Provider, { value, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `aifeatures-admin ${dark ? "dark" : ""} ${className || ""}`, children }) });
213
+ }
214
+ function useAifeaturesContext() {
215
+ const context = React.useContext(AifeaturesContext);
216
+ if (!context) {
217
+ throw new Error(
218
+ "useAifeaturesContext must be used within an AifeaturesProvider"
219
+ );
220
+ }
221
+ return context;
222
+ }
223
+
224
+ // src/components/FormsDashboard.tsx
225
+ var React13 = __toESM(require("react"), 1);
226
+ var import_lucide_react6 = require("lucide-react");
227
+
228
+ // src/ui/tabs.tsx
229
+ var React2 = __toESM(require("react"), 1);
230
+ var TabsPrimitive = __toESM(require("@radix-ui/react-tabs"), 1);
231
+
232
+ // src/lib/cn.ts
233
+ var import_clsx = require("clsx");
234
+ var import_tailwind_merge = require("tailwind-merge");
235
+ function cn(...inputs) {
236
+ return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
237
+ }
238
+
239
+ // src/ui/tabs.tsx
240
+ var import_jsx_runtime2 = require("react/jsx-runtime");
241
+ var Tabs = TabsPrimitive.Root;
242
+ var TabsList = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
243
+ TabsPrimitive.List,
244
+ {
245
+ ref,
246
+ className: cn(
247
+ "af-inline-flex af-h-9 af-items-center af-justify-center af-rounded-lg af-bg-muted af-p-1 af-text-muted-foreground",
248
+ className
249
+ ),
250
+ ...props
251
+ }
252
+ ));
253
+ TabsList.displayName = TabsPrimitive.List.displayName;
254
+ var TabsTrigger = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
255
+ TabsPrimitive.Trigger,
256
+ {
257
+ ref,
258
+ className: cn(
259
+ "af-inline-flex af-items-center af-justify-center af-whitespace-nowrap af-rounded-md af-px-3 af-py-1 af-text-sm af-font-medium af-ring-offset-background af-transition-all focus-visible:af-outline-none focus-visible:af-ring-2 focus-visible:af-ring-ring focus-visible:af-ring-offset-2 disabled:af-pointer-events-none disabled:af-opacity-50 data-[state=active]:af-bg-background data-[state=active]:af-text-foreground data-[state=active]:af-shadow",
260
+ className
261
+ ),
262
+ ...props
263
+ }
264
+ ));
265
+ TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
266
+ var TabsContent = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
267
+ TabsPrimitive.Content,
268
+ {
269
+ ref,
270
+ className: cn(
271
+ "af-mt-2 af-ring-offset-background focus-visible:af-outline-none focus-visible:af-ring-2 focus-visible:af-ring-ring focus-visible:af-ring-offset-2",
272
+ className
273
+ ),
274
+ ...props
275
+ }
276
+ ));
277
+ TabsContent.displayName = TabsPrimitive.Content.displayName;
278
+
279
+ // src/ui/button.tsx
280
+ var React3 = __toESM(require("react"), 1);
281
+ var import_react_slot = require("@radix-ui/react-slot");
282
+ var import_class_variance_authority = require("class-variance-authority");
283
+ var import_jsx_runtime3 = require("react/jsx-runtime");
284
+ var buttonVariants = (0, import_class_variance_authority.cva)(
285
+ "af-inline-flex af-items-center af-justify-center af-gap-2 af-whitespace-nowrap af-rounded-md af-text-sm af-font-medium af-transition-colors focus-visible:af-outline-none focus-visible:af-ring-1 focus-visible:af-ring-ring disabled:af-pointer-events-none disabled:af-opacity-50 [&_svg]:af-pointer-events-none [&_svg]:af-size-4 [&_svg]:af-shrink-0",
286
+ {
287
+ variants: {
288
+ variant: {
289
+ default: "af-bg-primary af-text-primary-foreground af-shadow hover:af-bg-primary/90",
290
+ destructive: "af-bg-destructive af-text-destructive-foreground af-shadow-sm hover:af-bg-destructive/90",
291
+ outline: "af-border af-border-input af-bg-background af-shadow-sm hover:af-bg-accent hover:af-text-accent-foreground",
292
+ secondary: "af-bg-secondary af-text-secondary-foreground af-shadow-sm hover:af-bg-secondary/80",
293
+ ghost: "hover:af-bg-accent hover:af-text-accent-foreground",
294
+ link: "af-text-primary af-underline-offset-4 hover:af-underline"
295
+ },
296
+ size: {
297
+ default: "af-h-9 af-px-4 af-py-2",
298
+ sm: "af-h-8 af-rounded-md af-px-3 af-text-xs",
299
+ lg: "af-h-10 af-rounded-md af-px-8",
300
+ icon: "af-h-9 af-w-9"
301
+ }
302
+ },
303
+ defaultVariants: {
304
+ variant: "default",
305
+ size: "default"
306
+ }
307
+ }
308
+ );
309
+ var Button = React3.forwardRef(
310
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
311
+ const Comp = asChild ? import_react_slot.Slot : "button";
312
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
313
+ Comp,
314
+ {
315
+ className: cn(buttonVariants({ variant, size, className })),
316
+ ref,
317
+ ...props
318
+ }
319
+ );
320
+ }
321
+ );
322
+ Button.displayName = "Button";
323
+
324
+ // src/components/FormsList.tsx
325
+ var import_lucide_react = require("lucide-react");
326
+
327
+ // src/ui/table.tsx
328
+ var React4 = __toESM(require("react"), 1);
329
+ var import_jsx_runtime4 = require("react/jsx-runtime");
330
+ var Table = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "af-relative af-w-full af-overflow-auto", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
331
+ "table",
332
+ {
333
+ ref,
334
+ className: cn("af-w-full af-caption-bottom af-text-sm", className),
335
+ ...props
336
+ }
337
+ ) }));
338
+ Table.displayName = "Table";
339
+ var TableHeader = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("thead", { ref, className: cn("[&_tr]:af-border-b", className), ...props }));
340
+ TableHeader.displayName = "TableHeader";
341
+ var TableBody = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
342
+ "tbody",
343
+ {
344
+ ref,
345
+ className: cn("[&_tr:last-child]:af-border-0", className),
346
+ ...props
347
+ }
348
+ ));
349
+ TableBody.displayName = "TableBody";
350
+ var TableFooter = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
351
+ "tfoot",
352
+ {
353
+ ref,
354
+ className: cn(
355
+ "af-border-t af-bg-muted/50 af-font-medium [&>tr]:last:af-border-b-0",
356
+ className
357
+ ),
358
+ ...props
359
+ }
360
+ ));
361
+ TableFooter.displayName = "TableFooter";
362
+ var TableRow = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
363
+ "tr",
364
+ {
365
+ ref,
366
+ className: cn(
367
+ "af-border-b af-transition-colors hover:af-bg-muted/50 data-[state=selected]:af-bg-muted",
368
+ className
369
+ ),
370
+ ...props
371
+ }
372
+ ));
373
+ TableRow.displayName = "TableRow";
374
+ var TableHead = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
375
+ "th",
376
+ {
377
+ ref,
378
+ className: cn(
379
+ "af-h-10 af-px-2 af-text-left af-align-middle af-font-medium af-text-muted-foreground [&:has([role=checkbox])]:af-pr-0 [&>[role=checkbox]]:af-translate-y-[2px]",
380
+ className
381
+ ),
382
+ ...props
383
+ }
384
+ ));
385
+ TableHead.displayName = "TableHead";
386
+ var TableCell = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
387
+ "td",
388
+ {
389
+ ref,
390
+ className: cn(
391
+ "af-p-2 af-align-middle [&:has([role=checkbox])]:af-pr-0 [&>[role=checkbox]]:af-translate-y-[2px]",
392
+ className
393
+ ),
394
+ ...props
395
+ }
396
+ ));
397
+ TableCell.displayName = "TableCell";
398
+ var TableCaption = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
399
+ "caption",
400
+ {
401
+ ref,
402
+ className: cn("af-mt-4 af-text-sm af-text-muted-foreground", className),
403
+ ...props
404
+ }
405
+ ));
406
+ TableCaption.displayName = "TableCaption";
407
+
408
+ // src/hooks/useForms.ts
409
+ var React5 = __toESM(require("react"), 1);
410
+ function useForms() {
411
+ const { api } = useAifeaturesContext();
412
+ const [forms, setForms] = React5.useState([]);
413
+ const [isLoading, setIsLoading] = React5.useState(true);
414
+ const [error, setError] = React5.useState(null);
415
+ const fetchForms = React5.useCallback(async () => {
416
+ try {
417
+ setIsLoading(true);
418
+ setError(null);
419
+ const data = await api.getForms();
420
+ setForms(data);
421
+ } catch (err) {
422
+ setError(err instanceof Error ? err : new Error("Failed to fetch forms"));
423
+ } finally {
424
+ setIsLoading(false);
425
+ }
426
+ }, [api]);
427
+ React5.useEffect(() => {
428
+ fetchForms();
429
+ }, [fetchForms]);
430
+ const createForm = React5.useCallback(
431
+ async (input) => {
432
+ const form = await api.createForm(input);
433
+ setForms((prev) => [...prev, form]);
434
+ return form;
435
+ },
436
+ [api]
437
+ );
438
+ const updateForm = React5.useCallback(
439
+ async (formId, input) => {
440
+ const form = await api.updateForm(formId, input);
441
+ setForms((prev) => prev.map((f) => f.id === formId ? form : f));
442
+ return form;
443
+ },
444
+ [api]
445
+ );
446
+ const deleteForm = React5.useCallback(
447
+ async (formId) => {
448
+ await api.deleteForm(formId);
449
+ setForms((prev) => prev.filter((f) => f.id !== formId));
450
+ },
451
+ [api]
452
+ );
453
+ return {
454
+ forms,
455
+ isLoading,
456
+ error,
457
+ refetch: fetchForms,
458
+ createForm,
459
+ updateForm,
460
+ deleteForm
461
+ };
462
+ }
463
+
464
+ // src/components/FormsList.tsx
465
+ var import_jsx_runtime5 = require("react/jsx-runtime");
466
+ function FormsList({ onSelectForm, className }) {
467
+ const { forms, isLoading, error } = useForms();
468
+ if (isLoading) {
469
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: `af-flex af-items-center af-justify-center af-py-8 ${className || ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "af-text-muted-foreground", children: "Loading forms..." }) });
470
+ }
471
+ if (error) {
472
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: `af-flex af-items-center af-justify-center af-py-8 ${className || ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "af-text-destructive", children: [
473
+ "Error: ",
474
+ error.message
475
+ ] }) });
476
+ }
477
+ if (forms.length === 0) {
478
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `af-flex af-flex-col af-items-center af-justify-center af-py-12 ${className || ""}`, children: [
479
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.Inbox, { className: "af-h-12 af-w-12 af-text-muted-foreground af-mb-4" }),
480
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "af-text-muted-foreground af-text-center", children: [
481
+ "No forms yet.",
482
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("br", {}),
483
+ "Forms will appear here when the AI creates contact forms on your website."
484
+ ] })
485
+ ] });
486
+ }
487
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Table, { children: [
488
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TableHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(TableRow, { children: [
489
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TableHead, { children: "Name" }),
490
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TableHead, { children: "Endpoint" }),
491
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TableHead, { className: "af-text-right", children: "Actions" })
492
+ ] }) }),
493
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TableBody, { children: forms.map((form) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(TableRow, { children: [
494
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TableCell, { className: "af-font-medium", children: form.name }),
495
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { className: "af-text-xs af-bg-muted af-px-1.5 af-py-0.5 af-rounded", children: form.endpoint_url.replace("https://aifeatures.dev", "") }) }),
496
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TableCell, { className: "af-text-right", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "af-flex af-items-center af-justify-end af-gap-2", children: [
497
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
498
+ Button,
499
+ {
500
+ variant: "ghost",
501
+ size: "sm",
502
+ onClick: () => onSelectForm?.(form, "submissions"),
503
+ children: [
504
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.Inbox, { className: "af-h-4 af-w-4 af-mr-1" }),
505
+ "Submissions"
506
+ ]
507
+ }
508
+ ),
509
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
510
+ Button,
511
+ {
512
+ variant: "ghost",
513
+ size: "sm",
514
+ onClick: () => onSelectForm?.(form, "settings"),
515
+ children: [
516
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.Settings, { className: "af-h-4 af-w-4 af-mr-1" }),
517
+ "Settings"
518
+ ]
519
+ }
520
+ )
521
+ ] }) })
522
+ ] }, form.id)) })
523
+ ] }) });
524
+ }
525
+
526
+ // src/components/FormSubmissions.tsx
527
+ var React9 = __toESM(require("react"), 1);
528
+ var import_lucide_react4 = require("lucide-react");
529
+
530
+ // src/ui/select.tsx
531
+ var React6 = __toESM(require("react"), 1);
532
+ var SelectPrimitive = __toESM(require("@radix-ui/react-select"), 1);
533
+ var import_lucide_react2 = require("lucide-react");
534
+ var import_jsx_runtime6 = require("react/jsx-runtime");
535
+ var Select = SelectPrimitive.Root;
536
+ var SelectValue = SelectPrimitive.Value;
537
+ var SelectTrigger = React6.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
538
+ SelectPrimitive.Trigger,
539
+ {
540
+ ref,
541
+ className: cn(
542
+ "af-flex af-h-9 af-w-full af-items-center af-justify-between af-whitespace-nowrap af-rounded-md af-border af-border-input af-bg-transparent af-px-3 af-py-2 af-text-sm af-shadow-sm af-ring-offset-background placeholder:af-text-muted-foreground focus:af-outline-none focus:af-ring-1 focus:af-ring-ring disabled:af-cursor-not-allowed disabled:af-opacity-50 [&>span]:af-line-clamp-1",
543
+ className
544
+ ),
545
+ ...props,
546
+ children: [
547
+ children,
548
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.ChevronDown, { className: "af-h-4 af-w-4 af-opacity-50" }) })
549
+ ]
550
+ }
551
+ ));
552
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
553
+ var SelectScrollUpButton = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
554
+ SelectPrimitive.ScrollUpButton,
555
+ {
556
+ ref,
557
+ className: cn(
558
+ "af-flex af-cursor-default af-items-center af-justify-center af-py-1",
559
+ className
560
+ ),
561
+ ...props,
562
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.ChevronUp, { className: "af-h-4 af-w-4" })
563
+ }
564
+ ));
565
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
566
+ var SelectScrollDownButton = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
567
+ SelectPrimitive.ScrollDownButton,
568
+ {
569
+ ref,
570
+ className: cn(
571
+ "af-flex af-cursor-default af-items-center af-justify-center af-py-1",
572
+ className
573
+ ),
574
+ ...props,
575
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.ChevronDown, { className: "af-h-4 af-w-4" })
576
+ }
577
+ ));
578
+ SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
579
+ var SelectContent = React6.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectPrimitive.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
580
+ SelectPrimitive.Content,
581
+ {
582
+ ref,
583
+ className: cn(
584
+ "af-relative af-z-50 af-max-h-96 af-min-w-[8rem] af-overflow-hidden af-rounded-md af-border af-bg-popover af-text-popover-foreground af-shadow-md data-[state=open]:af-animate-in data-[state=closed]:af-animate-out data-[state=closed]:af-fade-out-0 data-[state=open]:af-fade-in-0 data-[state=closed]:af-zoom-out-95 data-[state=open]:af-zoom-in-95 data-[side=bottom]:af-slide-in-from-top-2 data-[side=left]:af-slide-in-from-right-2 data-[side=right]:af-slide-in-from-left-2 data-[side=top]:af-slide-in-from-bottom-2",
585
+ position === "popper" && "data-[side=bottom]:af-translate-y-1 data-[side=left]:af--translate-x-1 data-[side=right]:af-translate-x-1 data-[side=top]:af--translate-y-1",
586
+ className
587
+ ),
588
+ position,
589
+ ...props,
590
+ children: [
591
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectScrollUpButton, {}),
592
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
593
+ SelectPrimitive.Viewport,
594
+ {
595
+ className: cn(
596
+ "af-p-1",
597
+ position === "popper" && "af-h-[var(--radix-select-trigger-height)] af-w-full af-min-w-[var(--radix-select-trigger-width)]"
598
+ ),
599
+ children
600
+ }
601
+ ),
602
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectScrollDownButton, {})
603
+ ]
604
+ }
605
+ ) }));
606
+ SelectContent.displayName = SelectPrimitive.Content.displayName;
607
+ var SelectLabel = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
608
+ SelectPrimitive.Label,
609
+ {
610
+ ref,
611
+ className: cn("af-px-2 af-py-1.5 af-text-sm af-font-semibold", className),
612
+ ...props
613
+ }
614
+ ));
615
+ SelectLabel.displayName = SelectPrimitive.Label.displayName;
616
+ var SelectItem = React6.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
617
+ SelectPrimitive.Item,
618
+ {
619
+ ref,
620
+ className: cn(
621
+ "af-relative af-flex af-w-full af-cursor-default af-select-none af-items-center af-rounded-sm af-py-1.5 af-pl-2 af-pr-8 af-text-sm af-outline-none focus:af-bg-accent focus:af-text-accent-foreground data-[disabled]:af-pointer-events-none data-[disabled]:af-opacity-50",
622
+ className
623
+ ),
624
+ ...props,
625
+ children: [
626
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "af-absolute af-right-2 af-flex af-h-3.5 af-w-3.5 af-items-center af-justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.Check, { className: "af-h-4 af-w-4" }) }) }),
627
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectPrimitive.ItemText, { children })
628
+ ]
629
+ }
630
+ ));
631
+ SelectItem.displayName = SelectPrimitive.Item.displayName;
632
+ var SelectSeparator = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
633
+ SelectPrimitive.Separator,
634
+ {
635
+ ref,
636
+ className: cn("af--mx-1 af-my-1 af-h-px af-bg-muted", className),
637
+ ...props
638
+ }
639
+ ));
640
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
641
+
642
+ // src/hooks/useSubmissions.ts
643
+ var React7 = __toESM(require("react"), 1);
644
+ function useSubmissions({
645
+ formId,
646
+ initialPageSize = 25
647
+ }) {
648
+ const { api } = useAifeaturesContext();
649
+ const [submissions, setSubmissions] = React7.useState([]);
650
+ const [total, setTotal] = React7.useState(0);
651
+ const [isLoading, setIsLoading] = React7.useState(true);
652
+ const [error, setError] = React7.useState(null);
653
+ const [page, setPage] = React7.useState(0);
654
+ const [pageSize, setPageSize] = React7.useState(initialPageSize);
655
+ const fetchSubmissions = React7.useCallback(async () => {
656
+ if (!formId) return;
657
+ try {
658
+ setIsLoading(true);
659
+ setError(null);
660
+ const options = {
661
+ limit: pageSize,
662
+ offset: page * pageSize
663
+ };
664
+ const data = await api.getSubmissions(
665
+ formId,
666
+ options
667
+ );
668
+ setSubmissions(data.submissions);
669
+ setTotal(data.total);
670
+ } catch (err) {
671
+ setError(
672
+ err instanceof Error ? err : new Error("Failed to fetch submissions")
673
+ );
674
+ } finally {
675
+ setIsLoading(false);
676
+ }
677
+ }, [api, formId, page, pageSize]);
678
+ React7.useEffect(() => {
679
+ fetchSubmissions();
680
+ }, [fetchSubmissions]);
681
+ const deleteSubmission = React7.useCallback(
682
+ async (submissionId) => {
683
+ await api.deleteSubmission(submissionId);
684
+ setSubmissions((prev) => prev.filter((s) => s.id !== submissionId));
685
+ setTotal((prev) => prev - 1);
686
+ },
687
+ [api]
688
+ );
689
+ const totalPages = Math.ceil(total / pageSize);
690
+ return {
691
+ submissions,
692
+ total,
693
+ isLoading,
694
+ error,
695
+ page,
696
+ pageSize,
697
+ hasNextPage: page < totalPages - 1,
698
+ hasPreviousPage: page > 0,
699
+ setPage,
700
+ setPageSize: (size) => {
701
+ setPageSize(size);
702
+ setPage(0);
703
+ },
704
+ refetch: fetchSubmissions,
705
+ deleteSubmission
706
+ };
707
+ }
708
+
709
+ // src/components/SubmissionDetail.tsx
710
+ var React8 = __toESM(require("react"), 1);
711
+ var import_lucide_react3 = require("lucide-react");
712
+ var import_jsx_runtime7 = require("react/jsx-runtime");
713
+ function formatDate(dateString) {
714
+ return new Date(dateString).toLocaleString(void 0, {
715
+ year: "numeric",
716
+ month: "short",
717
+ day: "numeric",
718
+ hour: "2-digit",
719
+ minute: "2-digit"
720
+ });
721
+ }
722
+ function formatBytes(bytes) {
723
+ if (bytes === 0) return "0 B";
724
+ const k = 1024;
725
+ const sizes = ["B", "KB", "MB", "GB"];
726
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
727
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
728
+ }
729
+ function SubmissionDetail({
730
+ submission,
731
+ onBack
732
+ }) {
733
+ const { api } = useAifeaturesContext();
734
+ const [downloadingFile, setDownloadingFile] = React8.useState(null);
735
+ const handleDownload = async (filename) => {
736
+ setDownloadingFile(filename);
737
+ try {
738
+ await api.downloadAttachment(submission.id, filename);
739
+ } catch (error) {
740
+ console.error("Download failed:", error);
741
+ } finally {
742
+ setDownloadingFile(null);
743
+ }
744
+ };
745
+ const dataEntries = Object.entries(submission.data).filter(
746
+ ([key]) => !key.startsWith("_")
747
+ );
748
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
749
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "af-mb-6", children: [
750
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
751
+ Button,
752
+ {
753
+ variant: "ghost",
754
+ size: "sm",
755
+ onClick: onBack,
756
+ className: "af-mb-2 af--ml-2",
757
+ children: [
758
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react3.ArrowLeft, { className: "af-h-4 af-w-4 af-mr-1" }),
759
+ "Back to Submissions"
760
+ ]
761
+ }
762
+ ),
763
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { className: "af-text-lg af-font-semibold", children: "Submission Details" }),
764
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "af-text-sm af-text-muted-foreground", children: [
765
+ "Submitted ",
766
+ formatDate(submission.metadata.submitted_at)
767
+ ] })
768
+ ] }),
769
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "af-space-y-6", children: [
770
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
771
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h4", { className: "af-text-sm af-font-medium af-mb-3", children: "Form Data" }),
772
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "af-space-y-3", children: [
773
+ dataEntries.map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "af-grid af-grid-cols-3 af-gap-2", children: [
774
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "af-text-sm af-text-muted-foreground af-capitalize", children: key.replace(/_/g, " ") }),
775
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "af-col-span-2 af-text-sm af-break-words", children: typeof value === "string" && value.includes("\n") ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { className: "af-whitespace-pre-wrap af-font-sans af-bg-muted af-p-2 af-rounded af-text-xs", children: value }) : String(value) })
776
+ ] }, key)),
777
+ dataEntries.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "af-text-sm af-text-muted-foreground", children: "No data submitted" })
778
+ ] })
779
+ ] }),
780
+ submission.attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
781
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h4", { className: "af-text-sm af-font-medium af-mb-3", children: "Attachments" }),
782
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "af-space-y-2", children: submission.attachments.map((attachment, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
783
+ "div",
784
+ {
785
+ className: "af-flex af-items-center af-justify-between af-p-2 af-bg-muted af-rounded",
786
+ children: [
787
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "af-flex af-items-center af-gap-2", children: [
788
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react3.FileText, { className: "af-h-4 af-w-4 af-text-muted-foreground" }),
789
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "af-text-sm", children: attachment.name }),
790
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "af-text-xs af-text-muted-foreground", children: [
791
+ "(",
792
+ formatBytes(attachment.size),
793
+ ")"
794
+ ] })
795
+ ] }),
796
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
797
+ Button,
798
+ {
799
+ variant: "ghost",
800
+ size: "sm",
801
+ onClick: () => handleDownload(attachment.name),
802
+ disabled: downloadingFile === attachment.name,
803
+ children: [
804
+ downloadingFile === attachment.name ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react3.Loader2, { className: "af-h-4 af-w-4 af-mr-1 af-animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react3.Download, { className: "af-h-4 af-w-4 af-mr-1" }),
805
+ downloadingFile === attachment.name ? "Downloading..." : "Download"
806
+ ]
807
+ }
808
+ )
809
+ ]
810
+ },
811
+ index
812
+ )) })
813
+ ] }),
814
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
815
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h4", { className: "af-text-sm af-font-medium af-mb-3", children: "Metadata" }),
816
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "af-space-y-2 af-text-sm", children: [
817
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "af-flex af-items-center af-gap-2 af-text-muted-foreground", children: [
818
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react3.Clock, { className: "af-h-4 af-w-4" }),
819
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: formatDate(submission.metadata.submitted_at) })
820
+ ] }),
821
+ submission.metadata.ip_address && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "af-flex af-items-center af-gap-2 af-text-muted-foreground", children: [
822
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react3.Globe, { className: "af-h-4 af-w-4" }),
823
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
824
+ "IP: ",
825
+ submission.metadata.ip_address
826
+ ] })
827
+ ] }),
828
+ submission.metadata.user_agent && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "af-flex af-items-start af-gap-2 af-text-muted-foreground", children: [
829
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react3.Monitor, { className: "af-h-4 af-w-4 af-mt-0.5" }),
830
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "af-text-xs af-break-all", children: submission.metadata.user_agent })
831
+ ] }),
832
+ submission.resend_id && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "af-flex af-items-center af-gap-2 af-text-muted-foreground", children: [
833
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react3.Mail, { className: "af-h-4 af-w-4" }),
834
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
835
+ "Email ID: ",
836
+ submission.resend_id
837
+ ] })
838
+ ] })
839
+ ] })
840
+ ] })
841
+ ] })
842
+ ] });
843
+ }
844
+
845
+ // src/components/FormSubmissions.tsx
846
+ var import_jsx_runtime8 = require("react/jsx-runtime");
847
+ function formatDate2(dateString) {
848
+ return new Date(dateString).toLocaleString(void 0, {
849
+ month: "short",
850
+ day: "numeric",
851
+ hour: "2-digit",
852
+ minute: "2-digit"
853
+ });
854
+ }
855
+ function getEmailFromData(data) {
856
+ const emailFields = ["email", "Email", "EMAIL", "e-mail", "mail"];
857
+ for (const field of emailFields) {
858
+ if (typeof data[field] === "string") {
859
+ return data[field];
860
+ }
861
+ }
862
+ return null;
863
+ }
864
+ function getPreviewText(data) {
865
+ const entries = Object.entries(data).filter(
866
+ ([key]) => !key.startsWith("_") && !key.toLowerCase().includes("email")
867
+ );
868
+ if (entries.length === 0) return "";
869
+ const [, value] = entries[0];
870
+ const text = String(value);
871
+ return text.length > 50 ? text.slice(0, 50) + "..." : text;
872
+ }
873
+ function FormSubmissions({ formId, className }) {
874
+ const {
875
+ submissions,
876
+ total,
877
+ isLoading,
878
+ error,
879
+ page,
880
+ pageSize,
881
+ hasNextPage,
882
+ hasPreviousPage,
883
+ setPage,
884
+ setPageSize
885
+ } = useSubmissions({ formId });
886
+ const [view, setView] = React9.useState("list");
887
+ const [selectedSubmission, setSelectedSubmission] = React9.useState(null);
888
+ const handleViewSubmission = (submission) => {
889
+ setSelectedSubmission(submission);
890
+ setView("detail");
891
+ };
892
+ const handleBack = () => {
893
+ setView("list");
894
+ setSelectedSubmission(null);
895
+ };
896
+ if (view === "detail" && selectedSubmission) {
897
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
898
+ SubmissionDetail,
899
+ {
900
+ submission: selectedSubmission,
901
+ onBack: handleBack
902
+ }
903
+ ) });
904
+ }
905
+ if (isLoading) {
906
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: `af-flex af-items-center af-justify-center af-py-8 ${className || ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "af-text-muted-foreground", children: "Loading submissions..." }) });
907
+ }
908
+ if (error) {
909
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: `af-flex af-items-center af-justify-center af-py-8 ${className || ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "af-text-destructive", children: [
910
+ "Error: ",
911
+ error.message
912
+ ] }) });
913
+ }
914
+ if (submissions.length === 0 && page === 0) {
915
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: `af-flex af-flex-col af-items-center af-justify-center af-py-12 ${className || ""}`, children: [
916
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react4.Inbox, { className: "af-h-12 af-w-12 af-text-muted-foreground af-mb-4" }),
917
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("p", { className: "af-text-muted-foreground af-text-center", children: [
918
+ "No submissions yet.",
919
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("br", {}),
920
+ "Submissions will appear here when visitors use your form."
921
+ ] })
922
+ ] });
923
+ }
924
+ const startIndex = page * pageSize + 1;
925
+ const endIndex = Math.min((page + 1) * pageSize, total);
926
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className, children: [
927
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Table, { children: [
928
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TableHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(TableRow, { children: [
929
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TableHead, { children: "Email" }),
930
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TableHead, { children: "Preview" }),
931
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TableHead, { children: "Date" }),
932
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TableHead, { className: "af-text-right", children: "Actions" })
933
+ ] }) }),
934
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TableBody, { children: submissions.map((submission) => {
935
+ const email = getEmailFromData(submission.data);
936
+ const preview = getPreviewText(submission.data);
937
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(TableRow, { children: [
938
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TableCell, { className: "af-font-medium", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "af-flex af-items-center af-gap-2", children: [
939
+ email || /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "af-text-muted-foreground af-italic", children: "No email" }),
940
+ submission.attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "af-flex af-items-center af-gap-1 af-text-muted-foreground", title: `${submission.attachments.length} attachment(s)`, children: [
941
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react4.Paperclip, { className: "af-h-3 af-w-3" }),
942
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "af-text-xs", children: submission.attachments.length })
943
+ ] })
944
+ ] }) }),
945
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TableCell, { className: "af-text-muted-foreground af-max-w-[200px] af-truncate", children: preview || /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "af-italic", children: "No preview available" }) }),
946
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TableCell, { className: "af-text-muted-foreground", children: formatDate2(submission.metadata.submitted_at) }),
947
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TableCell, { className: "af-text-right", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
948
+ Button,
949
+ {
950
+ variant: "ghost",
951
+ size: "icon",
952
+ onClick: () => handleViewSubmission(submission),
953
+ title: "View details",
954
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react4.Eye, { className: "af-h-4 af-w-4" })
955
+ }
956
+ ) })
957
+ ] }, submission.id);
958
+ }) })
959
+ ] }),
960
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "af-flex af-items-center af-justify-between af-px-2 af-py-4", children: [
961
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "af-flex af-items-center af-gap-2 af-text-sm af-text-muted-foreground", children: [
962
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { children: [
963
+ "Showing ",
964
+ startIndex,
965
+ "-",
966
+ endIndex,
967
+ " of ",
968
+ total
969
+ ] }),
970
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
971
+ Select,
972
+ {
973
+ value: String(pageSize),
974
+ onValueChange: (value) => setPageSize(Number(value)),
975
+ children: [
976
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectTrigger, { className: "af-w-[70px] af-h-8", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectValue, {}) }),
977
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(SelectContent, { children: [
978
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectItem, { value: "10", children: "10" }),
979
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectItem, { value: "25", children: "25" }),
980
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectItem, { value: "50", children: "50" }),
981
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectItem, { value: "100", children: "100" })
982
+ ] })
983
+ ]
984
+ }
985
+ ),
986
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "per page" })
987
+ ] }),
988
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "af-flex af-items-center af-gap-2", children: [
989
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
990
+ Button,
991
+ {
992
+ variant: "outline",
993
+ size: "sm",
994
+ onClick: () => setPage(page - 1),
995
+ disabled: !hasPreviousPage,
996
+ children: [
997
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react4.ChevronLeft, { className: "af-h-4 af-w-4 af-mr-1" }),
998
+ "Previous"
999
+ ]
1000
+ }
1001
+ ),
1002
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1003
+ Button,
1004
+ {
1005
+ variant: "outline",
1006
+ size: "sm",
1007
+ onClick: () => setPage(page + 1),
1008
+ disabled: !hasNextPage,
1009
+ children: [
1010
+ "Next",
1011
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react4.ChevronRight, { className: "af-h-4 af-w-4 af-ml-1" })
1012
+ ]
1013
+ }
1014
+ )
1015
+ ] })
1016
+ ] })
1017
+ ] });
1018
+ }
1019
+
1020
+ // src/components/FormSettings.tsx
1021
+ var React12 = __toESM(require("react"), 1);
1022
+ var import_lucide_react5 = require("lucide-react");
1023
+
1024
+ // src/ui/input.tsx
1025
+ var React10 = __toESM(require("react"), 1);
1026
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1027
+ var Input = React10.forwardRef(
1028
+ ({ className, type, ...props }, ref) => {
1029
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1030
+ "input",
1031
+ {
1032
+ type,
1033
+ className: cn(
1034
+ "af-flex af-h-9 af-w-full af-rounded-md af-border af-border-input af-bg-transparent af-px-3 af-py-1 af-text-sm af-shadow-sm af-transition-colors file:af-border-0 file:af-bg-transparent file:af-text-sm file:af-font-medium file:af-text-foreground placeholder:af-text-muted-foreground focus-visible:af-outline-none focus-visible:af-ring-1 focus-visible:af-ring-ring disabled:af-cursor-not-allowed disabled:af-opacity-50",
1035
+ className
1036
+ ),
1037
+ ref,
1038
+ ...props
1039
+ }
1040
+ );
1041
+ }
1042
+ );
1043
+ Input.displayName = "Input";
1044
+
1045
+ // src/ui/label.tsx
1046
+ var React11 = __toESM(require("react"), 1);
1047
+ var import_class_variance_authority2 = require("class-variance-authority");
1048
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1049
+ var labelVariants = (0, import_class_variance_authority2.cva)(
1050
+ "af-text-sm af-font-medium af-leading-none peer-disabled:af-cursor-not-allowed peer-disabled:af-opacity-70"
1051
+ );
1052
+ var Label2 = React11.forwardRef(
1053
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { ref, className: cn(labelVariants(), className), ...props })
1054
+ );
1055
+ Label2.displayName = "Label";
1056
+
1057
+ // src/ui/badge.tsx
1058
+ var import_class_variance_authority3 = require("class-variance-authority");
1059
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1060
+ var badgeVariants = (0, import_class_variance_authority3.cva)(
1061
+ "af-inline-flex af-items-center af-rounded-md af-border af-px-2.5 af-py-0.5 af-text-xs af-font-semibold af-transition-colors focus:af-outline-none focus:af-ring-2 focus:af-ring-ring focus:af-ring-offset-2",
1062
+ {
1063
+ variants: {
1064
+ variant: {
1065
+ default: "af-border-transparent af-bg-primary af-text-primary-foreground af-shadow hover:af-bg-primary/80",
1066
+ secondary: "af-border-transparent af-bg-secondary af-text-secondary-foreground hover:af-bg-secondary/80",
1067
+ destructive: "af-border-transparent af-bg-destructive af-text-destructive-foreground af-shadow hover:af-bg-destructive/80",
1068
+ outline: "af-text-foreground",
1069
+ success: "af-border-transparent af-bg-green-100 af-text-green-800",
1070
+ warning: "af-border-transparent af-bg-yellow-100 af-text-yellow-800"
1071
+ }
1072
+ },
1073
+ defaultVariants: {
1074
+ variant: "default"
1075
+ }
1076
+ }
1077
+ );
1078
+ function Badge({ className, variant, ...props }) {
1079
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
1080
+ }
1081
+
1082
+ // src/components/FormSettings.tsx
1083
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1084
+ function FormSettings({ form, onSaved, className }) {
1085
+ const { updateForm } = useForms();
1086
+ const [isSaving, setIsSaving] = React12.useState(false);
1087
+ const [lastSaved, setLastSaved] = React12.useState(null);
1088
+ const [error, setError] = React12.useState(null);
1089
+ const [name, setName] = React12.useState(form.name);
1090
+ const [redirectUrl, setRedirectUrl] = React12.useState(form.redirect_url || "");
1091
+ const [emailRecipients, setEmailRecipients] = React12.useState(
1092
+ form.email_recipients
1093
+ );
1094
+ const [newEmail, setNewEmail] = React12.useState("");
1095
+ React12.useEffect(() => {
1096
+ setName(form.name);
1097
+ setRedirectUrl(form.redirect_url || "");
1098
+ setEmailRecipients(form.email_recipients);
1099
+ setError(null);
1100
+ }, [form]);
1101
+ const save = React12.useCallback(
1102
+ async (updates) => {
1103
+ try {
1104
+ setIsSaving(true);
1105
+ setError(null);
1106
+ const updatedForm = await updateForm(form.id, updates);
1107
+ setLastSaved(/* @__PURE__ */ new Date());
1108
+ onSaved?.(updatedForm);
1109
+ } catch (err) {
1110
+ setError(err instanceof Error ? err.message : "Failed to save");
1111
+ } finally {
1112
+ setIsSaving(false);
1113
+ }
1114
+ },
1115
+ [form.id, updateForm, onSaved]
1116
+ );
1117
+ React12.useEffect(() => {
1118
+ if (lastSaved) {
1119
+ const timer = setTimeout(() => setLastSaved(null), 2e3);
1120
+ return () => clearTimeout(timer);
1121
+ }
1122
+ }, [lastSaved]);
1123
+ const handleAddEmail = async () => {
1124
+ const email = newEmail.trim().toLowerCase();
1125
+ if (!email) return;
1126
+ if (!email.includes("@")) {
1127
+ setError("Please enter a valid email address");
1128
+ return;
1129
+ }
1130
+ if (emailRecipients.includes(email)) {
1131
+ setError("This email is already added");
1132
+ return;
1133
+ }
1134
+ const newRecipients = [...emailRecipients, email];
1135
+ setEmailRecipients(newRecipients);
1136
+ setNewEmail("");
1137
+ setError(null);
1138
+ await save({ email_recipients: newRecipients });
1139
+ };
1140
+ const handleRemoveEmail = async (email) => {
1141
+ const newRecipients = emailRecipients.filter((e) => e !== email);
1142
+ setEmailRecipients(newRecipients);
1143
+ await save({ email_recipients: newRecipients });
1144
+ };
1145
+ const handleNameBlur = async () => {
1146
+ if (name !== form.name) {
1147
+ await save({ name });
1148
+ }
1149
+ };
1150
+ const handleRedirectBlur = async () => {
1151
+ const newValue = redirectUrl || null;
1152
+ if (newValue !== form.redirect_url) {
1153
+ await save({ redirect_url: newValue });
1154
+ }
1155
+ };
1156
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: `af-space-y-6 af-relative ${className || ""}`, children: [
1157
+ (isSaving || lastSaved) && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "aifeatures-admin af-fixed af-bottom-4 af-right-4 af-z-50", children: isSaving ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "af-flex af-items-center af-gap-2 af-bg-background af-border af-shadow-lg af-rounded-lg af-px-4 af-py-3", children: [
1158
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.Loader2, { className: "af-h-4 af-w-4 af-animate-spin af-text-muted-foreground" }),
1159
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "af-text-sm", children: "Saving..." })
1160
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "af-flex af-items-center af-gap-2 af-bg-green-50 af-border af-border-green-200 af-shadow-lg af-rounded-lg af-px-4 af-py-3", children: [
1161
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.Check, { className: "af-h-4 af-w-4 af-text-green-600" }),
1162
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "af-text-sm af-text-green-800", children: "Changes saved" })
1163
+ ] }) }),
1164
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "af-space-y-2", children: [
1165
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Label2, { htmlFor: "form-name", children: "Form Name" }),
1166
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1167
+ Input,
1168
+ {
1169
+ id: "form-name",
1170
+ value: name,
1171
+ onChange: (e) => setName(e.target.value),
1172
+ onBlur: handleNameBlur,
1173
+ placeholder: "Contact Form"
1174
+ }
1175
+ ),
1176
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "af-text-xs af-text-muted-foreground", children: "A name to identify this form in your dashboard." })
1177
+ ] }),
1178
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "af-space-y-2", children: [
1179
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Label2, { children: "Email Recipients" }),
1180
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "af-text-xs af-text-muted-foreground af-mb-2", children: "Form submissions will be sent to these email addresses." }),
1181
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "af-flex af-flex-wrap af-gap-2 af-mb-2", children: [
1182
+ emailRecipients.map((email) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Badge, { variant: "secondary", className: "af-gap-1", children: [
1183
+ email,
1184
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1185
+ "button",
1186
+ {
1187
+ type: "button",
1188
+ onClick: () => handleRemoveEmail(email),
1189
+ className: "af-ml-1 hover:af-text-destructive",
1190
+ disabled: isSaving,
1191
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.X, { className: "af-h-3 af-w-3" })
1192
+ }
1193
+ )
1194
+ ] }, email)),
1195
+ emailRecipients.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "af-text-sm af-text-muted-foreground af-italic", children: "No recipients configured" })
1196
+ ] }),
1197
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "af-flex af-gap-2", children: [
1198
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1199
+ Input,
1200
+ {
1201
+ type: "email",
1202
+ value: newEmail,
1203
+ onChange: (e) => setNewEmail(e.target.value),
1204
+ placeholder: "Add email address",
1205
+ onKeyDown: (e) => {
1206
+ if (e.key === "Enter") {
1207
+ e.preventDefault();
1208
+ handleAddEmail();
1209
+ }
1210
+ },
1211
+ disabled: isSaving
1212
+ }
1213
+ ),
1214
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1215
+ Button,
1216
+ {
1217
+ type: "button",
1218
+ variant: "outline",
1219
+ onClick: handleAddEmail,
1220
+ disabled: !newEmail.trim() || isSaving,
1221
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.Plus, { className: "af-h-4 af-w-4" })
1222
+ }
1223
+ )
1224
+ ] })
1225
+ ] }),
1226
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "af-space-y-2", children: [
1227
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Label2, { htmlFor: "redirect-url", children: "Redirect URL" }),
1228
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1229
+ Input,
1230
+ {
1231
+ id: "redirect-url",
1232
+ value: redirectUrl,
1233
+ onChange: (e) => setRedirectUrl(e.target.value),
1234
+ onBlur: handleRedirectBlur,
1235
+ placeholder: "/thank-you"
1236
+ }
1237
+ ),
1238
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "af-text-xs af-text-muted-foreground", children: "URL to redirect visitors to after successful submission. Leave empty for a default success page." })
1239
+ ] }),
1240
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "af-space-y-2", children: [
1241
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Label2, { children: "Form Endpoint" }),
1242
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "af-flex af-items-center af-gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("code", { className: "af-flex-1 af-text-xs af-bg-muted af-px-3 af-py-2 af-rounded af-border", children: form.endpoint_url }) }),
1243
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "af-text-xs af-text-muted-foreground", children: "Use this URL as the form action attribute." })
1244
+ ] }),
1245
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "af-space-y-2", children: [
1246
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Label2, { children: "Captcha Protection" }),
1247
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "af-flex af-items-center af-gap-2", children: [
1248
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Badge, { variant: form.captcha.enabled ? "success" : "secondary", children: form.captcha.enabled ? "Enabled" : "Disabled" }),
1249
+ form.captcha.enabled && form.captcha.provider && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "af-text-xs af-text-muted-foreground", children: [
1250
+ "(",
1251
+ form.captcha.provider,
1252
+ ")"
1253
+ ] })
1254
+ ] })
1255
+ ] }),
1256
+ error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "af-text-sm af-text-destructive af-bg-destructive/10 af-px-3 af-py-2 af-rounded", children: error })
1257
+ ] });
1258
+ }
1259
+
1260
+ // src/components/FormsDashboard.tsx
1261
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1262
+ function FormsDashboard({ className }) {
1263
+ const [view, setView] = React13.useState("list");
1264
+ const [selectedForm, setSelectedForm] = React13.useState(null);
1265
+ const [activeTab, setActiveTab] = React13.useState(
1266
+ "submissions"
1267
+ );
1268
+ const handleSelectForm = (form, tab) => {
1269
+ setSelectedForm(form);
1270
+ setView("detail");
1271
+ setActiveTab(tab);
1272
+ };
1273
+ const handleBack = () => {
1274
+ setView("list");
1275
+ setSelectedForm(null);
1276
+ };
1277
+ const handleFormSaved = (updatedForm) => {
1278
+ setSelectedForm(updatedForm);
1279
+ };
1280
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className, children: [
1281
+ view === "list" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
1282
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "af-mb-6", children: [
1283
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h2", { className: "af-text-lg af-font-semibold", children: "Forms" }),
1284
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "af-text-sm af-text-muted-foreground", children: "Manage your contact forms and view submissions." })
1285
+ ] }),
1286
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(FormsList, { onSelectForm: handleSelectForm })
1287
+ ] }),
1288
+ view === "detail" && selectedForm && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
1289
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "af-mb-6", children: [
1290
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1291
+ Button,
1292
+ {
1293
+ variant: "ghost",
1294
+ size: "sm",
1295
+ onClick: handleBack,
1296
+ className: "af-mb-2 af--ml-2",
1297
+ children: [
1298
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react6.ArrowLeft, { className: "af-h-4 af-w-4 af-mr-1" }),
1299
+ "Back to Forms"
1300
+ ]
1301
+ }
1302
+ ),
1303
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h2", { className: "af-text-lg af-font-semibold", children: selectedForm.name }),
1304
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "af-text-sm af-text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("code", { className: "af-text-xs af-bg-muted af-px-1.5 af-py-0.5 af-rounded", children: selectedForm.endpoint_url }) })
1305
+ ] }),
1306
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1307
+ Tabs,
1308
+ {
1309
+ value: activeTab,
1310
+ onValueChange: (v) => setActiveTab(v),
1311
+ children: [
1312
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(TabsList, { className: "af-mb-4", children: [
1313
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(TabsTrigger, { value: "submissions", className: "af-gap-2", children: [
1314
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react6.Inbox, { className: "af-h-4 af-w-4" }),
1315
+ "Submissions"
1316
+ ] }),
1317
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(TabsTrigger, { value: "settings", className: "af-gap-2", children: [
1318
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react6.Settings, { className: "af-h-4 af-w-4" }),
1319
+ "Settings"
1320
+ ] })
1321
+ ] }),
1322
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TabsContent, { value: "submissions", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(FormSubmissions, { formId: selectedForm.id }) }),
1323
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TabsContent, { value: "settings", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(FormSettings, { form: selectedForm, onSaved: handleFormSaved }) })
1324
+ ]
1325
+ }
1326
+ )
1327
+ ] })
1328
+ ] });
1329
+ }
1330
+ // Annotate the CommonJS export names for ESM import in node:
1331
+ 0 && (module.exports = {
1332
+ AifeaturesApiError,
1333
+ AifeaturesProvider,
1334
+ FormSettings,
1335
+ FormSubmissions,
1336
+ FormsDashboard,
1337
+ FormsList,
1338
+ SubmissionDetail,
1339
+ createApiClient,
1340
+ useAifeatures,
1341
+ useAifeaturesContext,
1342
+ useForms,
1343
+ useSubmissions
1344
+ });
1345
+ //# sourceMappingURL=index.cjs.map