jdc-react-mailer 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,73 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ /**
4
+ * Field names supported by the contact form.
5
+ * Honeypot is always included for spam protection but not configurable in `fields`.
6
+ */
7
+ type FormFieldName = 'name' | 'email' | 'phone' | 'subject' | 'message';
8
+ /**
9
+ * Order and inclusion of visible fields.
10
+ */
11
+ type FormFieldsConfig = readonly FormFieldName[];
12
+ /**
13
+ * Submit state for the form.
14
+ */
15
+ type SubmitState = 'idle' | 'loading' | 'success' | 'error';
16
+ /**
17
+ * Theme overrides applied as CSS custom properties on the form root.
18
+ */
19
+ interface ThemeOverrides {
20
+ primary?: string;
21
+ primaryHover?: string;
22
+ bg?: string;
23
+ surface?: string;
24
+ border?: string;
25
+ text?: string;
26
+ muted?: string;
27
+ error?: string;
28
+ success?: string;
29
+ radius?: string;
30
+ spacing?: string;
31
+ fontFamily?: string;
32
+ }
33
+ /**
34
+ * Payload sent to the API endpoint (matches handler expectation).
35
+ */
36
+ interface ContactFormPayload {
37
+ name?: string;
38
+ email: string;
39
+ phone?: string;
40
+ subject?: string;
41
+ message: string;
42
+ /** Honeypot; must be empty for valid submission */
43
+ website?: string;
44
+ }
45
+ /**
46
+ * Props for the ContactForm component.
47
+ */
48
+ interface ContactFormProps {
49
+ /** POST endpoint URL (e.g. /api/contact). Required. */
50
+ endpoint: string;
51
+ /** Field order and inclusion. Default: ['name', 'email', 'subject', 'message'] */
52
+ fields?: FormFieldsConfig;
53
+ /** Override labels per field */
54
+ labels?: Partial<Record<FormFieldName, string>>;
55
+ /** Override placeholders per field */
56
+ placeholders?: Partial<Record<FormFieldName, string>>;
57
+ /** Inline theme overrides (CSS variables) */
58
+ theme?: ThemeOverrides;
59
+ /** Message shown after successful submit */
60
+ successMessage?: string;
61
+ /** Callback when submit succeeds */
62
+ onSuccess?: (data: ContactFormPayload) => void;
63
+ /** Callback when submit fails */
64
+ onError?: (error: Error) => void;
65
+ /** Optional class name for the form root */
66
+ className?: string;
67
+ /** Submit button label */
68
+ submitLabel?: string;
69
+ }
70
+
71
+ declare function ContactForm({ endpoint, fields, labels, placeholders, theme, successMessage, onSuccess, onError, className, submitLabel, }: ContactFormProps): react_jsx_runtime.JSX.Element;
72
+
73
+ export { ContactForm, type ContactFormPayload, type ContactFormProps, type FormFieldName, type FormFieldsConfig, type SubmitState, type ThemeOverrides };
@@ -0,0 +1,73 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ /**
4
+ * Field names supported by the contact form.
5
+ * Honeypot is always included for spam protection but not configurable in `fields`.
6
+ */
7
+ type FormFieldName = 'name' | 'email' | 'phone' | 'subject' | 'message';
8
+ /**
9
+ * Order and inclusion of visible fields.
10
+ */
11
+ type FormFieldsConfig = readonly FormFieldName[];
12
+ /**
13
+ * Submit state for the form.
14
+ */
15
+ type SubmitState = 'idle' | 'loading' | 'success' | 'error';
16
+ /**
17
+ * Theme overrides applied as CSS custom properties on the form root.
18
+ */
19
+ interface ThemeOverrides {
20
+ primary?: string;
21
+ primaryHover?: string;
22
+ bg?: string;
23
+ surface?: string;
24
+ border?: string;
25
+ text?: string;
26
+ muted?: string;
27
+ error?: string;
28
+ success?: string;
29
+ radius?: string;
30
+ spacing?: string;
31
+ fontFamily?: string;
32
+ }
33
+ /**
34
+ * Payload sent to the API endpoint (matches handler expectation).
35
+ */
36
+ interface ContactFormPayload {
37
+ name?: string;
38
+ email: string;
39
+ phone?: string;
40
+ subject?: string;
41
+ message: string;
42
+ /** Honeypot; must be empty for valid submission */
43
+ website?: string;
44
+ }
45
+ /**
46
+ * Props for the ContactForm component.
47
+ */
48
+ interface ContactFormProps {
49
+ /** POST endpoint URL (e.g. /api/contact). Required. */
50
+ endpoint: string;
51
+ /** Field order and inclusion. Default: ['name', 'email', 'subject', 'message'] */
52
+ fields?: FormFieldsConfig;
53
+ /** Override labels per field */
54
+ labels?: Partial<Record<FormFieldName, string>>;
55
+ /** Override placeholders per field */
56
+ placeholders?: Partial<Record<FormFieldName, string>>;
57
+ /** Inline theme overrides (CSS variables) */
58
+ theme?: ThemeOverrides;
59
+ /** Message shown after successful submit */
60
+ successMessage?: string;
61
+ /** Callback when submit succeeds */
62
+ onSuccess?: (data: ContactFormPayload) => void;
63
+ /** Callback when submit fails */
64
+ onError?: (error: Error) => void;
65
+ /** Optional class name for the form root */
66
+ className?: string;
67
+ /** Submit button label */
68
+ submitLabel?: string;
69
+ }
70
+
71
+ declare function ContactForm({ endpoint, fields, labels, placeholders, theme, successMessage, onSuccess, onError, className, submitLabel, }: ContactFormProps): react_jsx_runtime.JSX.Element;
72
+
73
+ export { ContactForm, type ContactFormPayload, type ContactFormProps, type FormFieldName, type FormFieldsConfig, type SubmitState, type ThemeOverrides };
package/dist/index.js ADDED
@@ -0,0 +1,341 @@
1
+ // src/hooks/useContactForm.ts
2
+ import { useState, useCallback } from "react";
3
+ var DEFAULT_FIELDS = ["name", "email", "subject", "message"];
4
+ var DEFAULT_LABELS = {
5
+ name: "Name",
6
+ email: "Email",
7
+ phone: "Phone (optional)",
8
+ subject: "Subject",
9
+ message: "Message"
10
+ };
11
+ var HONEPOT_NAME = "website";
12
+ function isValidEmail(value) {
13
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value.trim());
14
+ }
15
+ function isValidPhone(value) {
16
+ return /^[0-9()\-\s+.ext]+$/.test(value.trim());
17
+ }
18
+ function getFieldErrors(payload, fields) {
19
+ const errors = {};
20
+ if (fields.includes("name") && payload.name !== void 0) {
21
+ const v = String(payload.name).trim();
22
+ if (!v) errors.name = "Name is required";
23
+ }
24
+ if (fields.includes("email")) {
25
+ const v = String(payload.email ?? "").trim();
26
+ if (!v) errors.email = "Email is required";
27
+ else if (!isValidEmail(v)) errors.email = "Please enter a valid email address";
28
+ }
29
+ if (fields.includes("phone") && payload.phone) {
30
+ const v = String(payload.phone).trim();
31
+ if (v && !isValidPhone(v)) errors.phone = "Please enter a valid phone number";
32
+ }
33
+ if (fields.includes("subject") && payload.subject !== void 0) {
34
+ const v = String(payload.subject).trim();
35
+ if (!v) errors.subject = "Subject is required";
36
+ }
37
+ if (fields.includes("message")) {
38
+ const v = String(payload.message ?? "").trim();
39
+ if (!v) errors.message = "Message is required";
40
+ }
41
+ return errors;
42
+ }
43
+ function useContactForm({
44
+ endpoint,
45
+ fields = DEFAULT_FIELDS,
46
+ onSuccess,
47
+ onError
48
+ }) {
49
+ const [values, setValues] = useState({});
50
+ const [errors, setErrors] = useState({});
51
+ const [submitState, setSubmitState] = useState("idle");
52
+ const [errorMessage, setErrorMessage] = useState(null);
53
+ const setValue = useCallback(
54
+ (field, value) => {
55
+ setValues((prev) => ({ ...prev, [field]: value }));
56
+ if (errors[field]) {
57
+ setErrors((prev) => {
58
+ const next = { ...prev };
59
+ delete next[field];
60
+ return next;
61
+ });
62
+ }
63
+ },
64
+ [errors]
65
+ );
66
+ const validate = useCallback(() => {
67
+ const payload = {
68
+ email: values.email ?? "",
69
+ message: values.message ?? "",
70
+ name: values.name,
71
+ phone: values.phone,
72
+ subject: values.subject
73
+ };
74
+ const nextErrors = getFieldErrors(payload, fields);
75
+ setErrors(nextErrors);
76
+ return Object.keys(nextErrors).length === 0;
77
+ }, [values, fields]);
78
+ const reset = useCallback(() => {
79
+ setValues({});
80
+ setErrors({});
81
+ setSubmitState("idle");
82
+ setErrorMessage(null);
83
+ }, []);
84
+ const submit = useCallback(
85
+ async (e) => {
86
+ e.preventDefault();
87
+ const payload = {
88
+ email: (values.email ?? "").trim(),
89
+ message: (values.message ?? "").trim(),
90
+ name: fields.includes("name") ? (values.name ?? "").trim() : void 0,
91
+ phone: fields.includes("phone") ? (values.phone ?? "").trim() || void 0 : void 0,
92
+ subject: fields.includes("subject") ? (values.subject ?? "").trim() : void 0,
93
+ website: (values.website ?? "").trim()
94
+ };
95
+ if (!validate()) return;
96
+ if (payload.website) {
97
+ setValues({});
98
+ setErrors({});
99
+ setSubmitState("success");
100
+ setErrorMessage(null);
101
+ onSuccess?.(payload);
102
+ return;
103
+ }
104
+ setSubmitState("loading");
105
+ setErrorMessage(null);
106
+ try {
107
+ const res = await fetch(endpoint, {
108
+ method: "POST",
109
+ headers: { "Content-Type": "application/json" },
110
+ body: JSON.stringify(payload)
111
+ });
112
+ const data = await res.json().catch(() => ({}));
113
+ if (!res.ok) {
114
+ const msg = typeof data?.message === "string" ? data.message : res.statusText || "Something went wrong";
115
+ throw new Error(msg);
116
+ }
117
+ setValues({});
118
+ setErrors({});
119
+ setSubmitState("success");
120
+ setErrorMessage(null);
121
+ onSuccess?.(payload);
122
+ } catch (err) {
123
+ const error = err instanceof Error ? err : new Error("Submission failed");
124
+ setSubmitState("error");
125
+ setErrorMessage(error.message);
126
+ onError?.(error);
127
+ }
128
+ },
129
+ [endpoint, fields, values, validate, onSuccess, onError, reset]
130
+ );
131
+ return {
132
+ values,
133
+ errors,
134
+ submitState,
135
+ errorMessage,
136
+ setValue,
137
+ setErrorMessage,
138
+ validate,
139
+ submit,
140
+ reset
141
+ };
142
+ }
143
+
144
+ // src/components/ContactForm/ContactForm.tsx
145
+ import { jsx, jsxs } from "react/jsx-runtime";
146
+ var DEFAULT_FIELDS2 = ["name", "email", "subject", "message"];
147
+ var THEME_KEYS = {
148
+ primary: "--jdcm-primary",
149
+ primaryHover: "--jdcm-primary-hover",
150
+ bg: "--jdcm-bg",
151
+ surface: "--jdcm-surface",
152
+ border: "--jdcm-border",
153
+ text: "--jdcm-text",
154
+ muted: "--jdcm-muted",
155
+ error: "--jdcm-error",
156
+ success: "--jdcm-success",
157
+ radius: "--jdcm-radius",
158
+ spacing: "--jdcm-spacing",
159
+ fontFamily: "--jdcm-font"
160
+ };
161
+ function themeToStyle(theme) {
162
+ const style = {};
163
+ for (const [key, value] of Object.entries(theme)) {
164
+ const cssVar = THEME_KEYS[key];
165
+ if (cssVar && value != null) style[cssVar] = value;
166
+ }
167
+ return style;
168
+ }
169
+ function ContactForm({
170
+ endpoint,
171
+ fields = DEFAULT_FIELDS2,
172
+ labels = {},
173
+ placeholders = {},
174
+ theme,
175
+ successMessage = "Thanks! I'll be in touch.",
176
+ onSuccess,
177
+ onError,
178
+ className,
179
+ submitLabel = "Send message"
180
+ }) {
181
+ const {
182
+ values,
183
+ errors,
184
+ submitState,
185
+ errorMessage,
186
+ setValue,
187
+ setErrorMessage,
188
+ submit
189
+ } = useContactForm({ endpoint, fields, onSuccess, onError });
190
+ const rootClassName = ["jdcm-root", className].filter(Boolean).join(" ");
191
+ const rootStyle = theme ? themeToStyle(theme) : void 0;
192
+ return /* @__PURE__ */ jsxs(
193
+ "div",
194
+ {
195
+ className: rootClassName,
196
+ style: rootStyle,
197
+ ...theme ? { "data-theme-set": "true" } : {},
198
+ role: "region",
199
+ "aria-label": "Contact form",
200
+ children: [
201
+ submitState === "success" && /* @__PURE__ */ jsx("p", { className: "jdcm-success-msg", role: "status", children: successMessage }),
202
+ submitState === "error" && errorMessage && /* @__PURE__ */ jsxs("div", { className: "jdcm-error-banner", role: "alert", children: [
203
+ /* @__PURE__ */ jsx("span", { children: errorMessage }),
204
+ /* @__PURE__ */ jsx(
205
+ "button",
206
+ {
207
+ type: "button",
208
+ onClick: () => setErrorMessage(null),
209
+ "aria-label": "Dismiss error",
210
+ children: "Dismiss"
211
+ }
212
+ )
213
+ ] }),
214
+ submitState !== "success" && /* @__PURE__ */ jsxs("form", { className: "jdcm-form", onSubmit: submit, noValidate: true, children: [
215
+ /* @__PURE__ */ jsxs("div", { className: "jdcm-field jdcm-hp", "aria-hidden": "true", children: [
216
+ /* @__PURE__ */ jsx("label", { htmlFor: "jdcm-website", children: "Website" }),
217
+ /* @__PURE__ */ jsx(
218
+ "input",
219
+ {
220
+ id: "jdcm-website",
221
+ type: "text",
222
+ name: HONEPOT_NAME,
223
+ tabIndex: -1,
224
+ autoComplete: "off",
225
+ value: values.website ?? "",
226
+ onChange: (e) => setValue(HONEPOT_NAME, e.target.value)
227
+ }
228
+ )
229
+ ] }),
230
+ fields.includes("name") && /* @__PURE__ */ jsxs("div", { className: "jdcm-field", children: [
231
+ /* @__PURE__ */ jsx("label", { htmlFor: "jdcm-name", children: labels.name ?? DEFAULT_LABELS.name }),
232
+ /* @__PURE__ */ jsx(
233
+ "input",
234
+ {
235
+ id: "jdcm-name",
236
+ type: "text",
237
+ name: "name",
238
+ autoComplete: "name",
239
+ placeholder: placeholders.name,
240
+ value: values.name ?? "",
241
+ onChange: (e) => setValue("name", e.target.value),
242
+ "aria-invalid": Boolean(errors.name),
243
+ "aria-describedby": errors.name ? "jdcm-name-err" : void 0
244
+ }
245
+ ),
246
+ errors.name && /* @__PURE__ */ jsx("span", { id: "jdcm-name-err", className: "jdcm-error-msg", children: errors.name })
247
+ ] }),
248
+ fields.includes("email") && /* @__PURE__ */ jsxs("div", { className: "jdcm-field", children: [
249
+ /* @__PURE__ */ jsx("label", { htmlFor: "jdcm-email", children: labels.email ?? DEFAULT_LABELS.email }),
250
+ /* @__PURE__ */ jsx(
251
+ "input",
252
+ {
253
+ id: "jdcm-email",
254
+ type: "email",
255
+ name: "email",
256
+ required: true,
257
+ autoComplete: "email",
258
+ placeholder: placeholders.email,
259
+ value: values.email ?? "",
260
+ onChange: (e) => setValue("email", e.target.value),
261
+ "aria-invalid": Boolean(errors.email),
262
+ "aria-describedby": errors.email ? "jdcm-email-err" : void 0
263
+ }
264
+ ),
265
+ errors.email && /* @__PURE__ */ jsx("span", { id: "jdcm-email-err", className: "jdcm-error-msg", children: errors.email })
266
+ ] }),
267
+ fields.includes("phone") && /* @__PURE__ */ jsxs("div", { className: "jdcm-field", children: [
268
+ /* @__PURE__ */ jsx("label", { htmlFor: "jdcm-phone", children: labels.phone ?? DEFAULT_LABELS.phone }),
269
+ /* @__PURE__ */ jsx(
270
+ "input",
271
+ {
272
+ id: "jdcm-phone",
273
+ type: "tel",
274
+ name: "phone",
275
+ autoComplete: "tel",
276
+ placeholder: placeholders.phone,
277
+ value: values.phone ?? "",
278
+ onChange: (e) => setValue("phone", e.target.value),
279
+ "aria-invalid": Boolean(errors.phone),
280
+ "aria-describedby": errors.phone ? "jdcm-phone-err" : void 0
281
+ }
282
+ ),
283
+ errors.phone && /* @__PURE__ */ jsx("span", { id: "jdcm-phone-err", className: "jdcm-error-msg", children: errors.phone })
284
+ ] }),
285
+ fields.includes("subject") && /* @__PURE__ */ jsxs("div", { className: "jdcm-field", children: [
286
+ /* @__PURE__ */ jsx("label", { htmlFor: "jdcm-subject", children: labels.subject ?? DEFAULT_LABELS.subject }),
287
+ /* @__PURE__ */ jsx(
288
+ "input",
289
+ {
290
+ id: "jdcm-subject",
291
+ type: "text",
292
+ name: "subject",
293
+ autoComplete: "off",
294
+ placeholder: placeholders.subject,
295
+ value: values.subject ?? "",
296
+ onChange: (e) => setValue("subject", e.target.value),
297
+ "aria-invalid": Boolean(errors.subject),
298
+ "aria-describedby": errors.subject ? "jdcm-subject-err" : void 0
299
+ }
300
+ ),
301
+ errors.subject && /* @__PURE__ */ jsx("span", { id: "jdcm-subject-err", className: "jdcm-error-msg", children: errors.subject })
302
+ ] }),
303
+ fields.includes("message") && /* @__PURE__ */ jsxs("div", { className: "jdcm-field", children: [
304
+ /* @__PURE__ */ jsx("label", { htmlFor: "jdcm-message", children: labels.message ?? DEFAULT_LABELS.message }),
305
+ /* @__PURE__ */ jsx(
306
+ "textarea",
307
+ {
308
+ id: "jdcm-message",
309
+ name: "message",
310
+ required: true,
311
+ placeholder: placeholders.message,
312
+ value: values.message ?? "",
313
+ onChange: (e) => setValue("message", e.target.value),
314
+ "aria-invalid": Boolean(errors.message),
315
+ "aria-describedby": errors.message ? "jdcm-message-err" : void 0
316
+ }
317
+ ),
318
+ errors.message && /* @__PURE__ */ jsx("span", { id: "jdcm-message-err", className: "jdcm-error-msg", children: errors.message })
319
+ ] }),
320
+ /* @__PURE__ */ jsxs(
321
+ "button",
322
+ {
323
+ type: "submit",
324
+ className: "jdcm-submit",
325
+ disabled: submitState === "loading",
326
+ "aria-busy": submitState === "loading",
327
+ children: [
328
+ submitState === "loading" && /* @__PURE__ */ jsx("span", { className: "jdcm-spinner", "aria-hidden": "true" }),
329
+ submitState === "loading" ? "Sending\u2026" : submitLabel
330
+ ]
331
+ }
332
+ )
333
+ ] })
334
+ ]
335
+ }
336
+ );
337
+ }
338
+ export {
339
+ ContactForm
340
+ };
341
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/useContactForm.ts","../src/components/ContactForm/ContactForm.tsx"],"sourcesContent":["import { useState, useCallback } from 'react';\nimport type {\n FormFieldName,\n FormFieldsConfig,\n ContactFormPayload,\n SubmitState,\n} from '../components/ContactForm/types';\n\nconst DEFAULT_FIELDS: FormFieldsConfig = ['name', 'email', 'subject', 'message'];\n\nconst DEFAULT_LABELS: Record<FormFieldName, string> = {\n name: 'Name',\n email: 'Email',\n phone: 'Phone (optional)',\n subject: 'Subject',\n message: 'Message',\n};\n\nconst HONEPOT_NAME = 'website';\n\nfunction isValidEmail(value: string): boolean {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value.trim());\n}\n\nfunction isValidPhone(value: string): boolean {\n return /^[0-9()\\-\\s+.ext]+$/.test(value.trim());\n}\n\nfunction getFieldErrors(\n payload: Partial<ContactFormPayload>,\n fields: FormFieldsConfig\n): Partial<Record<FormFieldName, string>> {\n const errors: Partial<Record<FormFieldName, string>> = {};\n\n if (fields.includes('name') && payload.name !== undefined) {\n const v = String(payload.name).trim();\n if (!v) errors.name = 'Name is required';\n }\n\n if (fields.includes('email')) {\n const v = String(payload.email ?? '').trim();\n if (!v) errors.email = 'Email is required';\n else if (!isValidEmail(v)) errors.email = 'Please enter a valid email address';\n }\n\n if (fields.includes('phone') && payload.phone) {\n const v = String(payload.phone).trim();\n if (v && !isValidPhone(v)) errors.phone = 'Please enter a valid phone number';\n }\n\n if (fields.includes('subject') && payload.subject !== undefined) {\n const v = String(payload.subject).trim();\n if (!v) errors.subject = 'Subject is required';\n }\n\n if (fields.includes('message')) {\n const v = String(payload.message ?? '').trim();\n if (!v) errors.message = 'Message is required';\n }\n\n return errors;\n}\n\nexport interface UseContactFormOptions {\n endpoint: string;\n fields?: FormFieldsConfig;\n onSuccess?: (data: ContactFormPayload) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UseContactFormReturn {\n values: Partial<ContactFormPayload>;\n errors: Partial<Record<FormFieldName, string>>;\n submitState: SubmitState;\n errorMessage: string | null;\n setValue: (field: FormFieldName | typeof HONEPOT_NAME, value: string) => void;\n setErrorMessage: (msg: string | null) => void;\n validate: () => boolean;\n submit: (e: React.FormEvent) => Promise<void>;\n reset: () => void;\n}\n\nexport function useContactForm({\n endpoint,\n fields = DEFAULT_FIELDS,\n onSuccess,\n onError,\n}: UseContactFormOptions): UseContactFormReturn {\n const [values, setValues] = useState<Partial<ContactFormPayload>>({});\n const [errors, setErrors] = useState<Partial<Record<FormFieldName, string>>>({});\n const [submitState, setSubmitState] = useState<SubmitState>('idle');\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n\n const setValue = useCallback(\n (field: FormFieldName | typeof HONEPOT_NAME, value: string) => {\n setValues((prev) => ({ ...prev, [field]: value }));\n if (errors[field as FormFieldName]) {\n setErrors((prev) => {\n const next = { ...prev };\n delete next[field as FormFieldName];\n return next;\n });\n }\n },\n [errors]\n );\n\n const validate = useCallback((): boolean => {\n const payload: Partial<ContactFormPayload> = {\n email: values.email ?? '',\n message: values.message ?? '',\n name: values.name,\n phone: values.phone,\n subject: values.subject,\n };\n const nextErrors = getFieldErrors(payload, fields);\n setErrors(nextErrors);\n return Object.keys(nextErrors).length === 0;\n }, [values, fields]);\n\n const reset = useCallback(() => {\n setValues({});\n setErrors({});\n setSubmitState('idle');\n setErrorMessage(null);\n }, []);\n\n const submit = useCallback(\n async (e: React.FormEvent) => {\n e.preventDefault();\n\n const payload: Partial<ContactFormPayload> = {\n email: (values.email ?? '').trim(),\n message: (values.message ?? '').trim(),\n name: fields.includes('name') ? (values.name ?? '').trim() : undefined,\n phone: fields.includes('phone') ? (values.phone ?? '').trim() || undefined : undefined,\n subject: fields.includes('subject') ? (values.subject ?? '').trim() : undefined,\n website: (values.website ?? '').trim(),\n };\n\n if (!validate()) return;\n\n if (payload.website) {\n setValues({});\n setErrors({});\n setSubmitState('success');\n setErrorMessage(null);\n onSuccess?.(payload as ContactFormPayload);\n return;\n }\n\n setSubmitState('loading');\n setErrorMessage(null);\n\n try {\n const res = await fetch(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n });\n\n const data = await res.json().catch(() => ({}));\n\n if (!res.ok) {\n const msg =\n typeof data?.message === 'string'\n ? data.message\n : res.statusText || 'Something went wrong';\n throw new Error(msg);\n }\n\n setValues({});\n setErrors({});\n setSubmitState('success');\n setErrorMessage(null);\n onSuccess?.(payload as ContactFormPayload);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Submission failed');\n setSubmitState('error');\n setErrorMessage(error.message);\n onError?.(error);\n }\n },\n [endpoint, fields, values, validate, onSuccess, onError, reset]\n );\n return {\n values,\n errors,\n submitState,\n errorMessage,\n setValue,\n setErrorMessage,\n validate,\n submit,\n reset,\n };\n}\n\nexport { DEFAULT_LABELS, HONEPOT_NAME };\n","import React from 'react';\nimport { useContactForm, DEFAULT_LABELS, HONEPOT_NAME } from '../../hooks/useContactForm';\nimport type { ContactFormProps, FormFieldName, ThemeOverrides } from './types';\n/* Consumer imports: import 'jdc-react-mailer/style.css' */\n\nconst DEFAULT_FIELDS: FormFieldName[] = ['name', 'email', 'subject', 'message'];\n\nconst THEME_KEYS: Record<keyof ThemeOverrides, string> = {\n primary: '--jdcm-primary',\n primaryHover: '--jdcm-primary-hover',\n bg: '--jdcm-bg',\n surface: '--jdcm-surface',\n border: '--jdcm-border',\n text: '--jdcm-text',\n muted: '--jdcm-muted',\n error: '--jdcm-error',\n success: '--jdcm-success',\n radius: '--jdcm-radius',\n spacing: '--jdcm-spacing',\n fontFamily: '--jdcm-font',\n};\n\nfunction themeToStyle(theme: ThemeOverrides): React.CSSProperties {\n const style: React.CSSProperties = {};\n for (const [key, value] of Object.entries(theme)) {\n const cssVar = THEME_KEYS[key as keyof ThemeOverrides];\n if (cssVar && value != null) style[cssVar as keyof React.CSSProperties] = value;\n }\n return style;\n}\n\nexport function ContactForm({\n endpoint,\n fields = DEFAULT_FIELDS,\n labels = {},\n placeholders = {},\n theme,\n successMessage = \"Thanks! I'll be in touch.\",\n onSuccess,\n onError,\n className,\n submitLabel = 'Send message',\n}: ContactFormProps) {\n const {\n values,\n errors,\n submitState,\n errorMessage,\n setValue,\n setErrorMessage,\n submit,\n } = useContactForm({ endpoint, fields, onSuccess, onError });\n\n const rootClassName = ['jdcm-root', className].filter(Boolean).join(' ');\n const rootStyle = theme ? themeToStyle(theme) : undefined;\n\n return (\n <div\n className={rootClassName}\n style={rootStyle}\n {...(theme ? { 'data-theme-set': 'true' } : {})}\n role=\"region\"\n aria-label=\"Contact form\"\n >\n {submitState === 'success' && (\n <p className=\"jdcm-success-msg\" role=\"status\">\n {successMessage}\n </p>\n )}\n\n {submitState === 'error' && errorMessage && (\n <div className=\"jdcm-error-banner\" role=\"alert\">\n <span>{errorMessage}</span>\n <button\n type=\"button\"\n onClick={() => setErrorMessage(null)}\n aria-label=\"Dismiss error\"\n >\n Dismiss\n </button>\n </div>\n )}\n\n {submitState !== 'success' && (\n <form className=\"jdcm-form\" onSubmit={submit} noValidate>\n {/* Honeypot */}\n <div className=\"jdcm-field jdcm-hp\" aria-hidden=\"true\">\n <label htmlFor=\"jdcm-website\">Website</label>\n <input\n id=\"jdcm-website\"\n type=\"text\"\n name={HONEPOT_NAME}\n tabIndex={-1}\n autoComplete=\"off\"\n value={values.website ?? ''}\n onChange={(e) => setValue(HONEPOT_NAME, e.target.value)}\n />\n </div>\n\n {fields.includes('name') && (\n <div className=\"jdcm-field\">\n <label htmlFor=\"jdcm-name\">\n {labels.name ?? DEFAULT_LABELS.name}\n </label>\n <input\n id=\"jdcm-name\"\n type=\"text\"\n name=\"name\"\n autoComplete=\"name\"\n placeholder={placeholders.name}\n value={values.name ?? ''}\n onChange={(e) => setValue('name', e.target.value)}\n aria-invalid={Boolean(errors.name)}\n aria-describedby={errors.name ? 'jdcm-name-err' : undefined}\n />\n {errors.name && (\n <span id=\"jdcm-name-err\" className=\"jdcm-error-msg\">\n {errors.name}\n </span>\n )}\n </div>\n )}\n\n {fields.includes('email') && (\n <div className=\"jdcm-field\">\n <label htmlFor=\"jdcm-email\">\n {labels.email ?? DEFAULT_LABELS.email}\n </label>\n <input\n id=\"jdcm-email\"\n type=\"email\"\n name=\"email\"\n required\n autoComplete=\"email\"\n placeholder={placeholders.email}\n value={values.email ?? ''}\n onChange={(e) => setValue('email', e.target.value)}\n aria-invalid={Boolean(errors.email)}\n aria-describedby={errors.email ? 'jdcm-email-err' : undefined}\n />\n {errors.email && (\n <span id=\"jdcm-email-err\" className=\"jdcm-error-msg\">\n {errors.email}\n </span>\n )}\n </div>\n )}\n\n {fields.includes('phone') && (\n <div className=\"jdcm-field\">\n <label htmlFor=\"jdcm-phone\">\n {labels.phone ?? DEFAULT_LABELS.phone}\n </label>\n <input\n id=\"jdcm-phone\"\n type=\"tel\"\n name=\"phone\"\n autoComplete=\"tel\"\n placeholder={placeholders.phone}\n value={values.phone ?? ''}\n onChange={(e) => setValue('phone', e.target.value)}\n aria-invalid={Boolean(errors.phone)}\n aria-describedby={errors.phone ? 'jdcm-phone-err' : undefined}\n />\n {errors.phone && (\n <span id=\"jdcm-phone-err\" className=\"jdcm-error-msg\">\n {errors.phone}\n </span>\n )}\n </div>\n )}\n\n {fields.includes('subject') && (\n <div className=\"jdcm-field\">\n <label htmlFor=\"jdcm-subject\">\n {labels.subject ?? DEFAULT_LABELS.subject}\n </label>\n <input\n id=\"jdcm-subject\"\n type=\"text\"\n name=\"subject\"\n autoComplete=\"off\"\n placeholder={placeholders.subject}\n value={values.subject ?? ''}\n onChange={(e) => setValue('subject', e.target.value)}\n aria-invalid={Boolean(errors.subject)}\n aria-describedby={errors.subject ? 'jdcm-subject-err' : undefined}\n />\n {errors.subject && (\n <span id=\"jdcm-subject-err\" className=\"jdcm-error-msg\">\n {errors.subject}\n </span>\n )}\n </div>\n )}\n\n {fields.includes('message') && (\n <div className=\"jdcm-field\">\n <label htmlFor=\"jdcm-message\">\n {labels.message ?? DEFAULT_LABELS.message}\n </label>\n <textarea\n id=\"jdcm-message\"\n name=\"message\"\n required\n placeholder={placeholders.message}\n value={values.message ?? ''}\n onChange={(e) => setValue('message', e.target.value)}\n aria-invalid={Boolean(errors.message)}\n aria-describedby={errors.message ? 'jdcm-message-err' : undefined}\n />\n {errors.message && (\n <span id=\"jdcm-message-err\" className=\"jdcm-error-msg\">\n {errors.message}\n </span>\n )}\n </div>\n )}\n\n <button\n type=\"submit\"\n className=\"jdcm-submit\"\n disabled={submitState === 'loading'}\n aria-busy={submitState === 'loading'}\n >\n {submitState === 'loading' && (\n <span className=\"jdcm-spinner\" aria-hidden=\"true\" />\n )}\n {submitState === 'loading' ? 'Sending…' : submitLabel}\n </button>\n </form>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["DEFAULT_FIELDS"]}