@marvalt/digivalt-core 0.2.29 → 0.2.32

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.
Files changed (59) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/GLOBAL-SHORTCODES.md +99 -0
  3. package/README.md +11 -9
  4. package/bin/env-example-fragments.cjs +6 -0
  5. package/bin/init.cjs +44 -5
  6. package/dist/generators/index.d.ts +3 -0
  7. package/dist/generators/prerender-seo.d.ts +6 -0
  8. package/dist/generators/seo-manifest.d.ts +3 -0
  9. package/dist/generators/seo-urls.d.ts +29 -0
  10. package/dist/generators/sitemap-paths.d.ts +5 -9
  11. package/dist/generators.cjs +1005 -155
  12. package/dist/generators.cjs.map +1 -1
  13. package/dist/generators.d.ts +86 -6
  14. package/dist/generators.esm.js +992 -156
  15. package/dist/generators.esm.js.map +1 -1
  16. package/dist/index.cjs +1019 -156
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.ts +103 -9
  19. package/dist/index.esm.js +1006 -157
  20. package/dist/index.esm.js.map +1 -1
  21. package/dist/registry/index.d.ts +20 -0
  22. package/dist/registry.cjs +1528 -0
  23. package/dist/registry.cjs.map +1 -0
  24. package/dist/registry.d.ts +26 -0
  25. package/dist/registry.esm.js +1523 -0
  26. package/dist/registry.esm.js.map +1 -0
  27. package/dist/seo/DigiValtRouteSeo.d.ts +12 -0
  28. package/dist/seo/DigiValtSeoHead.d.ts +2 -0
  29. package/dist/seo/buildPageJsonLd.d.ts +11 -0
  30. package/dist/seo/html.d.ts +8 -0
  31. package/dist/seo/index.d.ts +7 -0
  32. package/dist/seo/resolvePageSeo.d.ts +17 -0
  33. package/dist/seo/seoTypes.d.ts +57 -0
  34. package/dist/seo.cjs +307 -86
  35. package/dist/seo.cjs.map +1 -1
  36. package/dist/seo.d.ts +105 -2
  37. package/dist/seo.esm.js +300 -87
  38. package/dist/seo.esm.js.map +1 -1
  39. package/dist/static/wpStatic.d.ts +16 -0
  40. package/dist/static.cjs +10 -0
  41. package/dist/static.cjs.map +1 -1
  42. package/dist/static.d.ts +38 -2
  43. package/dist/static.esm.js +10 -1
  44. package/dist/static.esm.js.map +1 -1
  45. package/dist/utils/notifications.d.ts +3 -0
  46. package/dist/utils/wpRegistry.d.ts +1 -1
  47. package/docs/AI-LOCAL-WORDPRESS-BOOTSTRAP.md +7 -3
  48. package/docs/AI-MASTER-PROMPT.md +37 -0
  49. package/docs/ENVIRONMENT.md +3 -3
  50. package/docs/README.md +8 -5
  51. package/docs/SEO-PERFORMANCE.md +42 -11
  52. package/docs/SHORTCODES.md +39 -0
  53. package/package.json +20 -8
  54. package/template/DIGIVALT_SETUP.md +14 -8
  55. package/template/functions/robots.txt.ts +27 -0
  56. package/template/functions/sitemap.xml.ts +143 -65
  57. package/template/scripts/generate.ts +3 -10
  58. package/template/scripts/prerender-seo.ts +10 -0
  59. package/docs/LOVABLE-MASTER-PROMPT.md +0 -140
@@ -0,0 +1,1528 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var react = require('react');
5
+ var reactQuery = require('@tanstack/react-query');
6
+ var helmetAsync = require('react-helmet-async');
7
+ var wparser = require('@marvalt/wparser');
8
+ var madapter = require('@marvalt/madapter');
9
+ var plister = require('@marvalt/plister');
10
+ var reactRouterDom = require('react-router-dom');
11
+ var wadapter = require('@marvalt/wadapter');
12
+ require('clsx');
13
+ require('tailwind-merge');
14
+
15
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
16
+ /**
17
+ * Prefix a root-absolute path with Vite's `import.meta.env.BASE_URL`.
18
+ * Used so Pages Function URLs (`/api/...`) work when the app is built with a non-root `base`
19
+ * (e.g. path mounts via digivalt-uworker).
20
+ *
21
+ * - Absolute http(s) URLs and protocol-relative URLs are returned unchanged.
22
+ * - Empty / unset BASE_URL (`/` or `./`) leaves root-absolute paths as-is.
23
+ */
24
+ function withBasePath(path) {
25
+ if (/^https?:\/\//i.test(path) || path.startsWith("//")) {
26
+ return path;
27
+ }
28
+ const baseRaw = typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('registry.cjs', document.baseURI).href)) }) !== "undefined" && undefined && typeof undefined.BASE_URL === "string"
29
+ ? undefined.BASE_URL
30
+ : "/";
31
+ const base = baseRaw === "./" ? "/" : baseRaw;
32
+ if (!base || base === "/") {
33
+ return path;
34
+ }
35
+ const baseNorm = base.endsWith("/") ? base.slice(0, -1) : base;
36
+ if (path.startsWith(baseNorm + "/") || path === baseNorm) {
37
+ return path;
38
+ }
39
+ if (path.startsWith("/")) {
40
+ return `${baseNorm}${path}`;
41
+ }
42
+ return `${baseNorm}/${path}`;
43
+ }
44
+
45
+ const getImportMetaEnv = () => {
46
+ try {
47
+ return typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('registry.cjs', document.baseURI).href)) }) !== 'undefined' ? undefined : undefined;
48
+ }
49
+ catch {
50
+ return undefined;
51
+ }
52
+ };
53
+ const getEnv = (key) => {
54
+ const viteEnv = getImportMetaEnv();
55
+ if (viteEnv && key in viteEnv) {
56
+ const value = viteEnv[key];
57
+ return value == null ? undefined : String(value);
58
+ }
59
+ if (typeof process !== 'undefined' && process.env && key in process.env) {
60
+ const value = process.env[key];
61
+ return value == null ? undefined : String(value);
62
+ }
63
+ return undefined;
64
+ };
65
+ const isDevEnvironment = () => {
66
+ const viteEnv = getImportMetaEnv();
67
+ if (viteEnv && 'DEV' in viteEnv) {
68
+ return Boolean(viteEnv.DEV);
69
+ }
70
+ return typeof process !== 'undefined' && process.env?.NODE_ENV === 'development';
71
+ };
72
+ const isBrowserEnvironment = () => {
73
+ return typeof window !== 'undefined' && typeof document !== 'undefined';
74
+ };
75
+
76
+ // @ts-nocheck
77
+ // Gravity Forms data store with proper environment handling
78
+ const transformForm = (formData) => {
79
+ // Transform fields to ensure proper structure
80
+ const transformedFields = (formData.fields || []).map((field) => ({
81
+ id: field.id.toString(), // Ensure ID is string
82
+ type: field.type,
83
+ label: field.label,
84
+ description: field.description,
85
+ isRequired: field.isRequired ?? field.is_required ?? field.required ?? false,
86
+ placeholder: field.placeholder,
87
+ defaultValue: field.defaultValue ?? field.default_value,
88
+ cssClass: field.cssClass ?? field.css_class,
89
+ content: field.content,
90
+ inputs: field.inputs || null,
91
+ choices: field.choices || [],
92
+ validation: {
93
+ message: field.errorMessage ?? field.validationMessage ?? field.validation_message,
94
+ pattern: field.inputMaskValue
95
+ },
96
+ conditionalLogic: field.conditionalLogic ?? field.conditional_logic
97
+ }));
98
+ return {
99
+ id: formData.id.toString(), // Ensure ID is string
100
+ title: formData.title || formData.name || `Form ${formData.id}`,
101
+ description: formData.description,
102
+ fields: transformedFields,
103
+ button: {
104
+ text: formData.button?.text || 'Submit',
105
+ type: formData.button?.type || 'text',
106
+ imageUrl: formData.button?.imageUrl,
107
+ },
108
+ confirmation: {
109
+ type: formData.confirmation?.type || 'message',
110
+ message: formData.confirmation?.message,
111
+ url: formData.confirmation?.url,
112
+ pageId: formData.confirmation?.pageId,
113
+ queryString: formData.confirmation?.queryString,
114
+ isDefault: formData.confirmation?.isDefault,
115
+ },
116
+ settings: {
117
+ enableHoneypot: formData.enableHoneypot || false,
118
+ enableAnimation: formData.enableAnimation || false,
119
+ validationSummary: formData.validationSummary || false,
120
+ saveAndContinue: formData.save?.enabled || false,
121
+ limitEntries: {
122
+ enabled: formData.limitEntries || false,
123
+ limit: formData.limitEntriesCount,
124
+ message: formData.limitEntriesMessage
125
+ },
126
+ scheduleForm: {
127
+ enabled: formData.scheduleForm || false,
128
+ start: formData.scheduleStart,
129
+ end: formData.scheduleEnd,
130
+ message: formData.scheduleMessage
131
+ },
132
+ },
133
+ isActive: formData.isActive === true || formData.is_active === "1" || formData.is_active === true,
134
+ isPublished: formData.isPublished === true || formData.is_trash === "0" || formData.is_trash === false || formData.is_active === "1" || formData.is_active === true,
135
+ };
136
+ };
137
+ // Default fallback data
138
+ const defaultData = {
139
+ generated_at: new Date().toISOString(),
140
+ total_forms: 0,
141
+ forms: []
142
+ };
143
+ // Load static data from the generated JSON file
144
+ let gravityFormsData = defaultData;
145
+ // Function to load data dynamically
146
+ const loadGravityFormsData = async () => {
147
+ if (!isBrowserEnvironment()) {
148
+ return gravityFormsData;
149
+ }
150
+ try {
151
+ console.log('🔄 Loading Gravity Forms data from /gravity-forms-data.json...');
152
+ const response = await fetch('/gravity-forms-data.json');
153
+ if (response.ok) {
154
+ const jsonData = await response.json();
155
+ console.log('🔍 Gravity Forms Data Load Debug:', {
156
+ totalForms: jsonData.total_forms,
157
+ formsCount: jsonData.forms?.length || 0,
158
+ firstForm: jsonData.forms?.[0] ? {
159
+ id: jsonData.forms[0].id,
160
+ title: jsonData.forms[0].title,
161
+ is_active: jsonData.forms[0].is_active,
162
+ isActive: jsonData.forms[0].isActive,
163
+ isPublished: jsonData.forms[0].isPublished
164
+ } : null
165
+ });
166
+ // Transform the data to ensure it matches our interface
167
+ const transformedForms = jsonData.forms.map((form) => transformForm(form));
168
+ gravityFormsData = {
169
+ generated_at: jsonData.generated_at,
170
+ total_forms: jsonData.total_forms,
171
+ forms: transformedForms
172
+ };
173
+ console.log('🔍 Form Transformation Debug:', {
174
+ originalForms: jsonData.forms.map((f) => ({ id: f.id, title: f.title, is_active: f.is_active })),
175
+ transformedForms: transformedForms.map(f => ({ id: f.id, title: f.title, isActive: f.isActive, isPublished: f.isPublished }))
176
+ });
177
+ console.log('🔍 Transformed Forms Debug:', {
178
+ totalForms: gravityFormsData.total_forms,
179
+ formsCount: gravityFormsData.forms.length,
180
+ activeForms: gravityFormsData.forms.filter(f => f.isActive).length,
181
+ publishedForms: gravityFormsData.forms.filter(f => f.isPublished).length
182
+ });
183
+ return gravityFormsData;
184
+ }
185
+ else {
186
+ console.error('❌ Failed to load gravityForms.json:', response.status, response.statusText);
187
+ }
188
+ }
189
+ catch (error) {
190
+ console.error('❌ Error loading gravityForms.json:', error);
191
+ }
192
+ return defaultData;
193
+ };
194
+ const getFormById$1 = (id) => {
195
+ const idStr = String(id);
196
+ const idNum = typeof id === 'number' ? id : parseInt(idStr, 10);
197
+ return gravityFormsData.forms.find(form => String(form.id) === idStr || form.id === idNum);
198
+ };
199
+
200
+ /** Notify an app without depending on an app-local toast component. */
201
+ function notify(level, message) {
202
+ if (typeof window !== 'undefined') {
203
+ window.dispatchEvent(new CustomEvent('digivalt:notification', {
204
+ detail: { level, message },
205
+ }));
206
+ }
207
+ const logger = level === 'error' ? console.error : console.info;
208
+ logger(`[DigiValt] ${message}`);
209
+ }
210
+
211
+ /**
212
+ * Decodes HTML entities in a string
213
+ * Handles both named entities (&, ") and numeric entities (', ’)
214
+ * @param text - The text string with HTML entities
215
+ * @returns Decoded text string
216
+ */
217
+ function decodeHtmlEntities(text) {
218
+ if (!text)
219
+ return '';
220
+ // Use browser's built-in decoder if available (most efficient)
221
+ if (typeof document !== 'undefined') {
222
+ const textarea = document.createElement('textarea');
223
+ textarea.innerHTML = text;
224
+ return textarea.value;
225
+ }
226
+ // Fallback for server-side or when document is not available
227
+ // Decode common named entities
228
+ const namedEntities = {
229
+ '&': '&',
230
+ '&lt;': '<',
231
+ '&gt;': '>',
232
+ '&quot;': '"',
233
+ '&apos;': "'",
234
+ '&nbsp;': ' ',
235
+ '&copy;': '©',
236
+ '&reg;': '®',
237
+ '&trade;': '™',
238
+ '&hellip;': '…',
239
+ '&mdash;': '—',
240
+ '&ndash;': '–',
241
+ '&lsquo;': '\u2018', // Left single quotation mark
242
+ '&rsquo;': '\u2019', // Right single quotation mark
243
+ '&ldquo;': '\u201C', // Left double quotation mark
244
+ '&rdquo;': '\u201D', // Right double quotation mark
245
+ };
246
+ let decoded = text;
247
+ // Decode numeric entities (&#039;, &#8217;, etc.)
248
+ decoded = decoded.replace(/&#(\d+);/g, (match, dec) => {
249
+ return String.fromCharCode(parseInt(dec, 10));
250
+ });
251
+ // Decode hex entities (&#x27;, etc.)
252
+ decoded = decoded.replace(/&#x([0-9a-fA-F]+);/g, (match, hex) => {
253
+ return String.fromCharCode(parseInt(hex, 16));
254
+ });
255
+ // Decode named entities
256
+ Object.entries(namedEntities).forEach(([entity, char]) => {
257
+ decoded = decoded.replace(new RegExp(entity, 'g'), char);
258
+ });
259
+ return decoded;
260
+ }
261
+ /**
262
+ * Replaces common WordPress HTML entities so they display as expected (e.g. en dash as hyphen, &#038;/&amp; as &).
263
+ * Use on block innerHTML or other WP-rendered HTML before passing to dangerouslySetInnerHTML.
264
+ */
265
+ function normalizeWordPressHtmlEntities(html) {
266
+ if (!html)
267
+ return '';
268
+ return decodeHtmlEntities(html.replace(/&#8211;/g, '-'));
269
+ }
270
+ /**
271
+ * Validates if a URL is safe for redirects
272
+ * @param url - The URL to validate
273
+ * @param allowedDomains - Array of allowed domains (optional)
274
+ * @returns boolean indicating if the URL is safe
275
+ */
276
+ function isValidRedirectUrl(url, allowedDomains = []) {
277
+ if (!url)
278
+ return false;
279
+ try {
280
+ const urlObj = new URL(url);
281
+ // Check if it's a relative URL (safe)
282
+ if (!urlObj.protocol)
283
+ return true;
284
+ // Check if it's HTTP/HTTPS
285
+ if (!['http:', 'https:'].includes(urlObj.protocol))
286
+ return false;
287
+ // If allowed domains are specified, check against them
288
+ if (allowedDomains.length > 0) {
289
+ return allowedDomains.some(domain => urlObj.hostname === domain || urlObj.hostname.endsWith(`.${domain}`));
290
+ }
291
+ // Default: allow any HTTPS URL or same-origin HTTP
292
+ return urlObj.protocol === 'https:' || urlObj.hostname === window.location.hostname;
293
+ }
294
+ catch {
295
+ return false;
296
+ }
297
+ }
298
+ /**
299
+ * Safely redirects to a URL after validation
300
+ * @param url - The URL to redirect to
301
+ * @param allowedDomains - Array of allowed domains (optional)
302
+ * @param fallbackUrl - Fallback URL if validation fails (optional)
303
+ */
304
+ function safeRedirect(url, allowedDomains = [], fallbackUrl) {
305
+ if (isValidRedirectUrl(url, allowedDomains)) {
306
+ window.location.href = url;
307
+ }
308
+ else {
309
+ console.warn('Invalid redirect URL:', url);
310
+ }
311
+ }
312
+
313
+ // @ts-nocheck
314
+ // Minimal browser-safe static data loader to avoid importing Node-only code in the runtime bundle.
315
+ /** Recursively normalize WordPress HTML entities (e.g. &#8211; → "-") in block innerHTML. */
316
+ function normalizeBlocksHtml(blocks) {
317
+ if (!blocks)
318
+ return;
319
+ for (const block of blocks) {
320
+ if (block.innerHTML && typeof block.innerHTML === 'string') {
321
+ block.innerHTML = normalizeWordPressHtmlEntities(block.innerHTML);
322
+ }
323
+ if (block.innerBlocks?.length)
324
+ normalizeBlocksHtml(block.innerBlocks);
325
+ }
326
+ }
327
+ /** Recursively decode HTML entities in all string values of an event_meta-like object (mutate in place). */
328
+ function normalizeEventMetaStrings(meta) {
329
+ for (const key of Object.keys(meta)) {
330
+ const v = meta[key];
331
+ if (typeof v === 'string') {
332
+ meta[key] = decodeHtmlEntities(v);
333
+ }
334
+ else if (Array.isArray(v)) {
335
+ for (let i = 0; i < v.length; i++) {
336
+ const el = v[i];
337
+ if (typeof el === 'string') {
338
+ v[i] = decodeHtmlEntities(el);
339
+ }
340
+ else if (el && typeof el === 'object' && !Array.isArray(el)) {
341
+ normalizeEventMetaStrings(el);
342
+ }
343
+ }
344
+ }
345
+ }
346
+ }
347
+ /** Normalize title.rendered, excerpt.rendered, content.rendered, content_cloudflare on a WP-like item (mutate in place). */
348
+ function normalizeRenderedStrings(item) {
349
+ if (!item || typeof item !== 'object')
350
+ return;
351
+ if (typeof item.title?.rendered === 'string') {
352
+ item.title.rendered = normalizeWordPressHtmlEntities(item.title.rendered);
353
+ }
354
+ if (typeof item.excerpt?.rendered === 'string') {
355
+ item.excerpt.rendered = normalizeWordPressHtmlEntities(item.excerpt.rendered);
356
+ }
357
+ if (typeof item.content?.rendered === 'string') {
358
+ item.content.rendered = normalizeWordPressHtmlEntities(item.content.rendered);
359
+ }
360
+ if (typeof item.content_cloudflare === 'string') {
361
+ item.content_cloudflare = normalizeWordPressHtmlEntities(item.content_cloudflare);
362
+ }
363
+ }
364
+ /**
365
+ * Mask email for privacy: first char of local + ***@****** + last char of domain name + TLD.
366
+ * Example: name@example.com.au → n***@******e.com.au
367
+ */
368
+ function maskEmail(email) {
369
+ const s = typeof email === 'string' ? email.trim() : '';
370
+ if (!s || !s.includes('@'))
371
+ return '***@***.***';
372
+ const parts = s.split('@', 2);
373
+ const local = parts[0];
374
+ const domain = parts[1];
375
+ if (!local || !domain)
376
+ return '***@***.***';
377
+ const localFirst = local.slice(0, 1);
378
+ const domainBits = domain.split('.');
379
+ if (domainBits.length < 2)
380
+ return localFirst + '***@******.' + domain;
381
+ const domainName = domainBits.shift() ?? '';
382
+ const tld = domainBits.join('.');
383
+ const domainLast = domainName.slice(-1);
384
+ return localFirst + '***@******' + domainLast + '.' + tld;
385
+ }
386
+ /** Replace raw members_email with masked value on each member in member arrays. */
387
+ function maskMemberEmailsInStaticData(data) {
388
+ if (!data)
389
+ return;
390
+ const memberKeys = ['chapter_member', 'members', 'member'];
391
+ const dataRecord = data;
392
+ for (const key of memberKeys) {
393
+ const arr = dataRecord[key];
394
+ if (!Array.isArray(arr))
395
+ continue;
396
+ for (const item of arr) {
397
+ if (item && typeof item === 'object') {
398
+ const obj = item;
399
+ if (obj.member_meta && typeof obj.member_meta === 'object') {
400
+ const meta = obj.member_meta;
401
+ if (meta.members_email != null)
402
+ meta.members_email = maskEmail(meta.members_email);
403
+ }
404
+ if (obj.public_profile && typeof obj.public_profile === 'object') {
405
+ const profile = obj.public_profile;
406
+ if (profile.members_email != null)
407
+ profile.members_email = maskEmail(profile.members_email);
408
+ }
409
+ }
410
+ }
411
+ }
412
+ }
413
+ /** Walk static data and normalize block HTML and .rendered/content fields so entities like &#8211; display correctly. */
414
+ function normalizeWordPressHtmlInStaticData(data) {
415
+ if (!data)
416
+ return;
417
+ if (data.pages) {
418
+ for (const page of data.pages) {
419
+ normalizeRenderedStrings(page);
420
+ if (page.blocks)
421
+ normalizeBlocksHtml(page.blocks);
422
+ }
423
+ }
424
+ if (data.posts) {
425
+ for (const post of data.posts) {
426
+ normalizeRenderedStrings(post);
427
+ }
428
+ }
429
+ const cptKeys = ['eventbrite_event', 'member', 'testimonial', 'chapter_member', 'members'];
430
+ const dataRecord = data;
431
+ for (const key of cptKeys) {
432
+ const arr = dataRecord[key];
433
+ if (Array.isArray(arr)) {
434
+ for (const item of arr) {
435
+ normalizeRenderedStrings(item);
436
+ if (key === 'eventbrite_event' && item?.event_meta && typeof item.event_meta === 'object' && !Array.isArray(item.event_meta)) {
437
+ normalizeEventMetaStrings(item.event_meta);
438
+ }
439
+ }
440
+ }
441
+ }
442
+ if (data.site_settings && typeof data.site_settings === 'object') {
443
+ const settings = data.site_settings;
444
+ if (typeof settings.name === 'string')
445
+ settings.name = normalizeWordPressHtmlEntities(settings.name);
446
+ if (typeof settings.description === 'string')
447
+ settings.description = normalizeWordPressHtmlEntities(settings.description);
448
+ }
449
+ if (data.header?.blocks)
450
+ normalizeBlocksHtml(data.header.blocks);
451
+ if (data.footer?.blocks)
452
+ normalizeBlocksHtml(data.footer.blocks);
453
+ }
454
+ let wpStaticCache = null;
455
+ const loadWordPressData = async (path = '/wordpress-data.json') => {
456
+ if (wpStaticCache)
457
+ return;
458
+ const res = await fetch(path);
459
+ if (!res.ok)
460
+ throw new Error(`Failed to load WordPress static data: ${res.status}`);
461
+ wpStaticCache = (await res.json());
462
+ normalizeWordPressHtmlInStaticData(wpStaticCache);
463
+ maskMemberEmailsInStaticData(wpStaticCache);
464
+ // Expose cache globally for theme loading (temporary workaround)
465
+ if (typeof window !== 'undefined') {
466
+ window.__wpStaticCache = wpStaticCache;
467
+ }
468
+ };
469
+ const getWordPressPages = () => wpStaticCache?.pages ?? [];
470
+ const getWordPressPageBySlug = (slug) => {
471
+ const pages = getWordPressPages();
472
+ return pages.find(page => page.slug === slug);
473
+ };
474
+ const getWordPressPageById = (id) => {
475
+ const pages = getWordPressPages();
476
+ return pages.find(page => page.id === id);
477
+ };
478
+
479
+ const TurnstileWidget = ({ siteKey, action, cData, onSuccess, onError, onExpire, theme = 'auto', size = 'normal', tabIndex, onWidgetId, }) => {
480
+ const widgetRef = react.useRef(null);
481
+ const widgetId = react.useRef(null);
482
+ const scriptLoaded = react.useRef(false);
483
+ react.useEffect(() => {
484
+ if (!widgetRef.current || !siteKey)
485
+ return;
486
+ const loadTurnstile = () => {
487
+ if (window.turnstile && widgetRef.current && !widgetId.current) {
488
+ try {
489
+ widgetId.current = window.turnstile.render(widgetRef.current, {
490
+ sitekey: siteKey,
491
+ callback: onSuccess,
492
+ 'error-callback': onError,
493
+ 'expired-callback': onExpire,
494
+ theme,
495
+ size,
496
+ tabindex: tabIndex,
497
+ });
498
+ // Notify parent component of widget ID for reset capability
499
+ if (widgetId.current && onWidgetId) {
500
+ onWidgetId(widgetId.current);
501
+ }
502
+ }
503
+ catch (error) {
504
+ console.error('Failed to render Turnstile widget:', error);
505
+ onError?.();
506
+ }
507
+ }
508
+ };
509
+ // Check if Turnstile is already loaded
510
+ if (window.turnstile) {
511
+ loadTurnstile();
512
+ }
513
+ else if (!scriptLoaded.current) {
514
+ // Load Turnstile script
515
+ scriptLoaded.current = true;
516
+ const script = document.createElement('script');
517
+ script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js';
518
+ script.async = true;
519
+ script.defer = true;
520
+ script.onload = loadTurnstile;
521
+ script.onerror = () => {
522
+ console.error('Failed to load Turnstile script');
523
+ onError?.();
524
+ };
525
+ document.head.appendChild(script);
526
+ }
527
+ return () => {
528
+ if (widgetId.current && window.turnstile) {
529
+ try {
530
+ window.turnstile.remove(widgetId.current);
531
+ }
532
+ catch (error) {
533
+ console.error('Failed to remove Turnstile widget:', error);
534
+ }
535
+ widgetId.current = null;
536
+ }
537
+ };
538
+ }, [siteKey, onSuccess, onError, onExpire, theme, size, tabIndex]);
539
+ return jsxRuntime.jsx("div", { ref: widgetRef, className: "cf-turnstile" });
540
+ };
541
+ const StaticGravityForm = ({ formId, config, className = '', onSubmit, onError, }) => {
542
+ const navigate = reactRouterDom.useNavigate();
543
+ const [form, setForm] = react.useState(null);
544
+ const [loading, setLoading] = react.useState(true);
545
+ const [error, setError] = react.useState(null); // For loading/data errors only
546
+ const [submissionError, setSubmissionError] = react.useState(null); // For submission errors only
547
+ const [submitting, setSubmitting] = react.useState(false);
548
+ const [result, setResult] = react.useState(null);
549
+ const [submitted, setSubmitted] = react.useState(false); // Track if form was successfully submitted
550
+ const [formData, setFormData] = react.useState({});
551
+ const [turnstileToken, setTurnstileToken] = react.useState(null);
552
+ const [turnstileError, setTurnstileError] = react.useState(null);
553
+ const turnstileWidgetIdRef = react.useRef(null);
554
+ // Load form from static data
555
+ react.useEffect(() => {
556
+ const loadForm = async () => {
557
+ try {
558
+ setLoading(true);
559
+ setError(null);
560
+ if (process.env.NODE_ENV !== 'production') {
561
+ console.log('🔍 StaticGravityForm: Loading form', { formId, formIdType: typeof formId });
562
+ }
563
+ // Ensure static data is loaded
564
+ const dataStore = await loadGravityFormsData();
565
+ if (process.env.NODE_ENV !== 'production') {
566
+ console.log('🔍 StaticGravityForm: Data loaded', {
567
+ totalForms: dataStore?.total_forms,
568
+ formsCount: dataStore?.forms?.length,
569
+ availableFormIds: dataStore?.forms?.map(f => f.id),
570
+ });
571
+ }
572
+ // Get form from static store - try both string and number formats
573
+ const formIdStr = String(formId);
574
+ const formIdNum = typeof formId === 'number' ? formId : parseInt(formIdStr, 10);
575
+ let staticForm = getFormById$1(formIdStr);
576
+ // If not found with string, try with number as string
577
+ if (!staticForm && !isNaN(formIdNum)) {
578
+ staticForm = getFormById$1(String(formIdNum));
579
+ }
580
+ if (process.env.NODE_ENV !== 'production') {
581
+ console.log('🔍 StaticGravityForm: Form lookup', {
582
+ formId,
583
+ formIdStr,
584
+ formIdNum,
585
+ found: !!staticForm,
586
+ formTitle: staticForm?.title,
587
+ });
588
+ }
589
+ if (!staticForm) {
590
+ const errorMsg = `Form with ID ${formId} not found in static data. Please ensure the form exists in /gravity-forms-data.json and run 'npm run generate:gf' to regenerate static data.`;
591
+ console.error('❌ StaticGravityForm:', errorMsg);
592
+ setError(new Error(errorMsg));
593
+ setLoading(false);
594
+ return;
595
+ }
596
+ setForm(staticForm);
597
+ if (process.env.NODE_ENV !== 'production') {
598
+ console.log('✅ StaticGravityForm: Form loaded successfully', {
599
+ formId: staticForm.id,
600
+ title: staticForm.title,
601
+ fieldsCount: staticForm.fields?.length,
602
+ });
603
+ }
604
+ }
605
+ catch (err) {
606
+ const error = err instanceof Error ? err : new Error('Failed to load form from static data');
607
+ console.error('❌ StaticGravityForm error:', error);
608
+ setError(error);
609
+ if (onError) {
610
+ onError(error);
611
+ }
612
+ }
613
+ finally {
614
+ setLoading(false);
615
+ }
616
+ };
617
+ loadForm();
618
+ }, [formId, onError]);
619
+ // Get Turnstile site key from environment - memoized to prevent re-renders
620
+ const turnstilesiteKey = react.useMemo(() => {
621
+ try {
622
+ // @ts-ignore - import.meta is a Vite-specific global
623
+ if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('registry.cjs', document.baseURI).href)) }) !== 'undefined' && undefined) {
624
+ // @ts-ignore
625
+ const key = undefined.VITE_TURNSTILE_SITE_KEY;
626
+ // Ensure we return a string or undefined, not an object
627
+ return typeof key === 'string' ? key : undefined;
628
+ }
629
+ }
630
+ catch (e) {
631
+ // import.meta not available
632
+ }
633
+ return undefined;
634
+ }, []); // Empty deps - site key doesn't change during runtime
635
+ // Memoize Turnstile callbacks to prevent widget re-renders
636
+ const handleTurnstileSuccess = react.useCallback((token) => {
637
+ setTurnstileToken(token);
638
+ setTurnstileError(null);
639
+ }, []);
640
+ const handleTurnstileError = react.useCallback(() => {
641
+ setTurnstileToken(null);
642
+ setTurnstileError('Verification failed. Please try again.');
643
+ }, []);
644
+ const handleTurnstileExpire = react.useCallback(() => {
645
+ setTurnstileToken(null);
646
+ setTurnstileError('Verification expired. Please verify again.');
647
+ }, []);
648
+ // Handle form submission using API
649
+ const handleSubmit = async (e) => {
650
+ e.preventDefault();
651
+ // Check Turnstile token if enabled
652
+ if (turnstilesiteKey && !turnstileToken) {
653
+ setTurnstileError('Please complete the verification');
654
+ return;
655
+ }
656
+ if (!form) {
657
+ const error = new Error('Form data not available');
658
+ setError(error);
659
+ if (onError) {
660
+ onError(error);
661
+ }
662
+ return;
663
+ }
664
+ console.log('🔍 StaticGravityForm.handleSubmit:', {
665
+ formId,
666
+ formData,
667
+ formDataKeys: Object.keys(formData),
668
+ turnstileToken,
669
+ });
670
+ try {
671
+ setSubmitting(true);
672
+ setSubmissionError(null);
673
+ setResult(null);
674
+ // Create GravityFormsClient for submission only
675
+ const client = new wadapter.GravityFormsClient({
676
+ ...config,
677
+ proxyEndpoint: config.proxyEndpoint || withBasePath('/api/gravity-forms-submit'),
678
+ });
679
+ const submission = {
680
+ form_id: parseInt(String(formId), 10),
681
+ field_values: formData,
682
+ ...(turnstileToken ? {
683
+ headers: {
684
+ 'cf-turnstile-response': turnstileToken
685
+ }
686
+ } : {})
687
+ };
688
+ console.log('🔍 StaticGravityForm submission object:', submission);
689
+ // Submit form via API
690
+ const submissionResult = await client.submitForm(parseInt(String(formId), 10), submission);
691
+ setResult(submissionResult);
692
+ // Clear form data after successful submission
693
+ setFormData({});
694
+ // Reset Turnstile widget if present
695
+ if (turnstileWidgetIdRef.current && window.turnstile) {
696
+ try {
697
+ window.turnstile.reset(turnstileWidgetIdRef.current);
698
+ }
699
+ catch (e) {
700
+ console.warn('Failed to reset Turnstile widget:', e);
701
+ }
702
+ }
703
+ setTurnstileToken(null);
704
+ setTurnstileError(null);
705
+ // Mark form as submitted
706
+ setSubmitted(true);
707
+ // Show success toast
708
+ notify('success', submissionResult.message || 'Form submitted successfully!');
709
+ // Handle confirmation types
710
+ const confirmation = submissionResult.confirmation;
711
+ if (confirmation) {
712
+ if (confirmation.type === 'redirect' && confirmation.url) {
713
+ // Redirect to URL
714
+ setTimeout(() => {
715
+ safeRedirect(confirmation.url);
716
+ }, 1500); // Small delay to show success message
717
+ }
718
+ else if (confirmation.type === 'page' && (confirmation.pageId || confirmation.page_id)) {
719
+ // Resolve page slug from ID and navigate
720
+ // Handle both camelCase (pageId) and snake_case (page_id) from API
721
+ const pageId = confirmation.pageId || confirmation.page_id;
722
+ // Load WordPress data if not already loaded, then resolve page
723
+ loadWordPressData().then(() => {
724
+ const page = getWordPressPageById(Number(pageId));
725
+ if (page?.slug) {
726
+ setTimeout(() => {
727
+ navigate(`/${page.slug}`);
728
+ }, 1500); // Small delay to show success message
729
+ }
730
+ else {
731
+ console.warn(`Page with ID ${pageId} not found in static data`);
732
+ }
733
+ }).catch((err) => {
734
+ console.error('Failed to load WordPress data for page redirect:', err);
735
+ });
736
+ }
737
+ // For 'message' type, we'll show the confirmation message in the UI
738
+ }
739
+ if (onSubmit) {
740
+ onSubmit(submissionResult);
741
+ }
742
+ }
743
+ catch (err) {
744
+ const error = err instanceof Error ? err : new Error('Unknown error');
745
+ console.error('❌ StaticGravityForm submission error:', error);
746
+ console.error('🔍 Error details:', {
747
+ message: error.message,
748
+ data: error.data,
749
+ validation_errors: error.validation_errors,
750
+ code: error.code,
751
+ });
752
+ // Determine error type and show appropriate message
753
+ let errorMessage = 'Form submission failed. Please try again.';
754
+ // Check if this is a CORS or network error
755
+ // Only show "Wrangler not running" if it's a clear network failure (ERR_FAILED, network error)
756
+ // Not for generic "Failed to fetch" which can happen for many reasons
757
+ const isNetworkError = error.message.includes('ERR_FAILED') ||
758
+ error.message.includes('NetworkError') ||
759
+ (error.message.includes('Failed to fetch') && !error.message.includes('403') && !error.message.includes('404') && !error.message.includes('500'));
760
+ const isCorsError = error.message.includes('CORS') || error.message.includes('Access-Control');
761
+ if (isNetworkError && config.proxyEndpoint?.includes('127.0.0.1:8788')) {
762
+ // Only show Wrangler error for clear network failures when using Wrangler proxy
763
+ errorMessage = 'Unable to connect to Wrangler development server. Please ensure it is running with `npm run pages:dev` on port 8788, or disable VITE_LOCAL_DEVELOPMENT to use the production proxy.';
764
+ }
765
+ else if (isCorsError) {
766
+ errorMessage = 'CORS error: The server is not allowing requests from this origin. Please check server configuration.';
767
+ }
768
+ else if (isNetworkError) {
769
+ errorMessage = 'Unable to connect to form server. Please check your connection or try again later.';
770
+ }
771
+ else if (error.message.includes('404') || error.message.includes('Not Found')) {
772
+ errorMessage = 'Form submission endpoint not found. Please contact support.';
773
+ }
774
+ else if (error.message.includes('403') || error.message.includes('Forbidden')) {
775
+ errorMessage = 'Form submission was denied. Please check your permissions.';
776
+ }
777
+ else if (error.message.includes('400') || error.message.includes('Bad Request')) {
778
+ // Try to extract validation errors from the error object
779
+ // WordPress REST API format: { code, message, data: { status, validation_errors } }
780
+ const errorData = error.data;
781
+ const validationErrors = error.validation_errors || errorData?.data?.validation_errors || errorData?.validation_errors;
782
+ if (validationErrors && typeof validationErrors === 'object') {
783
+ // Format validation errors for display
784
+ const errorList = Object.entries(validationErrors)
785
+ .map(([field, message]) => {
786
+ // Try to get field label from form if available
787
+ // For name fields, check if it's a sub-input (e.g., "1.3") and find parent field
788
+ let fieldObj = form?.fields?.find((f) => String(f.id) === String(field));
789
+ // If not found, it might be a sub-input of a name field
790
+ if (!fieldObj && field.includes('.')) {
791
+ const parentFieldId = field.split('.')[0];
792
+ fieldObj = form?.fields?.find((f) => String(f.id) === String(parentFieldId));
793
+ // If it's a name field, use the parent field's label
794
+ if (fieldObj?.type === 'name') {
795
+ return `${decodeHtmlEntities(fieldObj.label)}: ${message}`;
796
+ }
797
+ }
798
+ const fieldLabel = fieldObj?.label ? decodeHtmlEntities(fieldObj.label) : `Field ${field}`;
799
+ return `${fieldLabel}: ${message}`;
800
+ })
801
+ .join('; ');
802
+ errorMessage = `Validation failed: ${errorList}`;
803
+ }
804
+ else if (error.message.includes('Validation failed')) {
805
+ errorMessage = 'Form validation failed. Please check all required fields are filled correctly.';
806
+ }
807
+ else {
808
+ // Use the error message from WordPress
809
+ errorMessage = error.message || 'Form submission failed. Please try again.';
810
+ }
811
+ }
812
+ else if (error.message.includes('Network') || error.message.includes('network')) {
813
+ errorMessage = 'Network error. Please check your internet connection and try again.';
814
+ }
815
+ else if (error.message) {
816
+ // Use the error message if it's user-friendly
817
+ errorMessage = error.message;
818
+ }
819
+ setSubmissionError(error);
820
+ // Show error toast
821
+ notify('error', errorMessage);
822
+ if (onError) {
823
+ onError(error);
824
+ }
825
+ }
826
+ finally {
827
+ setSubmitting(false);
828
+ }
829
+ };
830
+ const handleFieldChange = (fieldId, value) => {
831
+ setFormData(prev => ({
832
+ ...prev,
833
+ [fieldId]: value,
834
+ }));
835
+ };
836
+ // Loading state
837
+ if (loading) {
838
+ return jsxRuntime.jsx("div", { className: `gravity-form loading ${className}`, children: "Loading form..." });
839
+ }
840
+ // Loading/Data error state (not submission errors)
841
+ if (error) {
842
+ return (jsxRuntime.jsxs("div", { className: `gravity-form error ${className}`, children: [jsxRuntime.jsxs("p", { children: ["Error: ", error.message] }), process.env.NODE_ENV !== 'production' && (jsxRuntime.jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Make sure the form exists in /gravity-forms-data.json and run `npm run generate:gf` to regenerate static data." }))] }));
843
+ }
844
+ // Form not found state
845
+ if (!form) {
846
+ return (jsxRuntime.jsxs("div", { className: `gravity-form not-found ${className}`, children: [jsxRuntime.jsx("p", { children: "Form not found" }), process.env.NODE_ENV !== 'production' && (jsxRuntime.jsxs("p", { className: "text-sm text-gray-500 mt-2", children: ["Form ID: ", formId, ". Check /gravity-forms-data.json or run `npm run generate:gf`."] }))] }));
847
+ }
848
+ // Show confirmation message if form was submitted and confirmation type is 'message'
849
+ const confirmation = result?.confirmation;
850
+ const showConfirmation = submitted && confirmation?.type === 'message';
851
+ return (jsxRuntime.jsx("div", { className: `gravity-form max-w-2xl mx-auto ${className}`, children: showConfirmation ? (
852
+ // Show confirmation message instead of form
853
+ jsxRuntime.jsxs("div", { className: "space-y-6 bg-white/95 backdrop-blur-sm p-6 md:p-8 rounded-lg shadow-lg", children: [form.title && (jsxRuntime.jsx("h2", { className: "text-2xl md:text-3xl font-bold mb-4 text-gray-900", children: form.title })), jsxRuntime.jsx("div", { className: "rounded-md bg-green-50 px-4 py-3 text-sm text-green-800 border border-green-200", children: confirmation?.message || result?.message || 'Thank you for your submission!' })] })) : (
854
+ // Show form
855
+ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: "space-y-6 bg-white/95 backdrop-blur-sm p-6 md:p-8 rounded-lg shadow-lg", children: [form.title && (jsxRuntime.jsx("h2", { className: "text-2xl md:text-3xl font-bold mb-4 text-gray-900", children: form.title })), form.description && (jsxRuntime.jsx("p", { className: "text-gray-600 mb-6", children: decodeHtmlEntities(form.description) })), form.fields.map(field => (jsxRuntime.jsxs("div", { className: `field field-${field.type} space-y-2`, children: [field.type !== 'html' && (jsxRuntime.jsxs("label", { htmlFor: `field_${field.id}`, className: "block text-sm font-medium text-gray-700", children: [decodeHtmlEntities(field.label), field.isRequired && jsxRuntime.jsx("span", { className: "text-red-500 ml-1", children: "*" })] })), field.type !== 'html' && field.description && (jsxRuntime.jsx("p", { className: "field-description text-sm text-gray-500", children: decodeHtmlEntities(field.description) })), field.type === 'html' && (jsxRuntime.jsx("div", { className: "gf-html-field prose max-w-none text-gray-700", dangerouslySetInnerHTML: { __html: decodeHtmlEntities(field.content || field.description || '') } })), field.type === 'text' && (jsxRuntime.jsx("input", { type: "text", id: `field_${field.id}`, name: field.label, required: field.isRequired, placeholder: field.placeholder ? decodeHtmlEntities(field.placeholder) : undefined, value: formData[field.id] || field.defaultValue || '', onChange: (e) => handleFieldChange(field.id, e.target.value), className: "w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-gray-900 bg-white" })), field.type === 'email' && (jsxRuntime.jsx("input", { type: "email", id: `field_${field.id}`, name: field.label, required: field.isRequired, placeholder: field.placeholder ? decodeHtmlEntities(field.placeholder) : undefined, value: formData[field.id] || field.defaultValue || '', onChange: (e) => handleFieldChange(field.id, e.target.value), className: "w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-gray-900 bg-white" })), field.type === 'textarea' && (jsxRuntime.jsx("textarea", { id: `field_${field.id}`, name: field.label, required: field.isRequired, placeholder: field.placeholder ? decodeHtmlEntities(field.placeholder) : undefined, value: formData[field.id] || field.defaultValue || '', onChange: (e) => handleFieldChange(field.id, e.target.value), rows: 4, className: "w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-gray-900 bg-white resize-y" })), field.type === 'select' && field.choices && (jsxRuntime.jsxs("select", { id: `field_${field.id}`, name: field.label, required: field.isRequired, value: formData[field.id] || field.defaultValue || (field.choices.find(c => c.isSelected)?.value || ''), onChange: (e) => handleFieldChange(field.id, e.target.value), className: "w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-gray-900 bg-white", children: [jsxRuntime.jsx("option", { value: "", children: "Select an option" }), field.choices.map((choice, index) => (jsxRuntime.jsx("option", { value: choice.value, children: decodeHtmlEntities(choice.text) }, index)))] })), field.type === 'name' && field.inputs && (jsxRuntime.jsx("div", { className: "name-field-inputs grid grid-cols-1 md:grid-cols-2 gap-4", children: field.inputs
856
+ .filter((input) => !input.isHidden)
857
+ .map((input) => (jsxRuntime.jsxs("div", { className: "name-input space-y-2", children: [jsxRuntime.jsxs("label", { htmlFor: `field_${input.id}`, className: "block text-sm font-medium text-gray-700", children: [input.label, field.isRequired && input.label.toLowerCase().includes('first') && (jsxRuntime.jsx("span", { className: "text-red-500 ml-1", children: "*" }))] }), input.choices ? (jsxRuntime.jsxs("select", { id: `field_${input.id}`, name: input.name || input.label, onChange: (e) => handleFieldChange(input.id, e.target.value), className: "w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-gray-900 bg-white", children: [jsxRuntime.jsxs("option", { value: "", children: ["Select ", decodeHtmlEntities(input.label)] }), input.choices.map((choice, index) => (jsxRuntime.jsx("option", { value: choice.value, children: decodeHtmlEntities(choice.text) }, index)))] })) : (jsxRuntime.jsx("input", { type: "text", id: `field_${input.id}`, name: input.name || input.label, placeholder: input.placeholder ? decodeHtmlEntities(input.placeholder) : undefined, required: field.isRequired && input.label.toLowerCase().includes('first'), autoComplete: input.autocompleteAttribute, value: formData[input.id] || '', onChange: (e) => handleFieldChange(input.id, e.target.value), className: "w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-gray-900 bg-white" }))] }, input.id))) }))] }, field.id))), turnstilesiteKey && (jsxRuntime.jsxs("div", { className: "form-turnstile flex justify-center py-4", children: [jsxRuntime.jsx(TurnstileWidget, { siteKey: turnstilesiteKey, onSuccess: handleTurnstileSuccess, onError: handleTurnstileError, onExpire: handleTurnstileExpire, onWidgetId: (id) => { turnstileWidgetIdRef.current = id; }, theme: "auto", size: "normal" }), turnstileError && (jsxRuntime.jsx("p", { className: "field-error turnstile-error text-red-600 text-sm mt-2", children: turnstileError }))] })), jsxRuntime.jsx("button", { type: "submit", disabled: submitting || (!!turnstilesiteKey && !turnstileToken), className: "w-full md:w-auto px-6 py-3 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed text-white font-semibold rounded-md shadow-md transition-colors duration-200", children: submitting
858
+ ? 'Submitting...'
859
+ : (turnstilesiteKey && !turnstileToken)
860
+ ? 'Complete verification first'
861
+ : form.button?.text || 'Submit' }), result && !result.success && (jsxRuntime.jsx("div", { className: `result p-4 rounded-md bg-red-50 text-red-800 border border-red-200`, children: result.message }))] })) }));
862
+ };
863
+
864
+ var forms = [
865
+ {
866
+ id: 3,
867
+ name: "Eventbright Form",
868
+ alias: "eventbrigh",
869
+ description: null,
870
+ isPublished: true,
871
+ fields: [
872
+ {
873
+ id: 10,
874
+ label: "First Name",
875
+ showLabel: true,
876
+ alias: "first_name",
877
+ type: "text",
878
+ defaultValue: null,
879
+ isRequired: true,
880
+ validationMessage: null,
881
+ helpMessage: null,
882
+ order: 1,
883
+ properties: {
884
+ placeholder: null
885
+ },
886
+ validation: [
887
+ ],
888
+ parent: null,
889
+ conditions: [
890
+ ],
891
+ labelAttributes: null,
892
+ inputAttributes: null,
893
+ containerAttributes: null,
894
+ leadField: "firstname",
895
+ saveResult: true,
896
+ isAutoFill: true,
897
+ isReadOnly: false,
898
+ mappedObject: "contact",
899
+ mappedField: "firstname"
900
+ },
901
+ {
902
+ id: 11,
903
+ label: "Last Name",
904
+ showLabel: true,
905
+ alias: "last_name",
906
+ type: "text",
907
+ defaultValue: null,
908
+ isRequired: true,
909
+ validationMessage: null,
910
+ helpMessage: null,
911
+ order: 2,
912
+ properties: {
913
+ placeholder: null
914
+ },
915
+ validation: [
916
+ ],
917
+ parent: null,
918
+ conditions: [
919
+ ],
920
+ labelAttributes: null,
921
+ inputAttributes: null,
922
+ containerAttributes: null,
923
+ leadField: "lastname",
924
+ saveResult: true,
925
+ isAutoFill: true,
926
+ isReadOnly: false,
927
+ mappedObject: "contact",
928
+ mappedField: "lastname"
929
+ },
930
+ {
931
+ id: 8,
932
+ label: "Email",
933
+ showLabel: true,
934
+ alias: "email",
935
+ type: "email",
936
+ defaultValue: null,
937
+ isRequired: true,
938
+ validationMessage: null,
939
+ helpMessage: null,
940
+ order: 3,
941
+ properties: {
942
+ placeholder: null
943
+ },
944
+ validation: [
945
+ ],
946
+ parent: null,
947
+ conditions: [
948
+ ],
949
+ labelAttributes: null,
950
+ inputAttributes: null,
951
+ containerAttributes: null,
952
+ leadField: "email",
953
+ saveResult: true,
954
+ isAutoFill: true,
955
+ isReadOnly: false,
956
+ mappedObject: "contact",
957
+ mappedField: "email"
958
+ },
959
+ {
960
+ id: 9,
961
+ label: "Submit",
962
+ showLabel: true,
963
+ alias: "submit",
964
+ type: "button",
965
+ defaultValue: null,
966
+ isRequired: false,
967
+ validationMessage: null,
968
+ helpMessage: null,
969
+ order: 4,
970
+ properties: [
971
+ ],
972
+ validation: [
973
+ ],
974
+ parent: null,
975
+ conditions: [
976
+ ],
977
+ labelAttributes: null,
978
+ inputAttributes: "class=\"btn btn-ghost\"",
979
+ containerAttributes: null,
980
+ leadField: null,
981
+ saveResult: true,
982
+ isAutoFill: false,
983
+ isReadOnly: false,
984
+ mappedObject: null,
985
+ mappedField: null
986
+ }
987
+ ],
988
+ actions: [
989
+ {
990
+ id: 1,
991
+ name: "Email",
992
+ description: null,
993
+ type: "lead.addutmtags",
994
+ order: 1,
995
+ properties: [
996
+ ]
997
+ },
998
+ {
999
+ id: 2,
1000
+ name: "THank You Notif 1",
1001
+ description: null,
1002
+ type: "email.send.user",
1003
+ order: 2,
1004
+ properties: {
1005
+ useremail: {
1006
+ email: "2"
1007
+ },
1008
+ user_id: [
1009
+ 1
1010
+ ]
1011
+ }
1012
+ },
1013
+ {
1014
+ id: 3,
1015
+ name: "Registered +10 (HOT)",
1016
+ description: null,
1017
+ type: "lead.changetags",
1018
+ order: 3,
1019
+ properties: {
1020
+ add_tags: [
1021
+ "HOT"
1022
+ ],
1023
+ remove_tags: [
1024
+ ]
1025
+ }
1026
+ }
1027
+ ],
1028
+ postAction: "message",
1029
+ postActionProperty: "Thanks for your submission. An email will be sent to you shortly.",
1030
+ formType: "campaign"
1031
+ },
1032
+ {
1033
+ id: 2,
1034
+ name: "second form",
1035
+ alias: "second_for",
1036
+ description: null,
1037
+ isPublished: true,
1038
+ fields: [
1039
+ {
1040
+ id: 4,
1041
+ label: "Name",
1042
+ showLabel: false,
1043
+ alias: "f_name",
1044
+ type: "text",
1045
+ defaultValue: null,
1046
+ isRequired: true,
1047
+ validationMessage: "this field is required",
1048
+ helpMessage: null,
1049
+ order: 1,
1050
+ properties: {
1051
+ placeholder: "your first name"
1052
+ },
1053
+ validation: [
1054
+ ],
1055
+ parent: null,
1056
+ conditions: [
1057
+ ],
1058
+ labelAttributes: null,
1059
+ inputAttributes: null,
1060
+ containerAttributes: null,
1061
+ leadField: "firstname",
1062
+ saveResult: true,
1063
+ isAutoFill: false,
1064
+ isReadOnly: false,
1065
+ mappedObject: "contact",
1066
+ mappedField: "firstname"
1067
+ },
1068
+ {
1069
+ id: 5,
1070
+ label: "Email",
1071
+ showLabel: true,
1072
+ alias: "email",
1073
+ type: "email",
1074
+ defaultValue: null,
1075
+ isRequired: true,
1076
+ validationMessage: "this is a required field",
1077
+ helpMessage: null,
1078
+ order: 2,
1079
+ properties: {
1080
+ placeholder: "email"
1081
+ },
1082
+ validation: [
1083
+ ],
1084
+ parent: null,
1085
+ conditions: [
1086
+ ],
1087
+ labelAttributes: null,
1088
+ inputAttributes: null,
1089
+ containerAttributes: null,
1090
+ leadField: "email",
1091
+ saveResult: true,
1092
+ isAutoFill: false,
1093
+ isReadOnly: false,
1094
+ mappedObject: "contact",
1095
+ mappedField: "email"
1096
+ },
1097
+ {
1098
+ id: 6,
1099
+ label: "Message",
1100
+ showLabel: false,
1101
+ alias: "f_message",
1102
+ type: "textarea",
1103
+ defaultValue: null,
1104
+ isRequired: true,
1105
+ validationMessage: "we need your message",
1106
+ helpMessage: null,
1107
+ order: 3,
1108
+ properties: [
1109
+ ],
1110
+ validation: [
1111
+ ],
1112
+ parent: null,
1113
+ conditions: [
1114
+ ],
1115
+ labelAttributes: null,
1116
+ inputAttributes: null,
1117
+ containerAttributes: null,
1118
+ leadField: "companyaddress1",
1119
+ saveResult: true,
1120
+ isAutoFill: false,
1121
+ isReadOnly: false,
1122
+ mappedObject: "company",
1123
+ mappedField: "companyaddress1"
1124
+ },
1125
+ {
1126
+ id: 7,
1127
+ label: "Submit",
1128
+ showLabel: true,
1129
+ alias: "submit",
1130
+ type: "button",
1131
+ defaultValue: null,
1132
+ isRequired: false,
1133
+ validationMessage: null,
1134
+ helpMessage: null,
1135
+ order: 4,
1136
+ properties: [
1137
+ ],
1138
+ validation: [
1139
+ ],
1140
+ parent: null,
1141
+ conditions: [
1142
+ ],
1143
+ labelAttributes: null,
1144
+ inputAttributes: "class=\"btn btn-ghost\"",
1145
+ containerAttributes: null,
1146
+ leadField: null,
1147
+ saveResult: true,
1148
+ isAutoFill: false,
1149
+ isReadOnly: false,
1150
+ mappedObject: null,
1151
+ mappedField: null
1152
+ }
1153
+ ],
1154
+ actions: [
1155
+ ],
1156
+ postAction: "message",
1157
+ postActionProperty: "Great, you have made it!",
1158
+ formType: "standalone"
1159
+ },
1160
+ {
1161
+ id: 1,
1162
+ name: "Simple form",
1163
+ alias: "simple_for",
1164
+ description: null,
1165
+ isPublished: true,
1166
+ fields: [
1167
+ {
1168
+ id: 1,
1169
+ label: "Name",
1170
+ showLabel: false,
1171
+ alias: "f_name",
1172
+ type: "text",
1173
+ defaultValue: null,
1174
+ isRequired: true,
1175
+ validationMessage: "This field is required",
1176
+ helpMessage: null,
1177
+ order: 1,
1178
+ properties: {
1179
+ placeholder: "Your name"
1180
+ },
1181
+ validation: [
1182
+ ],
1183
+ parent: null,
1184
+ conditions: [
1185
+ ],
1186
+ labelAttributes: null,
1187
+ inputAttributes: null,
1188
+ containerAttributes: null,
1189
+ leadField: "firstname",
1190
+ saveResult: true,
1191
+ isAutoFill: false,
1192
+ isReadOnly: false,
1193
+ mappedObject: "contact",
1194
+ mappedField: "firstname"
1195
+ },
1196
+ {
1197
+ id: 2,
1198
+ label: "EMail",
1199
+ showLabel: false,
1200
+ alias: "email",
1201
+ type: "email",
1202
+ defaultValue: null,
1203
+ isRequired: true,
1204
+ validationMessage: "This field is required",
1205
+ helpMessage: null,
1206
+ order: 2,
1207
+ properties: {
1208
+ placeholder: "Your email"
1209
+ },
1210
+ validation: [
1211
+ ],
1212
+ parent: null,
1213
+ conditions: [
1214
+ ],
1215
+ labelAttributes: null,
1216
+ inputAttributes: null,
1217
+ containerAttributes: null,
1218
+ leadField: "email",
1219
+ saveResult: true,
1220
+ isAutoFill: false,
1221
+ isReadOnly: false,
1222
+ mappedObject: "contact",
1223
+ mappedField: "email"
1224
+ },
1225
+ {
1226
+ id: 3,
1227
+ label: "Submit",
1228
+ showLabel: true,
1229
+ alias: "submit",
1230
+ type: "button",
1231
+ defaultValue: null,
1232
+ isRequired: false,
1233
+ validationMessage: null,
1234
+ helpMessage: null,
1235
+ order: 3,
1236
+ properties: [
1237
+ ],
1238
+ validation: [
1239
+ ],
1240
+ parent: null,
1241
+ conditions: [
1242
+ ],
1243
+ labelAttributes: null,
1244
+ inputAttributes: "class=\"btn btn-ghost\"",
1245
+ containerAttributes: null,
1246
+ leadField: null,
1247
+ saveResult: true,
1248
+ isAutoFill: false,
1249
+ isReadOnly: false,
1250
+ mappedObject: null,
1251
+ mappedField: null
1252
+ }
1253
+ ],
1254
+ actions: [
1255
+ ],
1256
+ postAction: "redirect",
1257
+ postActionProperty: "/mautic-test",
1258
+ formType: "standalone"
1259
+ }
1260
+ ];
1261
+ var mauticFormsData = {
1262
+ forms: forms
1263
+ };
1264
+
1265
+ // @ts-nocheck
1266
+ // Import the generated Mautic forms data
1267
+ // Create the data store
1268
+ const mauticData = {
1269
+ forms: mauticFormsData.forms
1270
+ };
1271
+ const getFormById = (id) => mauticData.forms.find(form => form.id === id);
1272
+
1273
+ /**
1274
+ * Integration Configuration
1275
+ * Centralized configuration for all third-party integrations
1276
+ */
1277
+ function envBool(key, defaultValue) {
1278
+ const v = getEnv(key);
1279
+ if (v === undefined || v === '')
1280
+ return defaultValue;
1281
+ const lower = v.toLowerCase();
1282
+ if (lower === 'false' || lower === '0' || lower === 'no')
1283
+ return false;
1284
+ if (lower === 'true' || lower === '1' || lower === 'yes')
1285
+ return true;
1286
+ return defaultValue;
1287
+ }
1288
+ /**
1289
+ * Get integration configuration with environment variable fallbacks
1290
+ */
1291
+ function getIntegrationConfig() {
1292
+ isDevEnvironment();
1293
+ return {
1294
+ wordpress: {
1295
+ enabled: true,
1296
+ apiUrl: getEnv('VITE_WORDPRESS_API_URL') || '',
1297
+ authMode: getEnv('VITE_AUTH_MODE') || 'direct',
1298
+ },
1299
+ supabase: {
1300
+ enabled: getEnv('VITE_AUTH_MODE') === 'supabase_proxy',
1301
+ url: getEnv('VITE_SUPABASE_URL') || '',
1302
+ anonKey: getEnv('VITE_SUPABASE_ANON_KEY') || '',
1303
+ serviceRoleKey: getEnv('VITE_SUPABASE_SERVICE_ROLE_KEY'),
1304
+ },
1305
+ gravityForms: {
1306
+ enabled: !!(getEnv('VITE_CLOUDFLARE_WORKER_URL') || getEnv('VITE_WORDPRESS_API_URL')),
1307
+ url: getEnv('VITE_WORDPRESS_API_URL'),
1308
+ proxyUrl: getEnv('VITE_CLOUDFLARE_WORKER_URL'),
1309
+ consumerKey: getEnv('VITE_GF_CONSUMER_KEY'),
1310
+ consumerSecret: getEnv('VITE_GF_CONSUMER_SECRET'),
1311
+ forms: {
1312
+ 'contact': {
1313
+ name: 'Contact Form',
1314
+ type: 'contact',
1315
+ successMessage: 'Thank you for your message. We\'ll get back to you soon!',
1316
+ },
1317
+ 'newsletter': {
1318
+ name: 'Newsletter Signup',
1319
+ type: 'newsletter',
1320
+ successMessage: 'Thank you for subscribing to our newsletter!',
1321
+ },
1322
+ 'support': {
1323
+ name: 'Support Request',
1324
+ type: 'support',
1325
+ successMessage: 'Your support request has been submitted successfully.',
1326
+ },
1327
+ },
1328
+ },
1329
+ mautic: {
1330
+ enabled: !!(getEnv('VITE_MAUTIC_PROXY_URL') || getEnv('VITE_MAUTIC_URL')),
1331
+ url: getEnv('VITE_MAUTIC_URL') || '',
1332
+ proxyUrl: getEnv('VITE_MAUTIC_PROXY_URL'),
1333
+ forms: {
1334
+ '1': {
1335
+ name: 'Newsletter Signup',
1336
+ type: 'newsletter',
1337
+ successMessage: 'Thank you for subscribing to our newsletter!',
1338
+ postAction: 'message',
1339
+ postActionProperty: 'Thank you for your submission!'
1340
+ },
1341
+ '2': {
1342
+ name: 'Contact Form',
1343
+ type: 'contact',
1344
+ successMessage: 'Thank you for contacting us! We\'ll get back to you soon.',
1345
+ postAction: 'message',
1346
+ postActionProperty: 'Thank you for your message!'
1347
+ },
1348
+ '3': {
1349
+ name: 'Lead Capture',
1350
+ type: 'lead',
1351
+ successMessage: 'Thank you for your interest! We\'ll be in touch.',
1352
+ postAction: 'message',
1353
+ postActionProperty: 'Thank you for your submission!'
1354
+ }
1355
+ }
1356
+ },
1357
+ phplist: {
1358
+ enabled: !!(getEnv('VITE_PHPLIST_URL') || getEnv('PHPLIST_URL')),
1359
+ url: getEnv('VITE_PHPLIST_URL') || getEnv('PHPLIST_URL'),
1360
+ proxyUrl: getEnv('VITE_PHPLIST_PROXY_URL') || getEnv('PHPLIST_PROXY_URL'),
1361
+ listId: parseInt(getEnv('VITE_PHPLIST_LIST_ID') || getEnv('PHPLIST_LIST_ID') || '0', 10) || undefined,
1362
+ subscribePageIds: (getEnv('VITE_PHPLIST_SUBSCRIBE_PAGE_IDS') || getEnv('PHPLIST_SUBSCRIBE_PAGE_IDS') || '')
1363
+ .split(',')
1364
+ .map((s) => parseInt(s.trim(), 10))
1365
+ .filter((n) => !Number.isNaN(n)),
1366
+ newsletterRouteBase: getEnv('VITE_PHPLIST_NEWSLETTER_ROUTE_BASE') || '/newsletters',
1367
+ },
1368
+ suiteCRM: {
1369
+ enabled: !!(getEnv('VITE_SUITECRM_URL') && getEnv('VITE_SUITECRM_CLIENT_ID') && getEnv('VITE_SUITECRM_CLIENT_SECRET')),
1370
+ url: getEnv('VITE_SUITECRM_URL'),
1371
+ proxyUrl: getEnv('VITE_SUITECRM_PROXY_URL'),
1372
+ appId: undefined,
1373
+ workerSecret: undefined,
1374
+ oauth2: {
1375
+ clientId: getEnv('VITE_SUITECRM_CLIENT_ID'),
1376
+ clientSecret: getEnv('VITE_SUITECRM_CLIENT_SECRET'),
1377
+ username: getEnv('VITE_SUITECRM_USERNAME'),
1378
+ password: getEnv('VITE_SUITECRM_PASSWORD'),
1379
+ },
1380
+ },
1381
+ chatwoot: {
1382
+ enabled: !!(getEnv('VITE_CHATWOOT_WEBSITE_TOKEN') && getEnv('VITE_CHATWOOT_BASE_URL')),
1383
+ websiteToken: getEnv('VITE_CHATWOOT_WEBSITE_TOKEN') || '',
1384
+ baseUrl: getEnv('VITE_CHATWOOT_BASE_URL') || '',
1385
+ locale: 'en',
1386
+ type: 'standard',
1387
+ launcherTitle: 'Chat',
1388
+ hideMessageBubble: false,
1389
+ position: 'right',
1390
+ showPopoutButton: false,
1391
+ },
1392
+ analytics: {
1393
+ googleAnalytics: { enabled: false },
1394
+ googleTagManager: { enabled: false },
1395
+ facebookPixel: { enabled: false },
1396
+ linkedinInsight: { enabled: false },
1397
+ },
1398
+ seo: (() => {
1399
+ const opt = (key) => {
1400
+ const v = getEnv(key);
1401
+ if (v === undefined || v === '')
1402
+ return undefined;
1403
+ const t = v.trim();
1404
+ return t || undefined;
1405
+ };
1406
+ const siteUrl = (getEnv('VITE_SEO_SITE_URL') || '').replace(/\/+$/, '').trim();
1407
+ const siteName = (getEnv('VITE_SEO_SITE_NAME') || '').trim();
1408
+ const defaultTitle = (getEnv('VITE_SEO_DEFAULT_TITLE') || '').trim() || siteName || '';
1409
+ return {
1410
+ defaultTitle,
1411
+ defaultDescription: (getEnv('VITE_SEO_DEFAULT_DESCRIPTION') || '').trim(),
1412
+ defaultKeywords: opt('VITE_SEO_DEFAULT_KEYWORDS'),
1413
+ defaultImage: (getEnv('VITE_SEO_DEFAULT_OG_IMAGE') || '').trim(),
1414
+ siteName,
1415
+ siteUrl,
1416
+ twitterHandle: opt('VITE_SEO_TWITTER_SITE'),
1417
+ facebookAppId: opt('VITE_SEO_FACEBOOK_APP_ID'),
1418
+ googleSiteVerification: opt('VITE_SEO_GOOGLE_SITE_VERIFICATION'),
1419
+ bingSiteVerification: opt('VITE_SEO_BING_SITE_VERIFICATION'),
1420
+ };
1421
+ })(),
1422
+ performance: {
1423
+ enableLazyLoading: envBool('VITE_PERF_LAZY_LOADING', true),
1424
+ enableImageOptimization: envBool('VITE_PERF_IMAGE_OPTIMIZATION', true),
1425
+ enableCodeSplitting: envBool('VITE_PERF_CODE_SPLITTING', true),
1426
+ enableServiceWorker: envBool('VITE_PERF_SERVICE_WORKER', false),
1427
+ enableCaching: envBool('VITE_PERF_CACHING', true),
1428
+ }
1429
+ };
1430
+ }
1431
+
1432
+ const MauticForm = ({ formId, title, description, className = '' }) => {
1433
+ // Get form from static data
1434
+ const form = getFormById(parseInt(formId));
1435
+ // Get form configuration from integrations config
1436
+ const integrationConfig = getIntegrationConfig();
1437
+ const formConfig = integrationConfig.mautic.forms[formId];
1438
+ // Debug logging in development
1439
+ if (undefined.DEV && form) {
1440
+ console.log('MauticForm Debug:', {
1441
+ formId,
1442
+ formPostAction: form.postAction,
1443
+ formPostActionProperty: form.postActionProperty,
1444
+ configPostAction: formConfig?.postAction,
1445
+ configPostActionProperty: formConfig?.postActionProperty,
1446
+ finalPostAction: form.postAction || formConfig?.postAction || 'message',
1447
+ finalPostActionProperty: form.postActionProperty || formConfig?.postActionProperty || 'Thank you for your submission!'
1448
+ });
1449
+ }
1450
+ // Use the package component
1451
+ return (jsxRuntime.jsx(madapter.MauticForm, { formId: formId, title: title, description: description, className: className, form: form, onSuccess: (data) => {
1452
+ console.log('Form submitted successfully:', data);
1453
+ }, onError: (error) => {
1454
+ console.error('Form submission error:', error);
1455
+ } }));
1456
+ };
1457
+
1458
+ const { HelmetProvider } = helmetAsync;
1459
+ const gravityFormsConfig = () => ({
1460
+ apiUrl: undefined.VITE_WORDPRESS_API_URL,
1461
+ timeout: 30000,
1462
+ proxyEndpoint: withBasePath('/api/gravity-forms-submit'),
1463
+ });
1464
+ const InlineGravityForm = ({ formId }) => (jsxRuntime.jsx(StaticGravityForm, { formId: formId, config: gravityFormsConfig() }));
1465
+ const ContentPopup = ({ buttonText, title, children }) => {
1466
+ const [isOpen, setIsOpen] = react.useState(false);
1467
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("button", { type: "button", onClick: () => setIsOpen(true), "data-digivalt-popup-trigger": true, children: buttonText }), isOpen && (jsxRuntime.jsx("div", { role: "dialog", "aria-modal": "true", "aria-label": typeof title === 'string' ? title : undefined, "data-digivalt-popup": true, children: jsxRuntime.jsxs("div", { "data-digivalt-popup-content": true, children: [jsxRuntime.jsxs("header", { children: [jsxRuntime.jsx("h2", { children: title }), jsxRuntime.jsx("button", { type: "button", onClick: () => setIsOpen(false), "aria-label": "Close", children: "\u00D7" })] }), children] }) }))] }));
1468
+ };
1469
+ /**
1470
+ * Registry for WordPress page-body blocks and DigiValt integration shortcodes.
1471
+ * Header and footer template parts deliberately remain app-owned.
1472
+ */
1473
+ function createContentRegistry(themePalette) {
1474
+ const colorMapper = themePalette
1475
+ ? (colorName) => colorName ? themePalette[colorName] || null : null
1476
+ : undefined;
1477
+ const registry = wparser.createEnhancedRegistry([], undefined, colorMapper);
1478
+ registry.renderers['gravityforms/form'] = ({ block }) => {
1479
+ const attrs = block?.attributes || {};
1480
+ const formId = attrs.formId || attrs.id || attrs.form_id || '1';
1481
+ return jsxRuntime.jsx(InlineGravityForm, { formId: formId });
1482
+ };
1483
+ registry.shortcodes = {
1484
+ ...registry.shortcodes,
1485
+ ...madapter.getMauticShortcodeHandlers({
1486
+ renderForm: ({ formId, title, description }) => (jsxRuntime.jsx(MauticForm, { formId: formId, title: title, description: description })),
1487
+ }),
1488
+ ...plister.getPhplistShortcodeHandlers(),
1489
+ gf_embed: (attrs) => (jsxRuntime.jsx(InlineGravityForm, { formId: attrs.id || attrs.formId || '1' })),
1490
+ gform: (attrs) => (jsxRuntime.jsx(InlineGravityForm, { formId: attrs.form_id || attrs.id || attrs.formId || '1' })),
1491
+ popupbtn_gf: (attrs) => (jsxRuntime.jsx(ContentPopup, { buttonText: attrs.text || attrs.buttonText || 'Submit', title: attrs.title || 'Contact Form', children: jsxRuntime.jsx(InlineGravityForm, { formId: attrs.id || attrs.formId || '1' }) })),
1492
+ popupgform: (attrs) => (jsxRuntime.jsx(ContentPopup, { buttonText: attrs.text || attrs.buttonText || 'Submit', title: attrs.title || 'Contact Form', children: jsxRuntime.jsx(InlineGravityForm, { formId: attrs.form_id || attrs.id || attrs.formId || '1' }) })),
1493
+ popupbtn_mautic: (attrs) => {
1494
+ const formId = attrs.id || attrs.formId || '1';
1495
+ return (jsxRuntime.jsx(ContentPopup, { buttonText: attrs.text || attrs.buttonText || 'Submit', title: attrs.title || attrs.popupTitle || 'Contact Form', children: jsxRuntime.jsx(MauticForm, { formId: String(formId) }) }));
1496
+ },
1497
+ };
1498
+ return registry;
1499
+ }
1500
+ /** Load and render one WordPress page body. */
1501
+ const DigiValtWpPage = ({ slug, className, dataPath = '/wordpress-data.json', themePalette, }) => {
1502
+ const [page, setPage] = react.useState(() => getWordPressPageBySlug(slug));
1503
+ const registry = react.useMemo(() => createContentRegistry(themePalette), [themePalette]);
1504
+ react.useEffect(() => {
1505
+ let active = true;
1506
+ loadWordPressData(dataPath).then(() => {
1507
+ if (active)
1508
+ setPage(getWordPressPageBySlug(slug));
1509
+ });
1510
+ return () => {
1511
+ active = false;
1512
+ };
1513
+ }, [dataPath, slug]);
1514
+ return page && Array.isArray(page.blocks)
1515
+ ? jsxRuntime.jsx(wparser.WPPage, { page: page, registry: registry, className: className })
1516
+ : null;
1517
+ };
1518
+ const DigiValtProviders = ({ children, queryClient }) => {
1519
+ const content = queryClient
1520
+ ? jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: queryClient, children: children })
1521
+ : children;
1522
+ return jsxRuntime.jsx(HelmetProvider, { children: content });
1523
+ };
1524
+
1525
+ exports.DigiValtProviders = DigiValtProviders;
1526
+ exports.DigiValtWpPage = DigiValtWpPage;
1527
+ exports.createContentRegistry = createContentRegistry;
1528
+ //# sourceMappingURL=registry.cjs.map