{"version":3,"file":"EmbeddedForm.DwoP11TU.mjs","names":["useRef","useState"],"sources":["https:/framerusercontent.com/modules/vAwMWEL85PUeTaW18lyc/8Par8MYwu0i7Yv1dK61q/EmbeddedForm.js"],"sourcesContent":["import{jsx as _jsx,jsxs as _jsxs}from\"react/jsx-runtime\";import{useEffect,useRef,useState}from\"react\";import{addPropertyControls,ControlType,useIsStaticRenderer}from\"framer\";// Measurement contract: every conversion event carries `event_city`. It is the\n// ONLY discriminator between editions, because the HubSpot forms carry no event\n// field of their own -- so it must be a prop, never a constant, or a shared\n// component reports every city as the one it was written for.\n// HubSpot free portal 146402008 (\"We Love GenAI\"), EU data residency.\nconst HUBSPOT_PORTAL_ID=\"146402008\";const HUBSPOT_REGION=\"eu1\";// `| undefined` is load-bearing: without it the `if (scriptPromises[src])`\n// guard below is typed as always-true, because noUncheckedIndexedAccess is off.\nconst scriptPromises={};// Vendor embed scripts are strictly necessary for the form the visitor asked\n// for, so they are not consent-gated. Consent Mode governs what gtag stores.\nfunction loadScript(src){if(typeof document===\"undefined\")return Promise.resolve();if(scriptPromises[src])return scriptPromises[src];scriptPromises[src]=new Promise(resolve=>{const existing=document.querySelector(`script[src=\"${src}\"]`);if(existing){resolve();return;}const script=document.createElement(\"script\");script.src=src;script.async=true;script.onload=()=>resolve();// Resolve on error too: a dead script must not wedge the component.\nscript.onerror=()=>resolve();document.head.appendChild(script);});return scriptPromises[src];}// Never forward field values (email, name) to GA4 — that is PII and violates\n// the GA4 terms. Only ids and classifiers go out.\nfunction fireEvent(name,params){if(typeof window===\"undefined\")return;const gtag=window.gtag;if(typeof gtag!==\"function\")return;gtag(\"event\",name,params);}/**\n * Embedded Form\n *\n * Renders a Tally or HubSpot form inline on our own domain and emits the\n * Funnel events: `form_open` when the form is opened and\n * `generate_lead` when it is submitted.\n *\n * This is deliberately a code component rather than Framer's Embed component.\n * Embed renders inside an iframe, and HubSpot's v4 submit signal is a DOM\n * CustomEvent on `window`, which cannot cross an iframe boundary at all.\n *\n * @framerIntrinsicWidth 640\n * @framerIntrinsicHeight 600\n *\n * @framerSupportedLayoutWidth any-prefer-fixed\n * @framerSupportedLayoutHeight any-prefer-fixed\n */export default function EmbeddedForm(props){const{eventCity=\"berlin\",formId=\"\",formType=\"award\",sourceSection=\"\",minHeight=600}=props;// Framer can hand back the option *title* (\"Tally\") rather than the\n// option value, so normalise before comparing. Getting this wrong fails\n// silently: the wrong branch renders and no conversion ever fires.\nconst provider=String(props.provider??\"tally\").toLowerCase()===\"hubspot\"?\"hubspot\":\"tally\";const isStatic=useIsStaticRenderer();const containerRef=useRef(null);const openFiredRef=useRef(false);const leadFiredRef=useRef(false);const[failed,setFailed]=useState(false);const params={event_city:String(eventCity||\"berlin\").toLowerCase(),form_type:formType,source_section:sourceSection||`/${formType}`,form_provider:provider,form_id:formId};// `form_open` = the visitor opened the form. Not a key event.\n// NOT `form_start` either: GA4 Enhanced Measurement auto-collects that\n// name for native form-field interactions, so reusing it would mix two\n// different meanings under one event again.\n// Deliberately NOT `begin_checkout`: that name is reserved for TICKET\n// checkout (the click out to Luma). Sharing one name made 59 form opens\n// read as ticket intent and left the ticket funnel with no signal at all.\nuseEffect(()=>{if(isStatic||!formId||openFiredRef.current)return;openFiredRef.current=true;fireEvent(\"form_open\",params);},[isStatic,formId,formType,provider,sourceSection,eventCity]);// `generate_lead` = the visitor completed it. This IS the conversion.\n// Both HubSpot APIs are registered because the portal's form version is\n// not guaranteed: v4 emits a DOM CustomEvent, legacy v2 posts a message.\n// They are mutually harmless, and the ref guard keeps it to one event.\nuseEffect(()=>{if(isStatic||typeof window===\"undefined\")return;function convert(){if(leadFiredRef.current)return;leadFiredRef.current=true;fireEvent(\"generate_lead\",params);}function onHubspotV4(){convert();}function onMessage(event){const data=event.data;// Tally delivers its events as a JSON *string*, so guard the type\n// before parsing or an unrelated script's object message throws.\nif(provider===\"tally\"&&typeof data===\"string\"){if(data.indexOf(\"Tally.FormSubmitted\")===-1)return;try{const parsed=JSON.parse(data);if(parsed?.event===\"Tally.FormSubmitted\")convert();}catch{// Not a Tally payload; ignore.\n}return;}// HubSpot legacy (v2) embed.\nif(provider===\"hubspot\"&&data&&typeof data===\"object\"&&data.type===\"hsFormCallback\"&&data.eventName===\"onFormSubmitted\"){convert();}}window.addEventListener(\"message\",onMessage);if(provider===\"hubspot\"){window.addEventListener(\"hs-form-event:on-submission:success\",onHubspotV4);}return()=>{window.removeEventListener(\"message\",onMessage);if(provider===\"hubspot\"){window.removeEventListener(\"hs-form-event:on-submission:success\",onHubspotV4);}};},[isStatic,provider,formId,formType,sourceSection,eventCity]);// Mount the vendor embed.\nuseEffect(()=>{if(isStatic||!formId)return;let cancelled=false;if(provider===\"tally\"){loadScript(\"https://tally.so/widgets/embed.js\").then(()=>{if(cancelled)return;const tally=window.Tally;if(tally?.loadEmbeds){tally.loadEmbeds();}else{setFailed(true);}});}else{loadScript(`https://js-${HUBSPOT_REGION}.hsforms.net/forms/embed/${HUBSPOT_PORTAL_ID}.js`);}return()=>{cancelled=true;};},[isStatic,provider,formId]);const rootStyle={...props.style,position:\"relative\",width:\"100%\",minHeight};// On the Framer canvas, show a labelled placeholder instead of loading\n// third-party scripts into the editor.\nif(isStatic){return /*#__PURE__*/_jsx(\"div\",{style:{...rootStyle,display:\"flex\",alignItems:\"center\",justifyContent:\"center\",background:\"#F5F5F5\",border:\"1px dashed #CCCCCC\",borderRadius:8,padding:24,boxSizing:\"border-box\",color:\"#666666\",fontSize:14,textAlign:\"center\"},children:formId?`${provider===\"tally\"?\"Tally\":\"HubSpot\"} form “${formId}” — tracked as ${formType}`:\"Set a form ID in the properties panel\"});}if(!formId)return /*#__PURE__*/_jsx(\"div\",{style:rootStyle});return /*#__PURE__*/_jsxs(\"div\",{ref:containerRef,style:rootStyle,children:[provider===\"tally\"?/*#__PURE__*/_jsx(\"iframe\",{// eager: the form IS the page content, deferring it paints blank\nloading:\"eager\",\"data-tally-src\":`https://tally.so/embed/${formId}?alignLeft=1&hideTitle=1&transparentBackground=1&dynamicHeight=1`,width:\"100%\",height:minHeight,frameBorder:0,marginHeight:0,marginWidth:0,title:`GenAI Berlin form: ${formType}`,style:{border:0,width:\"100%\"}}):/*#__PURE__*/_jsx(\"div\",{className:\"hs-form-frame\",\"data-region\":HUBSPOT_REGION,\"data-portal-id\":HUBSPOT_PORTAL_ID,\"data-form-id\":formId}),failed&&/*#__PURE__*/_jsx(\"noscript\",{children:\"The form could not be loaded.\"})]});}addPropertyControls(EmbeddedForm,{eventCity:{type:ControlType.Enum,title:\"Event City\",options:[\"berlin\",\"london\",\"zurich\"],optionTitles:[\"Berlin\",\"London\",\"Zurich\"],defaultValue:\"berlin\",description:\"Sent as event_city. The only thing separating editions in GA4.\"},provider:{type:ControlType.Enum,title:\"Provider\",options:[\"tally\",\"hubspot\"],optionTitles:[\"Tally\",\"HubSpot\"],defaultValue:\"tally\",displaySegmentedControl:true},formId:{type:ControlType.String,title:\"Form ID\",defaultValue:\"\",placeholder:\"Tally id, or HubSpot form GUID\",description:\"HubSpot needs the form GUID from the form editor — not the share-link token.\"},formType:{type:ControlType.String,title:\"Form Type\",defaultValue:\"award\",placeholder:\"award, partner, speaker…\",description:\"Sent as form_type on the GA4 conversion.\"},sourceSection:{type:ControlType.String,title:\"Source Section\",defaultValue:\"\",placeholder:\"Defaults to /<form type>\"},minHeight:{type:ControlType.Number,title:\"Min Height\",defaultValue:600,min:200,max:2e3,step:20,unit:\"px\"}});\nexport const __FramerMetadata__ = {\"exports\":{\"default\":{\"type\":\"reactComponent\",\"name\":\"EmbeddedForm\",\"slots\":[],\"annotations\":{\"framerSupportedLayoutWidth\":\"any-prefer-fixed\",\"framerContractVersion\":\"1\",\"framerIntrinsicWidth\":\"640\",\"framerSupportedLayoutHeight\":\"any-prefer-fixed\",\"framerIntrinsicHeight\":\"600\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./EmbeddedForm.map"],"mappings":"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"}