@maxischmaxi/maxforms-embed 0.0.5

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,11 @@
1
+ import { FormField } from '@maxischmaxi/maxforms-api-client';
2
+ export interface FileUploadProps {
3
+ field: FormField;
4
+ formId: string;
5
+ apiKey: string;
6
+ baseUrl: string;
7
+ value: string;
8
+ onChange: (value: string) => void;
9
+ }
10
+ export declare function FileUpload({ field, formId, apiKey, baseUrl, value, onChange, }: FileUploadProps): import("react/jsx-runtime").JSX.Element;
11
+ //# sourceMappingURL=FileUpload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileUpload.d.ts","sourceRoot":"","sources":["../../src/components/FileUpload.tsx"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,SAAS,EACf,MAAM,kCAAkC,CAAC;AAE1C,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AASD,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,MAAM,EACN,MAAM,EACN,OAAO,EACP,KAAK,EACL,QAAQ,GACT,EAAE,eAAe,2CAsQjB"}
@@ -0,0 +1,28 @@
1
+ import { ReactNode } from 'react';
2
+ import { FormProps } from '../types';
3
+ /**
4
+ * MaxForms embed form component with Zod validation and React Hook Form.
5
+ *
6
+ * Supports custom rendering for all field types and layout blocks through
7
+ * render props. If no custom renderer is provided, default renderers are used.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * // Basic usage
12
+ * <Form formId="abc123" apiKey="your-api-key" />
13
+ *
14
+ * // With custom renderers
15
+ * <Form
16
+ * formId="abc123"
17
+ * apiKey="your-api-key"
18
+ * renderInput={({ field, register, error }) => (
19
+ * <div>
20
+ * <input {...register(field.name)} className="my-input" />
21
+ * {error && <span className="error">{error.message}</span>}
22
+ * </div>
23
+ * )}
24
+ * />
25
+ * ```
26
+ */
27
+ export declare function Form({ formId, apiKey, baseUrl, onSubmit, onError, className, renderInput, renderTextarea, renderSelect, renderCheckbox, renderRadio, renderEmail, renderNumber, renderDate, renderFile, renderHeading, renderTextBlock, renderDivider, renderRow, renderSubmit, renderFormError, renderFieldError, renderLoading, renderSuccess, renderFieldWrapper, }: FormProps): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import('react').ReactPortal | import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element;
28
+ //# sourceMappingURL=Form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Form.d.ts","sourceRoot":"","sources":["../../src/components/Form.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAe,MAAM,OAAO,CAAC;AAUpD,OAAO,KAAK,EACV,SAAS,EAIV,MAAM,UAAU,CAAC;AAElB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,IAAI,CAAC,EACnB,MAAM,EACN,MAAM,EACN,OAAO,EACP,QAAQ,EACR,OAAO,EACP,SAAc,EAEd,WAAW,EACX,cAAc,EACd,YAAY,EACZ,cAAc,EACd,WAAW,EACX,WAAW,EACX,YAAY,EACZ,UAAU,EACV,UAAU,EAEV,aAAa,EACb,eAAe,EACf,aAAa,EACb,SAAS,EAET,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,kBAAkB,GACnB,EAAE,SAAS,wTAwRX"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Renders a horizontal divider block.
3
+ */
4
+ export declare function DividerBlock(): import("react/jsx-runtime").JSX.Element;
5
+ //# sourceMappingURL=DividerBlock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DividerBlock.d.ts","sourceRoot":"","sources":["../../../src/components/blocks/DividerBlock.tsx"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,YAAY,4CAE3B"}
@@ -0,0 +1,10 @@
1
+ import { FormBlock } from '@maxischmaxi/maxforms-api-client';
2
+ export interface HeadingBlockProps {
3
+ block: FormBlock;
4
+ }
5
+ /**
6
+ * Renders a heading block (H1, H2, or H3).
7
+ * The heading level is determined by block.level (defaults to 2).
8
+ */
9
+ export declare function HeadingBlock({ block }: HeadingBlockProps): import("react/jsx-runtime").JSX.Element;
10
+ //# sourceMappingURL=HeadingBlock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HeadingBlock.d.ts","sourceRoot":"","sources":["../../../src/components/blocks/HeadingBlock.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAElE,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,SAAS,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,EAAE,iBAAiB,2CAcxD"}
@@ -0,0 +1,13 @@
1
+ import { ReactNode } from 'react';
2
+ import { FormBlock } from '@maxischmaxi/maxforms-api-client';
3
+ export interface RowBlockProps {
4
+ block: FormBlock;
5
+ /** Function to render a child block */
6
+ renderChild: (child: FormBlock) => ReactNode;
7
+ }
8
+ /**
9
+ * Renders a row block with multiple columns.
10
+ * The number of columns is determined by block.columns (defaults to 2).
11
+ */
12
+ export declare function RowBlock({ block, renderChild }: RowBlockProps): import("react/jsx-runtime").JSX.Element;
13
+ //# sourceMappingURL=RowBlock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RowBlock.d.ts","sourceRoot":"","sources":["../../../src/components/blocks/RowBlock.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAElE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,SAAS,CAAC;IACjB,uCAAuC;IACvC,WAAW,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,SAAS,CAAC;CAC9C;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,aAAa,2CAa7D"}
@@ -0,0 +1,10 @@
1
+ import { FormBlock } from '@maxischmaxi/maxforms-api-client';
2
+ export interface TextBlockProps {
3
+ block: FormBlock;
4
+ }
5
+ /**
6
+ * Renders a text/paragraph block.
7
+ * The content can contain HTML from the rich text editor.
8
+ */
9
+ export declare function TextBlock({ block }: TextBlockProps): import("react/jsx-runtime").JSX.Element;
10
+ //# sourceMappingURL=TextBlock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextBlock.d.ts","sourceRoot":"","sources":["../../../src/components/blocks/TextBlock.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,cAAc,2CAgBlD"}
@@ -0,0 +1,5 @@
1
+ export { HeadingBlock, type HeadingBlockProps } from './HeadingBlock';
2
+ export { TextBlock, type TextBlockProps } from './TextBlock';
3
+ export { DividerBlock } from './DividerBlock';
4
+ export { RowBlock, type RowBlockProps } from './RowBlock';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/blocks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { UseMaxFormOptions, UseMaxFormReturn } from '../types';
2
+ /**
3
+ * A powerful hook for building custom form UIs with MaxForms.
4
+ *
5
+ * This hook provides full access to:
6
+ * - React Hook Form instance for form state management
7
+ * - Zod validation schema built from form field definitions
8
+ * - Form configuration (fields, layout, settings)
9
+ * - Loading, submitting, and success states
10
+ * - Submit and reset actions
11
+ * - Helper functions for accessing fields and errors
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * function MyCustomForm() {
16
+ * const {
17
+ * form,
18
+ * fields,
19
+ * isLoading,
20
+ * isSubmitting,
21
+ * isSuccess,
22
+ * submitForm,
23
+ * getFieldError,
24
+ * settings,
25
+ * } = useMaxForm({
26
+ * formId: "abc123",
27
+ * apiKey: "your-api-key",
28
+ * });
29
+ *
30
+ * if (isLoading) return <Spinner />;
31
+ * if (isSuccess) return <p>{settings.successMessage}</p>;
32
+ *
33
+ * return (
34
+ * <form onSubmit={form.handleSubmit(submitForm)}>
35
+ * {fields.map((field) => (
36
+ * <div key={field.id}>
37
+ * <label>{field.label}</label>
38
+ * <input {...form.register(field.name)} />
39
+ * {getFieldError(field.name) && (
40
+ * <span>{getFieldError(field.name)}</span>
41
+ * )}
42
+ * </div>
43
+ * ))}
44
+ * <button disabled={isSubmitting}>
45
+ * {isSubmitting ? "Submitting..." : settings.submitButtonText}
46
+ * </button>
47
+ * </form>
48
+ * );
49
+ * }
50
+ * ```
51
+ */
52
+ export declare function useMaxForm(options: UseMaxFormOptions): UseMaxFormReturn;
53
+ //# sourceMappingURL=useMaxForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMaxForm.d.ts","sourceRoot":"","sources":["../../src/hooks/useMaxForm.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAY,MAAM,UAAU,CAAC;AAoB9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,gBAAgB,CAuMvE"}
@@ -0,0 +1,27 @@
1
+ import { Form } from './components/Form';
2
+ import { FileUpload, FileUploadProps } from './components/FileUpload';
3
+ import { useMaxForm } from './hooks/useMaxForm';
4
+ export type { FormProps, FormData, FormSettingsData, FieldRenderContext, FileFieldRenderContext, RenderInputFn, RenderTextareaFn, RenderSelectFn, RenderCheckboxFn, RenderRadioFn, RenderEmailFn, RenderNumberFn, RenderDateFn, RenderFileFn, RenderHeadingFn, RenderTextBlockFn, RenderDividerFn, RenderRowFn, RenderSubmitFn, RenderFormErrorFn, RenderFieldErrorFn, RenderLoadingFn, RenderSuccessFn, RenderFieldWrapperFn, SubmitRenderProps, UseMaxFormOptions, UseMaxFormReturn, } from './types';
5
+ export { Form };
6
+ export { FileUpload, type FileUploadProps };
7
+ export { useMaxForm };
8
+ export { HeadingBlock, TextBlock, DividerBlock, RowBlock, } from './components/blocks';
9
+ export { buildFieldSchema, buildFormSchema, validateFormData, } from './lib/validation';
10
+ export interface RenderOptions {
11
+ formId: string;
12
+ /**
13
+ * API key for authenticating with the MaxForms API.
14
+ * Required for all embed requests.
15
+ */
16
+ apiKey: string;
17
+ baseUrl?: string;
18
+ onSubmit?: (data: Record<string, string>) => void;
19
+ onError?: (error: Error) => void;
20
+ }
21
+ /**
22
+ * Renders a MaxForms form into a DOM element
23
+ * @param selector CSS selector or DOM element
24
+ * @param options Form configuration options
25
+ */
26
+ export declare function render(selector: string | HTMLElement, options: RenderOptions): void;
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhD,OAAO,cAAc,CAAC;AAGtB,YAAY,EACV,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,EAClB,sBAAsB,EACtB,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,IAAI,EAAE,CAAC;AAChB,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,CAAC;AAG5C,OAAO,EAAE,UAAU,EAAE,CAAC;AAGtB,OAAO,EACL,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,QAAQ,GACT,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAG1B,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IAClD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CACpB,QAAQ,EAAE,MAAM,GAAG,WAAW,EAC9B,OAAO,EAAE,aAAa,GACrB,IAAI,CA0BN"}
@@ -0,0 +1,22 @@
1
+ import { z } from 'zod';
2
+ import { FormField } from '@maxischmaxi/maxforms-api-client';
3
+ /**
4
+ * Builds a Zod v4 schema for a single field based on its type and validation rules.
5
+ * Uses Zod v4's `error` parameter for custom error messages.
6
+ */
7
+ export declare function buildFieldSchema(field: FormField): z.ZodType;
8
+ /**
9
+ * Builds a complete Zod schema for all form fields.
10
+ * The schema uses field.name as keys (matching form data structure).
11
+ */
12
+ export declare function buildFormSchema(fields: FormField[]): z.ZodObject<Record<string, z.ZodType>>;
13
+ /**
14
+ * Validates form data against a schema and returns formatted errors.
15
+ * Uses Zod v4's safeParse.
16
+ */
17
+ export declare function validateFormData(schema: z.ZodType, data: Record<string, string>): {
18
+ success: boolean;
19
+ data?: Record<string, string>;
20
+ errors?: Record<string, string>;
21
+ };
22
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/lib/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,kCAAkC,CAAC;AAE7E;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,CAAC,CAAC,OAAO,CAiC5D;AA0TD;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,EAAE,GAClB,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAQxC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,CAAC,CAAC,OAAO,EACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC,CAiBA"}
@@ -0,0 +1 @@
1
+ :root{--maxforms-primary: #4f46e5;--maxforms-primary-hover: #4338ca;--maxforms-error: #dc2626;--maxforms-error-bg: #fef2f2;--maxforms-success: #16a34a;--maxforms-success-bg: #f0fdf4;--maxforms-text: #374151;--maxforms-text-muted: #6b7280;--maxforms-text-light: #9ca3af;--maxforms-bg: #ffffff;--maxforms-bg-muted: #f9fafb;--maxforms-bg-hover: #f3f4f6;--maxforms-border: #d1d5db;--maxforms-border-hover: #9ca3af;--maxforms-radius: .5rem;--maxforms-radius-sm: .25rem;--maxforms-font-size: .875rem;--maxforms-font-size-sm: .75rem;--maxforms-spacing: 1rem;--maxforms-spacing-sm: .5rem}.maxforms-form{display:flex;flex-direction:column;gap:var(--maxforms-spacing);width:100%;font-family:system-ui,-apple-system,sans-serif;font-size:var(--maxforms-font-size);color:var(--maxforms-text)}.maxforms-loading,.maxforms-error,.maxforms-success{padding:var(--maxforms-spacing);border-radius:var(--maxforms-radius);text-align:center}.maxforms-loading{background-color:var(--maxforms-bg-muted);color:var(--maxforms-text-muted)}.maxforms-error{background-color:var(--maxforms-error-bg);color:var(--maxforms-error);border:1px solid var(--maxforms-error)}.maxforms-success{background-color:var(--maxforms-success-bg);color:var(--maxforms-success);border:1px solid var(--maxforms-success)}.maxforms-form-error{padding:var(--maxforms-spacing-sm) var(--maxforms-spacing);background-color:var(--maxforms-error-bg);color:var(--maxforms-error);border:1px solid var(--maxforms-error);border-radius:var(--maxforms-radius);margin-bottom:var(--maxforms-spacing-sm)}.maxforms-form-error p{margin:0}.maxforms-field{display:flex;flex-direction:column;gap:var(--maxforms-spacing-sm)}.maxforms-field-has-error .maxforms-input{border-color:var(--maxforms-error)}.maxforms-label{font-size:var(--maxforms-font-size);font-weight:500;color:var(--maxforms-text)}.maxforms-required{color:var(--maxforms-error);margin-left:.25rem}.maxforms-field-error{font-size:var(--maxforms-font-size-sm);color:var(--maxforms-error)}.maxforms-input{width:100%;padding:.625rem .875rem;font-size:var(--maxforms-font-size);color:var(--maxforms-text);background-color:var(--maxforms-bg);border:1px solid var(--maxforms-border);border-radius:var(--maxforms-radius);transition:border-color .2s ease,box-shadow .2s ease;box-sizing:border-box}.maxforms-input::placeholder{color:var(--maxforms-text-light)}.maxforms-input:hover{border-color:var(--maxforms-border-hover)}.maxforms-input:focus{outline:none;border-color:var(--maxforms-primary);box-shadow:0 0 0 3px #4f46e51a}.maxforms-input:disabled{background-color:var(--maxforms-bg-muted);cursor:not-allowed;opacity:.7}.maxforms-input-error{border-color:var(--maxforms-error)}.maxforms-input-error:focus{border-color:var(--maxforms-error);box-shadow:0 0 0 3px #dc26261a}.maxforms-textarea{min-height:100px;resize:vertical}.maxforms-select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%236b7280' d='M2.5 4.5L6 8l3.5-3.5'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right .75rem center;padding-right:2.5rem}.maxforms-checkbox-group,.maxforms-radio-group{display:flex;flex-direction:column;gap:var(--maxforms-spacing-sm)}.maxforms-checkbox-label,.maxforms-radio-label{display:flex;align-items:center;gap:.5rem;font-size:var(--maxforms-font-size);color:var(--maxforms-text);cursor:pointer}.maxforms-checkbox,.maxforms-radio{width:1rem;height:1rem;margin:0;cursor:pointer;accent-color:var(--maxforms-primary)}.maxforms-checkbox:disabled,.maxforms-radio:disabled{cursor:not-allowed;opacity:.7}.maxforms-submit{padding:.75rem 1.5rem;font-size:var(--maxforms-font-size);font-weight:500;color:#fff;background-color:var(--maxforms-primary);border:none;border-radius:var(--maxforms-radius);cursor:pointer;transition:background-color .2s ease;align-self:flex-start}.maxforms-submit:hover:not(:disabled){background-color:var(--maxforms-primary-hover)}.maxforms-submit:focus{outline:none;box-shadow:0 0 0 3px #4f46e54d}.maxforms-submit:disabled{opacity:.7;cursor:not-allowed}.maxforms-heading{margin:0;font-weight:600;color:var(--maxforms-text);line-height:1.3}.maxforms-h1{font-size:1.875rem}.maxforms-h2{font-size:1.5rem}.maxforms-h3{font-size:1.25rem}.maxforms-text{font-size:var(--maxforms-font-size);color:var(--maxforms-text-muted);line-height:1.6;margin:0}.maxforms-text p{margin:0 0 .5rem}.maxforms-text p:last-child{margin-bottom:0}.maxforms-text a{color:var(--maxforms-primary);text-decoration:underline}.maxforms-text a:hover{color:var(--maxforms-primary-hover)}.maxforms-divider{border:none;border-top:1px solid var(--maxforms-border);margin:var(--maxforms-spacing-sm) 0}.maxforms-row{display:grid;gap:var(--maxforms-spacing)}.maxforms-row-2{grid-template-columns:repeat(2,1fr)}.maxforms-row-3{grid-template-columns:repeat(3,1fr)}.maxforms-row-4{grid-template-columns:repeat(4,1fr)}.maxforms-row-col{min-width:0}@media(max-width:640px){.maxforms-row-2,.maxforms-row-3,.maxforms-row-4{grid-template-columns:1fr}}.maxforms-file-upload{width:100%}.maxforms-file-input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.maxforms-file-dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:2rem;border:2px dashed var(--maxforms-border);border-radius:var(--maxforms-radius);background-color:var(--maxforms-bg-muted);cursor:pointer;transition:all .2s ease}.maxforms-file-dropzone:hover{border-color:var(--maxforms-border-hover);background-color:var(--maxforms-bg-hover)}.maxforms-file-dropzone:focus{outline:2px solid var(--maxforms-primary);outline-offset:2px}.maxforms-file-dropzone-active{border-color:var(--maxforms-primary);background-color:#4f46e50d}.maxforms-file-dropzone-uploading{cursor:default;pointer-events:none}.maxforms-file-upload-icon{color:var(--maxforms-text-light);margin-bottom:.5rem}.maxforms-file-dropzone-text{font-size:var(--maxforms-font-size);font-weight:500;color:var(--maxforms-text);margin:0}.maxforms-file-dropzone-hint{font-size:var(--maxforms-font-size-sm);color:var(--maxforms-text-muted);margin:.25rem 0 0}.maxforms-file-progress{width:100%;text-align:center}.maxforms-file-progress-bar{width:100%;height:.5rem;background-color:var(--maxforms-bg-hover);border-radius:9999px;overflow:hidden;margin-bottom:.5rem}.maxforms-file-progress-fill{height:100%;background-color:var(--maxforms-primary);transition:width .3s ease}.maxforms-file-progress-text{font-size:var(--maxforms-font-size-sm);color:var(--maxforms-text-muted)}.maxforms-file-uploaded{display:flex;align-items:center;justify-content:space-between;padding:.75rem 1rem;border:1px solid var(--maxforms-border);border-radius:var(--maxforms-radius);background-color:var(--maxforms-bg-muted)}.maxforms-file-info{display:flex;align-items:center;gap:.75rem;min-width:0}.maxforms-file-icon{flex-shrink:0;color:var(--maxforms-text-muted)}.maxforms-file-name{font-size:var(--maxforms-font-size);font-weight:500;color:var(--maxforms-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.maxforms-file-remove{flex-shrink:0;padding:.25rem;border:none;background:none;color:var(--maxforms-text-light);cursor:pointer;border-radius:var(--maxforms-radius-sm);transition:all .2s ease}.maxforms-file-remove:hover{color:var(--maxforms-error);background-color:var(--maxforms-error-bg)}.maxforms-file-error{font-size:var(--maxforms-font-size);color:var(--maxforms-error);margin-top:.5rem}