@marvalt/madapter 2.1.1 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2346,13 +2346,93 @@ const useMauticRemoveFromSegment = () => {
2346
2346
  });
2347
2347
  };
2348
2348
 
2349
+ const TurnstileWidget = ({ siteKey, onSuccess, onError, onExpire, theme = 'auto', size = 'normal', tabIndex, }) => {
2350
+ const widgetRef = React.useRef(null);
2351
+ const widgetId = React.useRef(null);
2352
+ const scriptLoaded = React.useRef(false);
2353
+ React.useEffect(() => {
2354
+ if (!widgetRef.current || !siteKey)
2355
+ return;
2356
+ const loadTurnstile = () => {
2357
+ if (window.turnstile && widgetRef.current && !widgetId.current) {
2358
+ try {
2359
+ widgetId.current = window.turnstile.render(widgetRef.current, {
2360
+ sitekey: siteKey,
2361
+ callback: onSuccess,
2362
+ 'error-callback': onError,
2363
+ 'expired-callback': onExpire,
2364
+ theme,
2365
+ size,
2366
+ tabindex: tabIndex,
2367
+ });
2368
+ }
2369
+ catch (error) {
2370
+ console.error('Failed to render Turnstile widget:', error);
2371
+ onError?.();
2372
+ }
2373
+ }
2374
+ };
2375
+ // Check if Turnstile is already loaded
2376
+ if (window.turnstile) {
2377
+ loadTurnstile();
2378
+ }
2379
+ else if (!scriptLoaded.current) {
2380
+ // Load Turnstile script
2381
+ scriptLoaded.current = true;
2382
+ const script = document.createElement('script');
2383
+ script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js';
2384
+ script.async = true;
2385
+ script.defer = true;
2386
+ script.onload = loadTurnstile;
2387
+ script.onerror = () => {
2388
+ console.error('Failed to load Turnstile script');
2389
+ onError?.();
2390
+ };
2391
+ document.head.appendChild(script);
2392
+ }
2393
+ return () => {
2394
+ if (widgetId.current && window.turnstile) {
2395
+ try {
2396
+ window.turnstile.remove(widgetId.current);
2397
+ }
2398
+ catch (error) {
2399
+ console.error('Failed to remove Turnstile widget:', error);
2400
+ }
2401
+ widgetId.current = null;
2402
+ }
2403
+ };
2404
+ }, [siteKey, onSuccess, onError, onExpire, theme, size, tabIndex]);
2405
+ return jsxRuntimeExports.jsx("div", { ref: widgetRef, className: "cf-turnstile" });
2406
+ };
2407
+
2349
2408
  const MauticForm = ({ formId, title, description, className = '', form, onSubmit, onSuccess, onError, }) => {
2350
2409
  const [formData, setFormData] = React.useState({});
2351
2410
  const [errors, setErrors] = React.useState({});
2352
2411
  const [isSubmitting, setIsSubmitting] = React.useState(false);
2353
2412
  const [isSubmitted, setIsSubmitted] = React.useState(false);
2354
2413
  const [showSuccessMessage, setShowSuccessMessage] = React.useState(false);
2414
+ const [turnstileToken, setTurnstileToken] = React.useState(null);
2355
2415
  const submitMutation = useMauticFormSubmission();
2416
+ // Get Turnstile site key from environment
2417
+ const getTurnstilesiteKey = () => {
2418
+ // Check for Vite environment (browser)
2419
+ if (typeof window !== 'undefined' && window.import?.meta?.env) {
2420
+ return window.import.meta.env.VITE_TURNSTILE_SITE_KEY;
2421
+ }
2422
+ // Check for direct import.meta (Vite)
2423
+ try {
2424
+ // @ts-ignore - import.meta is a Vite-specific global
2425
+ if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }) !== 'undefined' && undefined) {
2426
+ // @ts-ignore
2427
+ return undefined.VITE_TURNSTILE_SITE_KEY;
2428
+ }
2429
+ }
2430
+ catch (e) {
2431
+ // import.meta not available
2432
+ }
2433
+ return undefined;
2434
+ };
2435
+ const turnstilesiteKey = getTurnstilesiteKey();
2356
2436
  React.useEffect(() => {
2357
2437
  if (!form) {
2358
2438
  console.warn(`Form ${formId} not found`);
@@ -2411,6 +2491,11 @@ const MauticForm = ({ formId, title, description, className = '', form, onSubmit
2411
2491
  if (!validateForm()) {
2412
2492
  return;
2413
2493
  }
2494
+ // Check Turnstile token if enabled
2495
+ if (turnstilesiteKey && !turnstileToken) {
2496
+ setErrors(prev => ({ ...prev, _turnstile: 'Please complete the verification' }));
2497
+ return;
2498
+ }
2414
2499
  setIsSubmitting(true);
2415
2500
  setErrors({});
2416
2501
  try {
@@ -2426,7 +2511,12 @@ const MauticForm = ({ formId, title, description, className = '', form, onSubmit
2426
2511
  formId: parseInt(formId),
2427
2512
  fields: formData,
2428
2513
  returnUrl: window.location.href,
2429
- ...(derivedFormName ? { formName: derivedFormName } : {})
2514
+ ...(derivedFormName ? { formName: derivedFormName } : {}),
2515
+ ...(turnstileToken ? {
2516
+ headers: {
2517
+ 'cf-turnstile-response': turnstileToken
2518
+ }
2519
+ } : {})
2430
2520
  };
2431
2521
  // Call custom onSubmit if provided
2432
2522
  if (onSubmit) {
@@ -2515,7 +2605,23 @@ const MauticForm = ({ formId, title, description, className = '', form, onSubmit
2515
2605
  return (jsxRuntimeExports.jsxs("form", { className: `mautic-form ${className}`, onSubmit: handleSubmit, children: [(title || form.name) && (jsxRuntimeExports.jsxs("div", { className: "form-header", children: [jsxRuntimeExports.jsx("h3", { children: title || form.name }), (description || form.description) && (jsxRuntimeExports.jsx("p", { className: "form-description", children: description || form.description }))] })), jsxRuntimeExports.jsx("div", { className: "form-fields", children: form.fields
2516
2606
  // Filter out button/submit from field group; render them in actions
2517
2607
  .filter((field) => field.type !== 'button' && field.alias !== 'submit')
2518
- .map((field) => (jsxRuntimeExports.jsxs("div", { className: `form-field form-field-${field.type}`, children: [field.showLabel !== false && (jsxRuntimeExports.jsxs("label", { htmlFor: field.alias, className: "field-label", children: [field.label, field.isRequired && jsxRuntimeExports.jsx("span", { className: "required", children: "*" })] })), renderField(field), field.properties?.helpText && (jsxRuntimeExports.jsx("p", { className: "field-help", children: field.properties.helpText })), errors[field.alias] && (jsxRuntimeExports.jsx("p", { className: "field-error", children: errors[field.alias] }))] }, field.id))) }), jsxRuntimeExports.jsx("div", { className: "form-actions", children: jsxRuntimeExports.jsx("button", { type: "submit", disabled: isSubmitting, className: "submit-button", children: isSubmitting ? 'Submitting...' : 'Submit' }) }), submitMutation.error && (jsxRuntimeExports.jsx("div", { className: "form-error", children: jsxRuntimeExports.jsx("p", { children: "There was an error submitting the form. Please try again." }) }))] }));
2608
+ .map((field) => (jsxRuntimeExports.jsxs("div", { className: `form-field form-field-${field.type}`, children: [field.showLabel !== false && (jsxRuntimeExports.jsxs("label", { htmlFor: field.alias, className: "field-label", children: [field.label, field.isRequired && jsxRuntimeExports.jsx("span", { className: "required", children: "*" })] })), renderField(field), field.properties?.helpText && (jsxRuntimeExports.jsx("p", { className: "field-help", children: field.properties.helpText })), errors[field.alias] && (jsxRuntimeExports.jsx("p", { className: "field-error", children: errors[field.alias] }))] }, field.id))) }), turnstilesiteKey && (jsxRuntimeExports.jsxs("div", { className: "form-turnstile", children: [jsxRuntimeExports.jsx(TurnstileWidget, { siteKey: turnstilesiteKey, onSuccess: (token) => {
2609
+ setTurnstileToken(token);
2610
+ // Clear any turnstile error
2611
+ if (errors._turnstile) {
2612
+ setErrors(prev => {
2613
+ const next = { ...prev };
2614
+ delete next._turnstile;
2615
+ return next;
2616
+ });
2617
+ }
2618
+ }, onError: () => {
2619
+ setTurnstileToken(null);
2620
+ setErrors(prev => ({ ...prev, _turnstile: 'Verification failed. Please try again.' }));
2621
+ }, onExpire: () => {
2622
+ setTurnstileToken(null);
2623
+ setErrors(prev => ({ ...prev, _turnstile: 'Verification expired. Please verify again.' }));
2624
+ }, theme: "auto", size: "normal" }), errors._turnstile && (jsxRuntimeExports.jsx("p", { className: "field-error turnstile-error", children: errors._turnstile }))] })), jsxRuntimeExports.jsx("div", { className: "form-actions", children: jsxRuntimeExports.jsx("button", { type: "submit", disabled: isSubmitting || (!!turnstilesiteKey && !turnstileToken), className: "submit-button", children: isSubmitting ? 'Submitting...' : 'Submit' }) }), submitMutation.error && (jsxRuntimeExports.jsx("div", { className: "form-error", children: jsxRuntimeExports.jsx("p", { children: "There was an error submitting the form. Please try again." }) }))] }));
2519
2625
  };
2520
2626
 
2521
2627
  const MauticTracking = ({ enabled, mauticUrl, proxyUrl, children }) => {
@@ -2658,65 +2764,6 @@ const useMauticEvent = () => {
2658
2764
  };
2659
2765
  };
2660
2766
 
2661
- const TurnstileWidget = ({ siteKey, onSuccess, onError, onExpire, theme = 'auto', size = 'normal', tabIndex, }) => {
2662
- const widgetRef = React.useRef(null);
2663
- const widgetId = React.useRef(null);
2664
- const scriptLoaded = React.useRef(false);
2665
- React.useEffect(() => {
2666
- if (!widgetRef.current || !siteKey)
2667
- return;
2668
- const loadTurnstile = () => {
2669
- if (window.turnstile && widgetRef.current && !widgetId.current) {
2670
- try {
2671
- widgetId.current = window.turnstile.render(widgetRef.current, {
2672
- sitekey: siteKey,
2673
- callback: onSuccess,
2674
- 'error-callback': onError,
2675
- 'expired-callback': onExpire,
2676
- theme,
2677
- size,
2678
- tabindex: tabIndex,
2679
- });
2680
- }
2681
- catch (error) {
2682
- console.error('Failed to render Turnstile widget:', error);
2683
- onError?.();
2684
- }
2685
- }
2686
- };
2687
- // Check if Turnstile is already loaded
2688
- if (window.turnstile) {
2689
- loadTurnstile();
2690
- }
2691
- else if (!scriptLoaded.current) {
2692
- // Load Turnstile script
2693
- scriptLoaded.current = true;
2694
- const script = document.createElement('script');
2695
- script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js';
2696
- script.async = true;
2697
- script.defer = true;
2698
- script.onload = loadTurnstile;
2699
- script.onerror = () => {
2700
- console.error('Failed to load Turnstile script');
2701
- onError?.();
2702
- };
2703
- document.head.appendChild(script);
2704
- }
2705
- return () => {
2706
- if (widgetId.current && window.turnstile) {
2707
- try {
2708
- window.turnstile.remove(widgetId.current);
2709
- }
2710
- catch (error) {
2711
- console.error('Failed to remove Turnstile widget:', error);
2712
- }
2713
- widgetId.current = null;
2714
- }
2715
- };
2716
- }, [siteKey, onSuccess, onError, onExpire, theme, size, tabIndex]);
2717
- return jsxRuntimeExports.jsx("div", { ref: widgetRef, className: "cf-turnstile" });
2718
- };
2719
-
2720
2767
  const MauticContext = React.createContext(null);
2721
2768
  const MauticProvider = ({ config, children }) => {
2722
2769
  const client = React.useMemo(() => {