@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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/provider/AifeaturesProvider.tsx","../src/lib/api.ts","../src/components/FormsDashboard.tsx","../src/ui/tabs.tsx","../src/lib/cn.ts","../src/ui/button.tsx","../src/components/FormsList.tsx","../src/ui/table.tsx","../src/hooks/useForms.ts","../src/components/FormSubmissions.tsx","../src/ui/select.tsx","../src/hooks/useSubmissions.ts","../src/components/SubmissionDetail.tsx","../src/components/FormSettings.tsx","../src/ui/input.tsx","../src/ui/label.tsx","../src/ui/badge.tsx"],"sourcesContent":["import * as React from 'react'\nimport { createApiClient, type AifeaturesApiClient } from '../lib/api'\n\nexport interface AifeaturesContextValue {\n siteToken: string\n apiUrl: string\n api: AifeaturesApiClient\n}\n\nconst AifeaturesContext = React.createContext<AifeaturesContextValue | null>(\n null\n)\n\nexport interface AifeaturesProviderProps {\n /** Site-scoped API token from aifeatures */\n siteToken: string\n /** API URL (defaults to https://aifeatures.dev) */\n apiUrl?: string\n /** Optional dark mode */\n dark?: boolean\n /** Optional className for the wrapper */\n className?: string\n children: React.ReactNode\n}\n\n/**\n * Validates the token and returns an error message if invalid\n */\nfunction validateToken(token: string): string | null {\n if (!token) {\n return 'No siteToken provided to AifeaturesProvider'\n }\n\n if (token.startsWith('sk_')) {\n 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.'\n }\n\n if (!token.startsWith('st_')) {\n 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.`\n }\n\n return null\n}\n\nexport function AifeaturesProvider({\n siteToken,\n apiUrl = 'https://aifeatures.dev',\n dark = false,\n className,\n children,\n}: AifeaturesProviderProps) {\n // Validate token on mount and when it changes\n const tokenError = React.useMemo(() => validateToken(siteToken), [siteToken])\n\n const api = React.useMemo(\n () => createApiClient(siteToken, apiUrl),\n [siteToken, apiUrl]\n )\n\n const value = React.useMemo(\n () => ({\n siteToken,\n apiUrl,\n api,\n }),\n [siteToken, apiUrl, api]\n )\n\n // Show error UI if token is invalid\n if (tokenError) {\n return (\n <div className={`aifeatures-admin ${dark ? 'dark' : ''} ${className || ''}`}>\n <div className=\"af-rounded-md af-border af-border-destructive af-bg-destructive/10 af-p-4\">\n <h3 className=\"af-text-sm af-font-semibold af-text-destructive af-mb-2\">\n AifeaturesProvider Configuration Error\n </h3>\n <p className=\"af-text-sm af-text-destructive\">\n {tokenError}\n </p>\n </div>\n </div>\n )\n }\n\n return (\n <AifeaturesContext.Provider value={value}>\n <div className={`aifeatures-admin ${dark ? 'dark' : ''} ${className || ''}`}>\n {children}\n </div>\n </AifeaturesContext.Provider>\n )\n}\n\nexport function useAifeaturesContext(): AifeaturesContextValue {\n const context = React.useContext(AifeaturesContext)\n if (!context) {\n throw new Error(\n 'useAifeaturesContext must be used within an AifeaturesProvider'\n )\n }\n return context\n}\n\nexport { AifeaturesContext }\n","import type {\n Form,\n Submission,\n FormsListResponse,\n PaginatedSubmissions,\n CreateFormInput,\n UpdateFormInput,\n GetSubmissionsOptions,\n ApiError,\n} from '../types'\n\nexport class AifeaturesApiError extends Error {\n constructor(\n message: string,\n public status: number,\n public details?: ApiError\n ) {\n super(message)\n this.name = 'AifeaturesApiError'\n }\n}\n\nexport interface AifeaturesApiClient {\n // Forms\n getForms(): Promise<Form[]>\n getForm(formId: string): Promise<Form>\n createForm(input: CreateFormInput): Promise<Form>\n updateForm(formId: string, input: UpdateFormInput): Promise<Form>\n deleteForm(formId: string): Promise<void>\n\n // Submissions\n getSubmissions(\n formId: string,\n options?: GetSubmissionsOptions\n ): Promise<PaginatedSubmissions>\n getSubmission(submissionId: string): Promise<Submission>\n deleteSubmission(submissionId: string): Promise<void>\n\n // Attachments\n downloadAttachment(submissionId: string, filename: string): Promise<void>\n}\n\nexport function createApiClient(\n siteToken: string,\n apiUrl: string = 'https://aifeatures.dev'\n): AifeaturesApiClient {\n async function request<T>(\n path: string,\n options: RequestInit = {}\n ): Promise<T> {\n const url = `${apiUrl}${path}`\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Authorization': `Bearer ${siteToken}`,\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n })\n\n if (!response.ok) {\n let details: ApiError | undefined\n try {\n details = await response.json()\n } catch {\n // Ignore JSON parse errors\n }\n throw new AifeaturesApiError(\n details?.error || `Request failed with status ${response.status}`,\n response.status,\n details\n )\n }\n\n // Handle 204 No Content\n if (response.status === 204) {\n return undefined as T\n }\n\n return response.json()\n }\n\n return {\n // Forms\n async getForms(): Promise<Form[]> {\n const data = await request<FormsListResponse>('/api/v1/forms')\n return data.forms\n },\n\n async getForm(formId: string): Promise<Form> {\n return request<Form>(`/api/v1/forms/${formId}`)\n },\n\n async createForm(input: CreateFormInput): Promise<Form> {\n return request<Form>('/api/v1/forms', {\n method: 'POST',\n body: JSON.stringify(input),\n })\n },\n\n async updateForm(formId: string, input: UpdateFormInput): Promise<Form> {\n return request<Form>(`/api/v1/forms/${formId}`, {\n method: 'PATCH',\n body: JSON.stringify(input),\n })\n },\n\n async deleteForm(formId: string): Promise<void> {\n await request<void>(`/api/v1/forms/${formId}`, {\n method: 'DELETE',\n })\n },\n\n // Submissions\n async getSubmissions(\n formId: string,\n options: GetSubmissionsOptions = {}\n ): Promise<PaginatedSubmissions> {\n const params = new URLSearchParams()\n if (options.limit !== undefined) {\n params.set('limit', String(options.limit))\n }\n if (options.offset !== undefined) {\n params.set('offset', String(options.offset))\n }\n const query = params.toString()\n const path = `/api/v1/forms/${formId}/submissions${query ? `?${query}` : ''}`\n return request<PaginatedSubmissions>(path)\n },\n\n async getSubmission(submissionId: string): Promise<Submission> {\n return request<Submission>(`/api/v1/submissions/${submissionId}`)\n },\n\n async deleteSubmission(submissionId: string): Promise<void> {\n await request<void>(`/api/v1/submissions/${submissionId}`, {\n method: 'DELETE',\n })\n },\n\n // Attachments\n async downloadAttachment(submissionId: string, filename: string): Promise<void> {\n const url = `${apiUrl}/api/v1/submissions/${submissionId}/attachments/${encodeURIComponent(filename)}`\n const response = await fetch(url, {\n headers: {\n 'Authorization': `Bearer ${siteToken}`,\n },\n })\n\n if (!response.ok) {\n let details: ApiError | undefined\n try {\n details = await response.json()\n } catch {\n // Ignore JSON parse errors\n }\n throw new AifeaturesApiError(\n details?.error || `Download failed with status ${response.status}`,\n response.status,\n details\n )\n }\n\n // Create blob and trigger download\n const blob = await response.blob()\n const blobUrl = URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.href = blobUrl\n link.download = filename\n document.body.appendChild(link)\n link.click()\n document.body.removeChild(link)\n URL.revokeObjectURL(blobUrl)\n },\n }\n}\n","import * as React from 'react'\nimport { ArrowLeft, Settings, Inbox } from 'lucide-react'\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '../ui/tabs'\nimport { Button } from '../ui/button'\nimport { FormsList } from './FormsList'\nimport { FormSubmissions } from './FormSubmissions'\nimport { FormSettings } from './FormSettings'\nimport type { Form } from '../types'\n\nexport interface FormsDashboardProps {\n /** Optional className */\n className?: string\n}\n\ntype View = 'list' | 'detail'\n\nexport function FormsDashboard({ className }: FormsDashboardProps) {\n const [view, setView] = React.useState<View>('list')\n const [selectedForm, setSelectedForm] = React.useState<Form | null>(null)\n const [activeTab, setActiveTab] = React.useState<'submissions' | 'settings'>(\n 'submissions'\n )\n\n const handleSelectForm = (form: Form, tab: 'submissions' | 'settings') => {\n setSelectedForm(form)\n setView('detail')\n setActiveTab(tab)\n }\n\n const handleBack = () => {\n setView('list')\n setSelectedForm(null)\n }\n\n const handleFormSaved = (updatedForm: Form) => {\n setSelectedForm(updatedForm)\n }\n\n return (\n <div className={className}>\n {view === 'list' && (\n <div>\n <div className=\"af-mb-6\">\n <h2 className=\"af-text-lg af-font-semibold\">Forms</h2>\n <p className=\"af-text-sm af-text-muted-foreground\">\n Manage your contact forms and view submissions.\n </p>\n </div>\n <FormsList onSelectForm={handleSelectForm} />\n </div>\n )}\n\n {view === 'detail' && selectedForm && (\n <div>\n {/* Header with back button */}\n <div className=\"af-mb-6\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleBack}\n className=\"af-mb-2 af--ml-2\"\n >\n <ArrowLeft className=\"af-h-4 af-w-4 af-mr-1\" />\n Back to Forms\n </Button>\n <h2 className=\"af-text-lg af-font-semibold\">{selectedForm.name}</h2>\n <p className=\"af-text-sm af-text-muted-foreground\">\n <code className=\"af-text-xs af-bg-muted af-px-1.5 af-py-0.5 af-rounded\">\n {selectedForm.endpoint_url}\n </code>\n </p>\n </div>\n\n {/* Tabs for submissions and settings */}\n <Tabs\n value={activeTab}\n onValueChange={(v) => setActiveTab(v as 'submissions' | 'settings')}\n >\n <TabsList className=\"af-mb-4\">\n <TabsTrigger value=\"submissions\" className=\"af-gap-2\">\n <Inbox className=\"af-h-4 af-w-4\" />\n Submissions\n </TabsTrigger>\n <TabsTrigger value=\"settings\" className=\"af-gap-2\">\n <Settings className=\"af-h-4 af-w-4\" />\n Settings\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"submissions\">\n <FormSubmissions formId={selectedForm.id} />\n </TabsContent>\n\n <TabsContent value=\"settings\">\n <FormSettings form={selectedForm} onSaved={handleFormSaved} />\n </TabsContent>\n </Tabs>\n </div>\n )}\n </div>\n )\n}\n","import * as React from 'react'\nimport * as TabsPrimitive from '@radix-ui/react-tabs'\nimport { cn } from '../lib/cn'\n\nconst Tabs = TabsPrimitive.Root\n\nconst TabsList = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.List\n ref={ref}\n className={cn(\n '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',\n className\n )}\n {...props}\n />\n))\nTabsList.displayName = TabsPrimitive.List.displayName\n\nconst TabsTrigger = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Trigger\n ref={ref}\n className={cn(\n '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',\n className\n )}\n {...props}\n />\n))\nTabsTrigger.displayName = TabsPrimitive.Trigger.displayName\n\nconst TabsContent = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Content\n ref={ref}\n className={cn(\n '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',\n className\n )}\n {...props}\n />\n))\nTabsContent.displayName = TabsPrimitive.Content.displayName\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent }\n","import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import * as React from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../lib/cn'\n\nconst buttonVariants = cva(\n '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',\n {\n variants: {\n variant: {\n default:\n 'af-bg-primary af-text-primary-foreground af-shadow hover:af-bg-primary/90',\n destructive:\n 'af-bg-destructive af-text-destructive-foreground af-shadow-sm hover:af-bg-destructive/90',\n outline:\n 'af-border af-border-input af-bg-background af-shadow-sm hover:af-bg-accent hover:af-text-accent-foreground',\n secondary:\n 'af-bg-secondary af-text-secondary-foreground af-shadow-sm hover:af-bg-secondary/80',\n ghost: 'hover:af-bg-accent hover:af-text-accent-foreground',\n link: 'af-text-primary af-underline-offset-4 hover:af-underline',\n },\n size: {\n default: 'af-h-9 af-px-4 af-py-2',\n sm: 'af-h-8 af-rounded-md af-px-3 af-text-xs',\n lg: 'af-h-10 af-rounded-md af-px-8',\n icon: 'af-h-9 af-w-9',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button'\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n {...props}\n />\n )\n }\n)\nButton.displayName = 'Button'\n\nexport { Button, buttonVariants }\n","import * as React from 'react'\nimport { Inbox, Settings } from 'lucide-react'\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '../ui/table'\nimport { Button } from '../ui/button'\nimport { useForms } from '../hooks/useForms'\nimport type { Form } from '../types'\n\nexport interface FormsListProps {\n /** Called when a form is selected */\n onSelectForm?: (form: Form, tab: 'submissions' | 'settings') => void\n /** Optional className */\n className?: string\n}\n\nexport function FormsList({ onSelectForm, className }: FormsListProps) {\n const { forms, isLoading, error } = useForms()\n\n if (isLoading) {\n return (\n <div className={`af-flex af-items-center af-justify-center af-py-8 ${className || ''}`}>\n <div className=\"af-text-muted-foreground\">Loading forms...</div>\n </div>\n )\n }\n\n if (error) {\n return (\n <div className={`af-flex af-items-center af-justify-center af-py-8 ${className || ''}`}>\n <div className=\"af-text-destructive\">Error: {error.message}</div>\n </div>\n )\n }\n\n if (forms.length === 0) {\n return (\n <div className={`af-flex af-flex-col af-items-center af-justify-center af-py-12 ${className || ''}`}>\n <Inbox className=\"af-h-12 af-w-12 af-text-muted-foreground af-mb-4\" />\n <p className=\"af-text-muted-foreground af-text-center\">\n No forms yet.\n <br />\n Forms will appear here when the AI creates contact forms on your website.\n </p>\n </div>\n )\n }\n\n return (\n <div className={className}>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Name</TableHead>\n <TableHead>Endpoint</TableHead>\n <TableHead className=\"af-text-right\">Actions</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {forms.map((form) => (\n <TableRow key={form.id}>\n <TableCell className=\"af-font-medium\">{form.name}</TableCell>\n <TableCell>\n <code className=\"af-text-xs af-bg-muted af-px-1.5 af-py-0.5 af-rounded\">\n {form.endpoint_url.replace('https://aifeatures.dev', '')}\n </code>\n </TableCell>\n <TableCell className=\"af-text-right\">\n <div className=\"af-flex af-items-center af-justify-end af-gap-2\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => onSelectForm?.(form, 'submissions')}\n >\n <Inbox className=\"af-h-4 af-w-4 af-mr-1\" />\n Submissions\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => onSelectForm?.(form, 'settings')}\n >\n <Settings className=\"af-h-4 af-w-4 af-mr-1\" />\n Settings\n </Button>\n </div>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n )\n}\n","import * as React from 'react'\nimport { cn } from '../lib/cn'\n\nconst Table = React.forwardRef<\n HTMLTableElement,\n React.HTMLAttributes<HTMLTableElement>\n>(({ className, ...props }, ref) => (\n <div className=\"af-relative af-w-full af-overflow-auto\">\n <table\n ref={ref}\n className={cn('af-w-full af-caption-bottom af-text-sm', className)}\n {...props}\n />\n </div>\n))\nTable.displayName = 'Table'\n\nconst TableHeader = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <thead ref={ref} className={cn('[&_tr]:af-border-b', className)} {...props} />\n))\nTableHeader.displayName = 'TableHeader'\n\nconst TableBody = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tbody\n ref={ref}\n className={cn('[&_tr:last-child]:af-border-0', className)}\n {...props}\n />\n))\nTableBody.displayName = 'TableBody'\n\nconst TableFooter = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tfoot\n ref={ref}\n className={cn(\n 'af-border-t af-bg-muted/50 af-font-medium [&>tr]:last:af-border-b-0',\n className\n )}\n {...props}\n />\n))\nTableFooter.displayName = 'TableFooter'\n\nconst TableRow = React.forwardRef<\n HTMLTableRowElement,\n React.HTMLAttributes<HTMLTableRowElement>\n>(({ className, ...props }, ref) => (\n <tr\n ref={ref}\n className={cn(\n 'af-border-b af-transition-colors hover:af-bg-muted/50 data-[state=selected]:af-bg-muted',\n className\n )}\n {...props}\n />\n))\nTableRow.displayName = 'TableRow'\n\nconst TableHead = React.forwardRef<\n HTMLTableCellElement,\n React.ThHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <th\n ref={ref}\n className={cn(\n '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]',\n className\n )}\n {...props}\n />\n))\nTableHead.displayName = 'TableHead'\n\nconst TableCell = React.forwardRef<\n HTMLTableCellElement,\n React.TdHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <td\n ref={ref}\n className={cn(\n 'af-p-2 af-align-middle [&:has([role=checkbox])]:af-pr-0 [&>[role=checkbox]]:af-translate-y-[2px]',\n className\n )}\n {...props}\n />\n))\nTableCell.displayName = 'TableCell'\n\nconst TableCaption = React.forwardRef<\n HTMLTableCaptionElement,\n React.HTMLAttributes<HTMLTableCaptionElement>\n>(({ className, ...props }, ref) => (\n <caption\n ref={ref}\n className={cn('af-mt-4 af-text-sm af-text-muted-foreground', className)}\n {...props}\n />\n))\nTableCaption.displayName = 'TableCaption'\n\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n}\n","import * as React from 'react'\nimport { useAifeaturesContext } from '../provider/AifeaturesProvider'\nimport type { Form, CreateFormInput, UpdateFormInput } from '../types'\n\nexport interface UseFormsReturn {\n forms: Form[]\n isLoading: boolean\n error: Error | null\n refetch: () => Promise<void>\n createForm: (input: CreateFormInput) => Promise<Form>\n updateForm: (formId: string, input: UpdateFormInput) => Promise<Form>\n deleteForm: (formId: string) => Promise<void>\n}\n\nexport function useForms(): UseFormsReturn {\n const { api } = useAifeaturesContext()\n const [forms, setForms] = React.useState<Form[]>([])\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<Error | null>(null)\n\n const fetchForms = React.useCallback(async () => {\n try {\n setIsLoading(true)\n setError(null)\n const data = await api.getForms()\n setForms(data)\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to fetch forms'))\n } finally {\n setIsLoading(false)\n }\n }, [api])\n\n React.useEffect(() => {\n fetchForms()\n }, [fetchForms])\n\n const createForm = React.useCallback(\n async (input: CreateFormInput): Promise<Form> => {\n const form = await api.createForm(input)\n setForms((prev) => [...prev, form])\n return form\n },\n [api]\n )\n\n const updateForm = React.useCallback(\n async (formId: string, input: UpdateFormInput): Promise<Form> => {\n const form = await api.updateForm(formId, input)\n setForms((prev) => prev.map((f) => (f.id === formId ? form : f)))\n return form\n },\n [api]\n )\n\n const deleteForm = React.useCallback(\n async (formId: string): Promise<void> => {\n await api.deleteForm(formId)\n setForms((prev) => prev.filter((f) => f.id !== formId))\n },\n [api]\n )\n\n return {\n forms,\n isLoading,\n error,\n refetch: fetchForms,\n createForm,\n updateForm,\n deleteForm,\n }\n}\n","import * as React from 'react'\nimport {\n ChevronLeft,\n ChevronRight,\n Eye,\n Inbox,\n Paperclip,\n} from 'lucide-react'\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '../ui/table'\nimport { Button } from '../ui/button'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../ui/select'\nimport { useSubmissions } from '../hooks/useSubmissions'\nimport { SubmissionDetail } from './SubmissionDetail'\nimport type { Submission } from '../types'\n\nexport interface FormSubmissionsProps {\n /** The form ID to show submissions for */\n formId: string\n /** Optional className */\n className?: string\n}\n\ntype View = 'list' | 'detail'\n\nfunction formatDate(dateString: string): string {\n return new Date(dateString).toLocaleString(undefined, {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n })\n}\n\nfunction getEmailFromData(data: Record<string, unknown>): string | null {\n // Try common email field names\n const emailFields = ['email', 'Email', 'EMAIL', 'e-mail', 'mail']\n for (const field of emailFields) {\n if (typeof data[field] === 'string') {\n return data[field] as string\n }\n }\n return null\n}\n\nfunction getPreviewText(data: Record<string, unknown>): string {\n // Get first non-email, non-internal field as preview\n const entries = Object.entries(data).filter(\n ([key]) => !key.startsWith('_') && !key.toLowerCase().includes('email')\n )\n if (entries.length === 0) return ''\n\n const [, value] = entries[0]\n const text = String(value)\n return text.length > 50 ? text.slice(0, 50) + '...' : text\n}\n\nexport function FormSubmissions({ formId, className }: FormSubmissionsProps) {\n const {\n submissions,\n total,\n isLoading,\n error,\n page,\n pageSize,\n hasNextPage,\n hasPreviousPage,\n setPage,\n setPageSize,\n } = useSubmissions({ formId })\n\n const [view, setView] = React.useState<View>('list')\n const [selectedSubmission, setSelectedSubmission] =\n React.useState<Submission | null>(null)\n\n const handleViewSubmission = (submission: Submission) => {\n setSelectedSubmission(submission)\n setView('detail')\n }\n\n const handleBack = () => {\n setView('list')\n setSelectedSubmission(null)\n }\n\n // Show detail view\n if (view === 'detail' && selectedSubmission) {\n return (\n <div className={className}>\n <SubmissionDetail\n submission={selectedSubmission}\n onBack={handleBack}\n />\n </div>\n )\n }\n\n // Show list view\n if (isLoading) {\n return (\n <div className={`af-flex af-items-center af-justify-center af-py-8 ${className || ''}`}>\n <div className=\"af-text-muted-foreground\">Loading submissions...</div>\n </div>\n )\n }\n\n if (error) {\n return (\n <div className={`af-flex af-items-center af-justify-center af-py-8 ${className || ''}`}>\n <div className=\"af-text-destructive\">Error: {error.message}</div>\n </div>\n )\n }\n\n if (submissions.length === 0 && page === 0) {\n return (\n <div className={`af-flex af-flex-col af-items-center af-justify-center af-py-12 ${className || ''}`}>\n <Inbox className=\"af-h-12 af-w-12 af-text-muted-foreground af-mb-4\" />\n <p className=\"af-text-muted-foreground af-text-center\">\n No submissions yet.\n <br />\n Submissions will appear here when visitors use your form.\n </p>\n </div>\n )\n }\n\n const startIndex = page * pageSize + 1\n const endIndex = Math.min((page + 1) * pageSize, total)\n\n return (\n <div className={className}>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Email</TableHead>\n <TableHead>Preview</TableHead>\n <TableHead>Date</TableHead>\n <TableHead className=\"af-text-right\">Actions</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {submissions.map((submission) => {\n const email = getEmailFromData(submission.data)\n const preview = getPreviewText(submission.data)\n\n return (\n <TableRow key={submission.id}>\n <TableCell className=\"af-font-medium\">\n <div className=\"af-flex af-items-center af-gap-2\">\n {email || (\n <span className=\"af-text-muted-foreground af-italic\">No email</span>\n )}\n {submission.attachments.length > 0 && (\n <span className=\"af-flex af-items-center af-gap-1 af-text-muted-foreground\" title={`${submission.attachments.length} attachment(s)`}>\n <Paperclip className=\"af-h-3 af-w-3\" />\n <span className=\"af-text-xs\">{submission.attachments.length}</span>\n </span>\n )}\n </div>\n </TableCell>\n <TableCell className=\"af-text-muted-foreground af-max-w-[200px] af-truncate\">\n {preview || (\n <span className=\"af-italic\">No preview available</span>\n )}\n </TableCell>\n <TableCell className=\"af-text-muted-foreground\">\n {formatDate(submission.metadata.submitted_at)}\n </TableCell>\n <TableCell className=\"af-text-right\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => handleViewSubmission(submission)}\n title=\"View details\"\n >\n <Eye className=\"af-h-4 af-w-4\" />\n </Button>\n </TableCell>\n </TableRow>\n )\n })}\n </TableBody>\n </Table>\n\n {/* Pagination */}\n <div className=\"af-flex af-items-center af-justify-between af-px-2 af-py-4\">\n <div className=\"af-flex af-items-center af-gap-2 af-text-sm af-text-muted-foreground\">\n <span>\n Showing {startIndex}-{endIndex} of {total}\n </span>\n <Select\n value={String(pageSize)}\n onValueChange={(value) => setPageSize(Number(value))}\n >\n <SelectTrigger className=\"af-w-[70px] af-h-8\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"10\">10</SelectItem>\n <SelectItem value=\"25\">25</SelectItem>\n <SelectItem value=\"50\">50</SelectItem>\n <SelectItem value=\"100\">100</SelectItem>\n </SelectContent>\n </Select>\n <span>per page</span>\n </div>\n <div className=\"af-flex af-items-center af-gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setPage(page - 1)}\n disabled={!hasPreviousPage}\n >\n <ChevronLeft className=\"af-h-4 af-w-4 af-mr-1\" />\n Previous\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setPage(page + 1)}\n disabled={!hasNextPage}\n >\n Next\n <ChevronRight className=\"af-h-4 af-w-4 af-ml-1\" />\n </Button>\n </div>\n </div>\n </div>\n )\n}\n","import * as React from 'react'\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { Check, ChevronDown, ChevronUp } from 'lucide-react'\nimport { cn } from '../lib/cn'\n\nconst Select = SelectPrimitive.Root\n\nconst SelectGroup = SelectPrimitive.Group\n\nconst SelectValue = SelectPrimitive.Value\n\nconst SelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Trigger\n ref={ref}\n className={cn(\n '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',\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDown className=\"af-h-4 af-w-4 af-opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n))\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName\n\nconst SelectScrollUpButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton\n ref={ref}\n className={cn(\n 'af-flex af-cursor-default af-items-center af-justify-center af-py-1',\n className\n )}\n {...props}\n >\n <ChevronUp className=\"af-h-4 af-w-4\" />\n </SelectPrimitive.ScrollUpButton>\n))\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName\n\nconst SelectScrollDownButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton\n ref={ref}\n className={cn(\n 'af-flex af-cursor-default af-items-center af-justify-center af-py-1',\n className\n )}\n {...props}\n >\n <ChevronDown className=\"af-h-4 af-w-4\" />\n </SelectPrimitive.ScrollDownButton>\n))\nSelectScrollDownButton.displayName =\n SelectPrimitive.ScrollDownButton.displayName\n\nconst SelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(({ className, children, position = 'popper', ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n className={cn(\n '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',\n position === 'popper' &&\n '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',\n className\n )}\n position={position}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n 'af-p-1',\n position === 'popper' &&\n 'af-h-[var(--radix-select-trigger-height)] af-w-full af-min-w-[var(--radix-select-trigger-width)]'\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n))\nSelectContent.displayName = SelectPrimitive.Content.displayName\n\nconst SelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn('af-px-2 af-py-1.5 af-text-sm af-font-semibold', className)}\n {...props}\n />\n))\nSelectLabel.displayName = SelectPrimitive.Label.displayName\n\nconst SelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n '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',\n className\n )}\n {...props}\n >\n <span className=\"af-absolute af-right-2 af-flex af-h-3.5 af-w-3.5 af-items-center af-justify-center\">\n <SelectPrimitive.ItemIndicator>\n <Check className=\"af-h-4 af-w-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n))\nSelectItem.displayName = SelectPrimitive.Item.displayName\n\nconst SelectSeparator = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn('af--mx-1 af-my-1 af-h-px af-bg-muted', className)}\n {...props}\n />\n))\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName\n\nexport {\n Select,\n SelectGroup,\n SelectValue,\n SelectTrigger,\n SelectContent,\n SelectLabel,\n SelectItem,\n SelectSeparator,\n SelectScrollUpButton,\n SelectScrollDownButton,\n}\n","import * as React from 'react'\nimport { useAifeaturesContext } from '../provider/AifeaturesProvider'\nimport type {\n Submission,\n PaginatedSubmissions,\n GetSubmissionsOptions,\n} from '../types'\n\nexport interface UseSubmissionsReturn {\n submissions: Submission[]\n total: number\n isLoading: boolean\n error: Error | null\n page: number\n pageSize: number\n hasNextPage: boolean\n hasPreviousPage: boolean\n setPage: (page: number) => void\n setPageSize: (size: number) => void\n refetch: () => Promise<void>\n deleteSubmission: (submissionId: string) => Promise<void>\n}\n\nexport interface UseSubmissionsOptions {\n formId: string\n initialPageSize?: number\n}\n\nexport function useSubmissions({\n formId,\n initialPageSize = 25,\n}: UseSubmissionsOptions): UseSubmissionsReturn {\n const { api } = useAifeaturesContext()\n const [submissions, setSubmissions] = React.useState<Submission[]>([])\n const [total, setTotal] = React.useState(0)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<Error | null>(null)\n const [page, setPage] = React.useState(0)\n const [pageSize, setPageSize] = React.useState(initialPageSize)\n\n const fetchSubmissions = React.useCallback(async () => {\n if (!formId) return\n\n try {\n setIsLoading(true)\n setError(null)\n const options: GetSubmissionsOptions = {\n limit: pageSize,\n offset: page * pageSize,\n }\n const data: PaginatedSubmissions = await api.getSubmissions(\n formId,\n options\n )\n setSubmissions(data.submissions)\n setTotal(data.total)\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error('Failed to fetch submissions')\n )\n } finally {\n setIsLoading(false)\n }\n }, [api, formId, page, pageSize])\n\n React.useEffect(() => {\n fetchSubmissions()\n }, [fetchSubmissions])\n\n const deleteSubmission = React.useCallback(\n async (submissionId: string): Promise<void> => {\n await api.deleteSubmission(submissionId)\n setSubmissions((prev) => prev.filter((s) => s.id !== submissionId))\n setTotal((prev) => prev - 1)\n },\n [api]\n )\n\n const totalPages = Math.ceil(total / pageSize)\n\n return {\n submissions,\n total,\n isLoading,\n error,\n page,\n pageSize,\n hasNextPage: page < totalPages - 1,\n hasPreviousPage: page > 0,\n setPage,\n setPageSize: (size: number) => {\n setPageSize(size)\n setPage(0) // Reset to first page when page size changes\n },\n refetch: fetchSubmissions,\n deleteSubmission,\n }\n}\n","import * as React from 'react'\nimport { ArrowLeft, Download, Globe, Clock, FileText, Loader2, Monitor, Mail } from 'lucide-react'\nimport { Button } from '../ui/button'\nimport { useAifeaturesContext } from '../provider/AifeaturesProvider'\nimport type { Submission } from '../types'\n\nexport interface SubmissionDetailProps {\n submission: Submission\n onBack: () => void\n}\n\nfunction formatDate(dateString: string): string {\n return new Date(dateString).toLocaleString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n })\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B'\n const k = 1024\n const sizes = ['B', 'KB', 'MB', 'GB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`\n}\n\nexport function SubmissionDetail({\n submission,\n onBack,\n}: SubmissionDetailProps) {\n const { api } = useAifeaturesContext()\n const [downloadingFile, setDownloadingFile] = React.useState<string | null>(null)\n\n const handleDownload = async (filename: string) => {\n setDownloadingFile(filename)\n try {\n await api.downloadAttachment(submission.id, filename)\n } catch (error) {\n console.error('Download failed:', error)\n } finally {\n setDownloadingFile(null)\n }\n }\n\n const dataEntries = Object.entries(submission.data).filter(\n ([key]) => !key.startsWith('_')\n )\n\n return (\n <div>\n {/* Header with back button */}\n <div className=\"af-mb-6\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={onBack}\n className=\"af-mb-2 af--ml-2\"\n >\n <ArrowLeft className=\"af-h-4 af-w-4 af-mr-1\" />\n Back to Submissions\n </Button>\n <h3 className=\"af-text-lg af-font-semibold\">Submission Details</h3>\n <p className=\"af-text-sm af-text-muted-foreground\">\n Submitted {formatDate(submission.metadata.submitted_at)}\n </p>\n </div>\n\n <div className=\"af-space-y-6\">\n {/* Form Data */}\n <div>\n <h4 className=\"af-text-sm af-font-medium af-mb-3\">Form Data</h4>\n <div className=\"af-space-y-3\">\n {dataEntries.map(([key, value]) => (\n <div key={key} className=\"af-grid af-grid-cols-3 af-gap-2\">\n <div className=\"af-text-sm af-text-muted-foreground af-capitalize\">\n {key.replace(/_/g, ' ')}\n </div>\n <div className=\"af-col-span-2 af-text-sm af-break-words\">\n {typeof value === 'string' && value.includes('\\n') ? (\n <pre className=\"af-whitespace-pre-wrap af-font-sans af-bg-muted af-p-2 af-rounded af-text-xs\">\n {value}\n </pre>\n ) : (\n String(value)\n )}\n </div>\n </div>\n ))}\n {dataEntries.length === 0 && (\n <p className=\"af-text-sm af-text-muted-foreground\">No data submitted</p>\n )}\n </div>\n </div>\n\n {/* Attachments */}\n {submission.attachments.length > 0 && (\n <div>\n <h4 className=\"af-text-sm af-font-medium af-mb-3\">Attachments</h4>\n <div className=\"af-space-y-2\">\n {submission.attachments.map((attachment, index) => (\n <div\n key={index}\n className=\"af-flex af-items-center af-justify-between af-p-2 af-bg-muted af-rounded\"\n >\n <div className=\"af-flex af-items-center af-gap-2\">\n <FileText className=\"af-h-4 af-w-4 af-text-muted-foreground\" />\n <span className=\"af-text-sm\">{attachment.name}</span>\n <span className=\"af-text-xs af-text-muted-foreground\">\n ({formatBytes(attachment.size)})\n </span>\n </div>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => handleDownload(attachment.name)}\n disabled={downloadingFile === attachment.name}\n >\n {downloadingFile === attachment.name ? (\n <Loader2 className=\"af-h-4 af-w-4 af-mr-1 af-animate-spin\" />\n ) : (\n <Download className=\"af-h-4 af-w-4 af-mr-1\" />\n )}\n {downloadingFile === attachment.name ? 'Downloading...' : 'Download'}\n </Button>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Metadata */}\n <div>\n <h4 className=\"af-text-sm af-font-medium af-mb-3\">Metadata</h4>\n <div className=\"af-space-y-2 af-text-sm\">\n <div className=\"af-flex af-items-center af-gap-2 af-text-muted-foreground\">\n <Clock className=\"af-h-4 af-w-4\" />\n <span>{formatDate(submission.metadata.submitted_at)}</span>\n </div>\n {submission.metadata.ip_address && (\n <div className=\"af-flex af-items-center af-gap-2 af-text-muted-foreground\">\n <Globe className=\"af-h-4 af-w-4\" />\n <span>IP: {submission.metadata.ip_address}</span>\n </div>\n )}\n {submission.metadata.user_agent && (\n <div className=\"af-flex af-items-start af-gap-2 af-text-muted-foreground\">\n <Monitor className=\"af-h-4 af-w-4 af-mt-0.5\" />\n <span className=\"af-text-xs af-break-all\">\n {submission.metadata.user_agent}\n </span>\n </div>\n )}\n {submission.resend_id && (\n <div className=\"af-flex af-items-center af-gap-2 af-text-muted-foreground\">\n <Mail className=\"af-h-4 af-w-4\" />\n <span>Email ID: {submission.resend_id}</span>\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n )\n}\n","import * as React from 'react'\nimport { Plus, X, Loader2, Check } from 'lucide-react'\nimport { Button } from '../ui/button'\nimport { Input } from '../ui/input'\nimport { Label } from '../ui/label'\nimport { Badge } from '../ui/badge'\nimport { useForms } from '../hooks/useForms'\nimport type { Form, UpdateFormInput } from '../types'\n\nexport interface FormSettingsProps {\n /** The form to edit */\n form: Form\n /** Called when settings are saved */\n onSaved?: (form: Form) => void\n /** Optional className */\n className?: string\n}\n\nexport function FormSettings({ form, onSaved, className }: FormSettingsProps) {\n const { updateForm } = useForms()\n const [isSaving, setIsSaving] = React.useState(false)\n const [lastSaved, setLastSaved] = React.useState<Date | null>(null)\n const [error, setError] = React.useState<string | null>(null)\n\n // Local form state\n const [name, setName] = React.useState(form.name)\n const [redirectUrl, setRedirectUrl] = React.useState(form.redirect_url || '')\n const [emailRecipients, setEmailRecipients] = React.useState<string[]>(\n form.email_recipients\n )\n const [newEmail, setNewEmail] = React.useState('')\n\n // Reset state when form changes\n React.useEffect(() => {\n setName(form.name)\n setRedirectUrl(form.redirect_url || '')\n setEmailRecipients(form.email_recipients)\n setError(null)\n }, [form])\n\n // Auto-save function\n const save = React.useCallback(\n async (updates: UpdateFormInput) => {\n try {\n setIsSaving(true)\n setError(null)\n const updatedForm = await updateForm(form.id, updates)\n setLastSaved(new Date())\n onSaved?.(updatedForm)\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to save')\n } finally {\n setIsSaving(false)\n }\n },\n [form.id, updateForm, onSaved]\n )\n\n // Clear \"saved\" indicator after 2 seconds\n React.useEffect(() => {\n if (lastSaved) {\n const timer = setTimeout(() => setLastSaved(null), 2000)\n return () => clearTimeout(timer)\n }\n }, [lastSaved])\n\n const handleAddEmail = async () => {\n const email = newEmail.trim().toLowerCase()\n if (!email) return\n if (!email.includes('@')) {\n setError('Please enter a valid email address')\n return\n }\n if (emailRecipients.includes(email)) {\n setError('This email is already added')\n return\n }\n const newRecipients = [...emailRecipients, email]\n setEmailRecipients(newRecipients)\n setNewEmail('')\n setError(null)\n await save({ email_recipients: newRecipients })\n }\n\n const handleRemoveEmail = async (email: string) => {\n const newRecipients = emailRecipients.filter((e) => e !== email)\n setEmailRecipients(newRecipients)\n await save({ email_recipients: newRecipients })\n }\n\n // Save text fields on blur\n const handleNameBlur = async () => {\n if (name !== form.name) {\n await save({ name })\n }\n }\n\n const handleRedirectBlur = async () => {\n const newValue = redirectUrl || null\n if (newValue !== form.redirect_url) {\n await save({ redirect_url: newValue })\n }\n }\n\n return (\n <div className={`af-space-y-6 af-relative ${className || ''}`}>\n {/* Toast notification */}\n {(isSaving || lastSaved) && (\n <div className=\"aifeatures-admin af-fixed af-bottom-4 af-right-4 af-z-50\">\n {isSaving ? (\n <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\">\n <Loader2 className=\"af-h-4 af-w-4 af-animate-spin af-text-muted-foreground\" />\n <span className=\"af-text-sm\">Saving...</span>\n </div>\n ) : (\n <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\">\n <Check className=\"af-h-4 af-w-4 af-text-green-600\" />\n <span className=\"af-text-sm af-text-green-800\">Changes saved</span>\n </div>\n )}\n </div>\n )}\n\n {/* Form Name */}\n <div className=\"af-space-y-2\">\n <Label htmlFor=\"form-name\">Form Name</Label>\n <Input\n id=\"form-name\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n onBlur={handleNameBlur}\n placeholder=\"Contact Form\"\n />\n <p className=\"af-text-xs af-text-muted-foreground\">\n A name to identify this form in your dashboard.\n </p>\n </div>\n\n {/* Email Recipients */}\n <div className=\"af-space-y-2\">\n <Label>Email Recipients</Label>\n <p className=\"af-text-xs af-text-muted-foreground af-mb-2\">\n Form submissions will be sent to these email addresses.\n </p>\n <div className=\"af-flex af-flex-wrap af-gap-2 af-mb-2\">\n {emailRecipients.map((email) => (\n <Badge key={email} variant=\"secondary\" className=\"af-gap-1\">\n {email}\n <button\n type=\"button\"\n onClick={() => handleRemoveEmail(email)}\n className=\"af-ml-1 hover:af-text-destructive\"\n disabled={isSaving}\n >\n <X className=\"af-h-3 af-w-3\" />\n </button>\n </Badge>\n ))}\n {emailRecipients.length === 0 && (\n <span className=\"af-text-sm af-text-muted-foreground af-italic\">\n No recipients configured\n </span>\n )}\n </div>\n <div className=\"af-flex af-gap-2\">\n <Input\n type=\"email\"\n value={newEmail}\n onChange={(e) => setNewEmail(e.target.value)}\n placeholder=\"Add email address\"\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault()\n handleAddEmail()\n }\n }}\n disabled={isSaving}\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={handleAddEmail}\n disabled={!newEmail.trim() || isSaving}\n >\n <Plus className=\"af-h-4 af-w-4\" />\n </Button>\n </div>\n </div>\n\n {/* Redirect URL */}\n <div className=\"af-space-y-2\">\n <Label htmlFor=\"redirect-url\">Redirect URL</Label>\n <Input\n id=\"redirect-url\"\n value={redirectUrl}\n onChange={(e) => setRedirectUrl(e.target.value)}\n onBlur={handleRedirectBlur}\n placeholder=\"/thank-you\"\n />\n <p className=\"af-text-xs af-text-muted-foreground\">\n URL to redirect visitors to after successful submission. Leave empty\n for a default success page.\n </p>\n </div>\n\n {/* Form Endpoint (read-only) */}\n <div className=\"af-space-y-2\">\n <Label>Form Endpoint</Label>\n <div className=\"af-flex af-items-center af-gap-2\">\n <code className=\"af-flex-1 af-text-xs af-bg-muted af-px-3 af-py-2 af-rounded af-border\">\n {form.endpoint_url}\n </code>\n </div>\n <p className=\"af-text-xs af-text-muted-foreground\">\n Use this URL as the form action attribute.\n </p>\n </div>\n\n {/* Captcha Status (read-only for now) */}\n <div className=\"af-space-y-2\">\n <Label>Captcha Protection</Label>\n <div className=\"af-flex af-items-center af-gap-2\">\n <Badge variant={form.captcha.enabled ? 'success' : 'secondary'}>\n {form.captcha.enabled ? 'Enabled' : 'Disabled'}\n </Badge>\n {form.captcha.enabled && form.captcha.provider && (\n <span className=\"af-text-xs af-text-muted-foreground\">\n ({form.captcha.provider})\n </span>\n )}\n </div>\n </div>\n\n {/* Error message */}\n {error && (\n <div className=\"af-text-sm af-text-destructive af-bg-destructive/10 af-px-3 af-py-2 af-rounded\">\n {error}\n </div>\n )}\n </div>\n )\n}\n","import * as React from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface InputProps\n extends React.InputHTMLAttributes<HTMLInputElement> {}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n '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',\n className\n )}\n ref={ref}\n {...props}\n />\n )\n }\n)\nInput.displayName = 'Input'\n\nexport { Input }\n","import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../lib/cn'\n\nconst labelVariants = cva(\n 'af-text-sm af-font-medium af-leading-none peer-disabled:af-cursor-not-allowed peer-disabled:af-opacity-70'\n)\n\nexport interface LabelProps\n extends React.LabelHTMLAttributes<HTMLLabelElement>,\n VariantProps<typeof labelVariants> {}\n\nconst Label = React.forwardRef<HTMLLabelElement, LabelProps>(\n ({ className, ...props }, ref) => (\n <label ref={ref} className={cn(labelVariants(), className)} {...props} />\n )\n)\nLabel.displayName = 'Label'\n\nexport { Label }\n","import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../lib/cn'\n\nconst badgeVariants = cva(\n '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',\n {\n variants: {\n variant: {\n default:\n 'af-border-transparent af-bg-primary af-text-primary-foreground af-shadow hover:af-bg-primary/80',\n secondary:\n 'af-border-transparent af-bg-secondary af-text-secondary-foreground hover:af-bg-secondary/80',\n destructive:\n 'af-border-transparent af-bg-destructive af-text-destructive-foreground af-shadow hover:af-bg-destructive/80',\n outline: 'af-text-foreground',\n success:\n 'af-border-transparent af-bg-green-100 af-text-green-800',\n warning:\n 'af-border-transparent af-bg-yellow-100 af-text-yellow-800',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n)\n\nexport interface BadgeProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof badgeVariants> {}\n\nfunction Badge({ className, variant, ...props }: BadgeProps) {\n return (\n <div className={cn(badgeVariants({ variant }), className)} {...props} />\n )\n}\n\nexport { Badge, badgeVariants }\n"],"mappings":"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","names":["React","ArrowLeft","Settings","Inbox","React","jsx","React","jsx","React","jsx","React","jsx","jsxs","React","Inbox","React","jsx","jsxs","jsxs","jsx","React","React","jsx","jsxs","jsx","jsxs","formatDate","Inbox","React","Loader2","Check","React","jsx","React","cva","jsx","cva","Label","cva","jsx","cva","jsx","jsxs","Loader2","Check","Label","jsx","jsxs","ArrowLeft","Inbox","Settings"]}
@@ -0,0 +1 @@
1
+ .af-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.af-fixed{position:fixed}.af-absolute{position:absolute}.af-relative{position:relative}.af-inset-0{inset:0}.af-bottom-4{bottom:1rem}.af-left-\[50\%\]{left:50%}.af-right-2{right:.5rem}.af-right-4{right:1rem}.af-top-4{top:1rem}.af-top-\[50\%\]{top:50%}.af-z-50{z-index:50}.af-col-span-2{grid-column:span 2/span 2}.af--mx-1{margin-left:-.25rem;margin-right:-.25rem}.af-my-1{margin-top:.25rem;margin-bottom:.25rem}.af--ml-2{margin-left:-.5rem}.af-mb-2{margin-bottom:.5rem}.af-mb-3{margin-bottom:.75rem}.af-mb-4{margin-bottom:1rem}.af-mb-6{margin-bottom:1.5rem}.af-ml-1{margin-left:.25rem}.af-mr-1{margin-right:.25rem}.af-mt-0\.5{margin-top:.125rem}.af-mt-2{margin-top:.5rem}.af-mt-4{margin-top:1rem}.af-flex{display:flex}.af-inline-flex{display:inline-flex}.af-grid{display:grid}.af-h-10{height:2.5rem}.af-h-12{height:3rem}.af-h-3{height:.75rem}.af-h-3\.5{height:.875rem}.af-h-4{height:1rem}.af-h-8{height:2rem}.af-h-9{height:2.25rem}.af-h-\[var\(--radix-select-trigger-height\)\]{height:var(--radix-select-trigger-height)}.af-h-px{height:1px}.af-max-h-96{max-height:24rem}.af-w-12{width:3rem}.af-w-3{width:.75rem}.af-w-3\.5{width:.875rem}.af-w-4{width:1rem}.af-w-9{width:2.25rem}.af-w-\[70px\]{width:70px}.af-w-full{width:100%}.af-min-w-\[8rem\]{min-width:8rem}.af-min-w-\[var\(--radix-select-trigger-width\)\]{min-width:var(--radix-select-trigger-width)}.af-max-w-\[200px\]{max-width:200px}.af-max-w-lg{max-width:32rem}.af-flex-1{flex:1 1 0%}.af-caption-bottom{caption-side:bottom}.af-translate-x-\[-50\%\]{--tw-translate-x:-50%}.af-translate-x-\[-50\%\],.af-translate-y-\[-50\%\]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.af-translate-y-\[-50\%\]{--tw-translate-y:-50%}@keyframes af-spin{to{transform:rotate(1turn)}}.af-animate-spin{animation:af-spin 1s linear infinite}.af-cursor-default{cursor:default}.af-select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.af-grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.af-flex-col{flex-direction:column}.af-flex-col-reverse{flex-direction:column-reverse}.af-flex-wrap{flex-wrap:wrap}.af-items-start{align-items:flex-start}.af-items-center{align-items:center}.af-justify-end{justify-content:flex-end}.af-justify-center{justify-content:center}.af-justify-between{justify-content:space-between}.af-gap-1{gap:.25rem}.af-gap-2{gap:.5rem}.af-gap-4{gap:1rem}.af-space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem*var(--tw-space-y-reverse))}.af-space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.af-space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.af-space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.af-overflow-auto{overflow:auto}.af-overflow-hidden,.af-truncate{overflow:hidden}.af-truncate{text-overflow:ellipsis}.af-truncate,.af-whitespace-nowrap{white-space:nowrap}.af-whitespace-pre-wrap{white-space:pre-wrap}.af-break-words{overflow-wrap:break-word}.af-break-all{word-break:break-all}.af-rounded{border-radius:.25rem}.af-rounded-lg{border-radius:var(--radius)}.af-rounded-md{border-radius:calc(var(--radius) - 2px)}.af-rounded-sm{border-radius:calc(var(--radius) - 4px)}.af-border{border-width:1px}.af-border-b{border-bottom-width:1px}.af-border-t{border-top-width:1px}.af-border-destructive{border-color:hsl(var(--destructive))}.af-border-green-200{--tw-border-opacity:1;border-color:rgb(187 247 208/var(--tw-border-opacity,1))}.af-border-input{border-color:hsl(var(--input))}.af-border-transparent{border-color:transparent}.af-bg-background{background-color:hsl(var(--background))}.af-bg-black\/80{background-color:rgba(0,0,0,.8)}.af-bg-destructive{background-color:hsl(var(--destructive))}.af-bg-destructive\/10{background-color:hsl(var(--destructive)/.1)}.af-bg-green-100{--tw-bg-opacity:1;background-color:rgb(220 252 231/var(--tw-bg-opacity,1))}.af-bg-green-50{--tw-bg-opacity:1;background-color:rgb(240 253 244/var(--tw-bg-opacity,1))}.af-bg-muted{background-color:hsl(var(--muted))}.af-bg-muted\/50{background-color:hsl(var(--muted)/.5)}.af-bg-popover{background-color:hsl(var(--popover))}.af-bg-primary{background-color:hsl(var(--primary))}.af-bg-secondary{background-color:hsl(var(--secondary))}.af-bg-transparent{background-color:transparent}.af-bg-yellow-100{--tw-bg-opacity:1;background-color:rgb(254 249 195/var(--tw-bg-opacity,1))}.af-p-1{padding:.25rem}.af-p-2{padding:.5rem}.af-p-4{padding:1rem}.af-p-6{padding:1.5rem}.af-px-1\.5{padding-left:.375rem;padding-right:.375rem}.af-px-2{padding-left:.5rem;padding-right:.5rem}.af-px-2\.5{padding-left:.625rem;padding-right:.625rem}.af-px-3{padding-left:.75rem;padding-right:.75rem}.af-px-4{padding-left:1rem;padding-right:1rem}.af-px-8{padding-left:2rem;padding-right:2rem}.af-py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.af-py-1{padding-top:.25rem;padding-bottom:.25rem}.af-py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.af-py-12{padding-top:3rem;padding-bottom:3rem}.af-py-2{padding-top:.5rem;padding-bottom:.5rem}.af-py-3{padding-top:.75rem;padding-bottom:.75rem}.af-py-4{padding-top:1rem;padding-bottom:1rem}.af-py-8{padding-top:2rem;padding-bottom:2rem}.af-pl-2{padding-left:.5rem}.af-pr-8{padding-right:2rem}.af-text-left{text-align:left}.af-text-center{text-align:center}.af-text-right{text-align:right}.af-align-middle{vertical-align:middle}.af-font-sans{font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.af-text-lg{font-size:1.125rem;line-height:1.75rem}.af-text-sm{font-size:.875rem;line-height:1.25rem}.af-text-xs{font-size:.75rem;line-height:1rem}.af-font-medium{font-weight:500}.af-font-semibold{font-weight:600}.af-capitalize{text-transform:capitalize}.af-italic{font-style:italic}.af-leading-none{line-height:1}.af-tracking-tight{letter-spacing:-.025em}.af-text-destructive{color:hsl(var(--destructive))}.af-text-destructive-foreground{color:hsl(var(--destructive-foreground))}.af-text-foreground{color:hsl(var(--foreground))}.af-text-green-600{--tw-text-opacity:1;color:rgb(22 163 74/var(--tw-text-opacity,1))}.af-text-green-800{--tw-text-opacity:1;color:rgb(22 101 52/var(--tw-text-opacity,1))}.af-text-muted-foreground{color:hsl(var(--muted-foreground))}.af-text-popover-foreground{color:hsl(var(--popover-foreground))}.af-text-primary{color:hsl(var(--primary))}.af-text-primary-foreground{color:hsl(var(--primary-foreground))}.af-text-secondary-foreground{color:hsl(var(--secondary-foreground))}.af-text-yellow-800{--tw-text-opacity:1;color:rgb(133 77 14/var(--tw-text-opacity,1))}.af-underline-offset-4{text-underline-offset:4px}.af-opacity-50{opacity:.5}.af-opacity-70{opacity:.7}.af-shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.af-shadow,.af-shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.af-shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.af-shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.af-shadow-md,.af-shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.af-shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.af-outline-none{outline:2px solid transparent;outline-offset:2px}.af-ring-offset-background{--tw-ring-offset-color:hsl(var(--background))}.af-transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.af-transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.af-transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.aifeatures-admin{--background:0 0% 100%;--foreground:222.2 47.4% 11.2%;--muted:210 40% 96.1%;--muted-foreground:215.4 16.3% 46.9%;--popover:0 0% 100%;--popover-foreground:222.2 47.4% 11.2%;--border:214.3 31.8% 91.4%;--input:214.3 31.8% 91.4%;--card:0 0% 100%;--card-foreground:222.2 47.4% 11.2%;--primary:222.2 47.4% 11.2%;--primary-foreground:210 40% 98%;--secondary:210 40% 96.1%;--secondary-foreground:222.2 47.4% 11.2%;--accent:210 40% 96.1%;--accent-foreground:222.2 47.4% 11.2%;--destructive:0 84.2% 60.2%;--destructive-foreground:210 40% 98%;--ring:215 20.2% 65.1%;--radius:0.5rem}.aifeatures-admin.dark{--background:224 71% 4%;--foreground:213 31% 91%;--muted:223 47% 11%;--muted-foreground:215.4 16.3% 56.9%;--popover:224 71% 4%;--popover-foreground:215 20.2% 65.1%;--border:216 34% 17%;--input:216 34% 17%;--card:224 71% 4%;--card-foreground:213 31% 91%;--primary:210 40% 98%;--primary-foreground:222.2 47.4% 1.2%;--secondary:222.2 47.4% 11.2%;--secondary-foreground:210 40% 98%;--accent:216 34% 17%;--accent-foreground:210 40% 98%;--destructive:0 63% 31%;--destructive-foreground:210 40% 98%;--ring:216 34% 17%}.aifeatures-admin{font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;color:hsl(var(--foreground))}.aifeatures-admin [class*=af-border]{border-color:hsl(var(--border))}@keyframes aifeatures-dialog-overlay-show{0%{opacity:0}to{opacity:1}}@keyframes aifeatures-dialog-content-show{0%{opacity:0;transform:translate(-50%,-48%) scale(.96)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}.aifeatures-dialog-overlay{animation:aifeatures-dialog-overlay-show .15s cubic-bezier(.16,1,.3,1)}.aifeatures-dialog-content{animation:aifeatures-dialog-content-show .15s cubic-bezier(.16,1,.3,1)}.file\:af-border-0::file-selector-button{border-width:0}.file\:af-bg-transparent::file-selector-button{background-color:transparent}.file\:af-text-sm::file-selector-button{font-size:.875rem;line-height:1.25rem}.file\:af-font-medium::file-selector-button{font-weight:500}.file\:af-text-foreground::file-selector-button{color:hsl(var(--foreground))}.placeholder\:af-text-muted-foreground::-moz-placeholder{color:hsl(var(--muted-foreground))}.placeholder\:af-text-muted-foreground::placeholder{color:hsl(var(--muted-foreground))}.hover\:af-bg-accent:hover{background-color:hsl(var(--accent))}.hover\:af-bg-destructive\/80:hover{background-color:hsl(var(--destructive)/.8)}.hover\:af-bg-destructive\/90:hover{background-color:hsl(var(--destructive)/.9)}.hover\:af-bg-muted\/50:hover{background-color:hsl(var(--muted)/.5)}.hover\:af-bg-primary\/80:hover{background-color:hsl(var(--primary)/.8)}.hover\:af-bg-primary\/90:hover{background-color:hsl(var(--primary)/.9)}.hover\:af-bg-secondary\/80:hover{background-color:hsl(var(--secondary)/.8)}.hover\:af-text-accent-foreground:hover{color:hsl(var(--accent-foreground))}.hover\:af-text-destructive:hover{color:hsl(var(--destructive))}.hover\:af-underline:hover{text-decoration-line:underline}.hover\:af-opacity-100:hover{opacity:1}.focus\:af-bg-accent:focus{background-color:hsl(var(--accent))}.focus\:af-text-accent-foreground:focus{color:hsl(var(--accent-foreground))}.focus\:af-outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:af-ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:af-ring-1:focus,.focus\:af-ring-2:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:af-ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:af-ring-ring:focus{--tw-ring-color:hsl(var(--ring))}.focus\:af-ring-offset-2:focus{--tw-ring-offset-width:2px}.focus-visible\:af-outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:af-ring-1:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus-visible\:af-ring-2:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus-visible\:af-ring-ring:focus-visible{--tw-ring-color:hsl(var(--ring))}.focus-visible\:af-ring-offset-2:focus-visible{--tw-ring-offset-width:2px}.disabled\:af-pointer-events-none:disabled{pointer-events:none}.disabled\:af-cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:af-opacity-50:disabled{opacity:.5}.af-peer:disabled~.peer-disabled\:af-cursor-not-allowed{cursor:not-allowed}.af-peer:disabled~.peer-disabled\:af-opacity-70{opacity:.7}.data-\[disabled\]\:af-pointer-events-none[data-disabled]{pointer-events:none}.data-\[side\=bottom\]\:af-translate-y-1[data-side=bottom]{--tw-translate-y:0.25rem}.data-\[side\=bottom\]\:af-translate-y-1[data-side=bottom],.data-\[side\=left\]\:af--translate-x-1[data-side=left]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[side\=left\]\:af--translate-x-1[data-side=left]{--tw-translate-x:-0.25rem}.data-\[side\=right\]\:af-translate-x-1[data-side=right]{--tw-translate-x:0.25rem}.data-\[side\=right\]\:af-translate-x-1[data-side=right],.data-\[side\=top\]\:af--translate-y-1[data-side=top]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[side\=top\]\:af--translate-y-1[data-side=top]{--tw-translate-y:-0.25rem}.data-\[state\=active\]\:af-bg-background[data-state=active]{background-color:hsl(var(--background))}.data-\[state\=open\]\:af-bg-accent[data-state=open]{background-color:hsl(var(--accent))}.data-\[state\=selected\]\:af-bg-muted[data-state=selected]{background-color:hsl(var(--muted))}.data-\[state\=active\]\:af-text-foreground[data-state=active]{color:hsl(var(--foreground))}.data-\[state\=open\]\:af-text-muted-foreground[data-state=open]{color:hsl(var(--muted-foreground))}.data-\[disabled\]\:af-opacity-50[data-disabled]{opacity:.5}.data-\[state\=active\]\:af-shadow[data-state=active]{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}@media (min-width:640px){.sm\:af-flex-row{flex-direction:row}.sm\:af-justify-end{justify-content:flex-end}.sm\:af-space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.sm\:af-rounded-lg{border-radius:var(--radius)}.sm\:af-text-left{text-align:left}}.\[\&\:has\(\[role\=checkbox\]\)\]\:af-pr-0:has([role=checkbox]){padding-right:0}.\[\&\>\[role\=checkbox\]\]\:af-translate-y-\[2px\]>[role=checkbox]{--tw-translate-y:2px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.\[\&\>span\]\:af-line-clamp-1>span{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1}.\[\&\>tr\]\:last\:af-border-b-0:last-child>tr{border-bottom-width:0}.\[\&_svg\]\:af-pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:af-size-4 svg{width:1rem;height:1rem}.\[\&_svg\]\:af-shrink-0 svg{flex-shrink:0}.\[\&_tr\:last-child\]\:af-border-0 tr:last-child{border-width:0}.\[\&_tr\]\:af-border-b tr{border-bottom-width:1px}
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "@aifeatures/admin-react",
3
+ "version": "0.1.0",
4
+ "description": "React components for managing aifeatures forms",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ },
20
+ "./styles.css": "./dist/styles.css"
21
+ },
22
+ "files": [
23
+ "dist"
24
+ ],
25
+ "peerDependencies": {
26
+ "react": ">=18",
27
+ "react-dom": ">=18"
28
+ },
29
+ "dependencies": {
30
+ "@radix-ui/react-dialog": "^1.1.2",
31
+ "@radix-ui/react-popover": "^1.1.2",
32
+ "@radix-ui/react-select": "^2.1.2",
33
+ "@radix-ui/react-slot": "^1.1.0",
34
+ "@radix-ui/react-tabs": "^1.1.1",
35
+ "class-variance-authority": "^0.7.0",
36
+ "clsx": "^2.1.1",
37
+ "lucide-react": "^0.460.0",
38
+ "tailwind-merge": "^2.5.5"
39
+ },
40
+ "devDependencies": {
41
+ "@storybook/addon-essentials": "^8.4.2",
42
+ "@storybook/addon-interactions": "^8.4.2",
43
+ "@storybook/addon-links": "^8.4.2",
44
+ "@storybook/blocks": "^8.4.2",
45
+ "@storybook/react": "^8.4.2",
46
+ "@storybook/react-vite": "^8.4.2",
47
+ "@storybook/test": "^8.4.2",
48
+ "@types/react": "^18.3.12",
49
+ "@types/react-dom": "^18.3.1",
50
+ "autoprefixer": "^10.4.20",
51
+ "msw": "^2.6.5",
52
+ "msw-storybook-addon": "^2.0.3",
53
+ "postcss": "^8.4.49",
54
+ "react": "^18.3.1",
55
+ "react-dom": "^18.3.1",
56
+ "storybook": "^8.4.2",
57
+ "tailwindcss": "^3.4.15",
58
+ "tsup": "^8.3.5",
59
+ "typescript": "^5.3.3"
60
+ },
61
+ "sideEffects": [
62
+ "*.css"
63
+ ],
64
+ "msw": {
65
+ "workerDirectory": [
66
+ ".storybook/public"
67
+ ]
68
+ },
69
+ "scripts": {
70
+ "build": "tsup && pnpm build:css",
71
+ "build:css": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --minify",
72
+ "dev": "tsup --watch",
73
+ "dev:css": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --watch",
74
+ "lint": "eslint src/",
75
+ "typecheck": "tsc --noEmit",
76
+ "storybook": "storybook dev -p 6006",
77
+ "build-storybook": "storybook build"
78
+ }
79
+ }