{"version":3,"file":"BlockPersonalEmails.Cg4moVpr.mjs","names":["useState"],"sources":["https:/framerusercontent.com/modules/vj7bFUjvEQFgEzNBkdoG/vf3CKm378wlVcBk7IhSU/createStore.js","https:/framer.com/m/framer/store.js@^1.0.0","https:/framerusercontent.com/modules/82g7G8AHIFT1rXx7CjsE/nXuKDl9BEkoiouzdKj9K/BlockPersonalEmails.js"],"sourcesContent":["import{useState,useEffect}from\"react\";import{Data,useObserveData}from\"framer\";export function createStore(state1){// Use Data so that a Preview reload resets the state\nconst dataStore=Data({state:Object.freeze({...state1})});// Create a set function that updates the state\nconst setDataStore=newState=>{// If the state is an object, make sure we copy it\nif(typeof newState===\"function\"){newState=newState(dataStore.state);}dataStore.state=Object.freeze({...dataStore.state,...newState});};// Store the initial state, copy the object if it's an object\nlet storeState=typeof state1===\"object\"?Object.freeze({...state1}):state1;// Keep a list of all the listeners, in the form of React hook setters\nconst storeSetters=new Set();// Create a set function that updates all the listeners / setters\nconst setStoreState=newState=>{// If the state is an object, make sure we copy it\nif(typeof newState===\"function\"){newState=newState(storeState);}storeState=typeof newState===\"object\"?Object.freeze({...storeState,...newState}):newState;// Update all the listeners / setters with the new value\nstoreSetters.forEach(setter=>setter(storeState));};// Create the actual hook based on everything above\nfunction useStore(){// Create the hook we are going to use as a listener\nconst[state,setState]=useState(storeState);// If we unmount the component using this hook, we need to remove the listener\n// @ts-ignore\nuseEffect(()=>{// But right now, we need to add the listener\nstoreSetters.add(setState);return()=>storeSetters.delete(setState);},[]);// If Data context exists, use Data, otherwise use vanilla React state\nif(useObserveData()===true){useObserveData();return[dataStore.state,setDataStore];}else{// Return the state and a function to update the central store\nreturn[state,setStoreState];}}return useStore;}\nexport const __FramerMetadata__ = {\"exports\":{\"createStore\":{\"type\":\"function\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./createStore.map","/*\n * createStore (framer/store@1.0.1)\n *\n * Learn More: https://www.framer.com/asset-urls\n */\n\nexport * from \"https://framerusercontent.com/modules/vj7bFUjvEQFgEzNBkdoG/vf3CKm378wlVcBk7IhSU/createStore.js\"\n","// BrixBlockNonWorkEmails.tsx\n//\n// BRIX Templates Work Email Validation for Framer\n// ----------------------------------------------------------------------------\n// Enforces \"work email only\" on native Framer forms by blocking personal\n// email providers like Gmail, Outlook, and Yahoo.\n//\n// Version: 1.0.0\n// Author: BRIX Templates\n//\n// Apply these overrides:\n//   - brixBlockNonWorkEmailsInput   → Email input layer\n//   - brixBlockNonWorkEmailsButton  → Submit button layer\n//   - brixBlockNonWorkEmailsError   → Error message Text layer\nimport{jsx as _jsx}from\"react/jsx-runtime\";import{forwardRef,useCallback,useEffect,useRef}from\"react\";import{createStore}from\"https://framer.com/m/framer/store.js@^1.0.0\";// -----------------------------\n// 1. Shared store across layers\n// -----------------------------\nconst useBrixBlockEmailStore=createStore({email:\"\",blocked:false,message:\"\",touched:false});// -----------------------------\n// 2. Blocked email domains\n// -----------------------------\n// Major global free email providers\nconst BRIX_BLOCKED_DOMAINS=new Set([// Google\n\"gmail.com\",\"googlemail.com\",// Microsoft\n\"outlook.com\",\"hotmail.com\",\"live.com\",\"msn.com\",// Yahoo\n\"yahoo.com\",\"yahoo.co.uk\",\"yahoo.co.in\",\"ymail.com\",// Apple\n\"icloud.com\",\"me.com\",\"mac.com\",// AOL\n\"aol.com\",// German providers\n\"gmx.com\",\"gmx.de\",\"web.de\",// Privacy-focused\n\"proton.me\",\"protonmail.com\",\"pm.me\",\"tuta.com\",\"tutanota.com\",// Other popular free providers\n\"zoho.com\",\"mail.com\",\"inbox.com\"]);// -----------------------------\n// 3. Helper functions\n// -----------------------------\nfunction normalizeEmail(value){return(value||\"\").trim().toLowerCase();}function extractDomain(email){const at=email.lastIndexOf(\"@\");if(at===-1)return\"\";return email.slice(at+1).trim().toLowerCase().replace(/\\.$/,\"\");}function looksEmailish(value){return/.+@.+\\..+/.test(value);}function isBlockedDomain(domain){if(!domain)return false;return BRIX_BLOCKED_DOMAINS.has(domain);}function computeValidation(email){const normalized=normalizeEmail(email);const domain=extractDomain(normalized);if(!domain)return{blocked:false,message:\"\"};if(isBlockedDomain(domain)){return{blocked:true,message:\"Please use a work email address (personal email providers are not accepted).\"};}return{blocked:false,message:\"\"};}function setNativeValidity(inputEl,email,blocked,message){if(!inputEl||typeof inputEl.setCustomValidity!==\"function\")return;if(!looksEmailish(email)){inputEl.setCustomValidity(\"\");return;}inputEl.setCustomValidity(blocked?message:\"\");}function mergeRefs(a,b){return node=>{b.current=node;if(typeof a===\"function\")a(node);else if(a&&typeof a===\"object\")a.current=node;};}// -----------------------------\n// 4. Overrides\n// -----------------------------\n// EMAIL INPUT\n// Attach to the email input field inside your Framer Form.\nexport function brixBlockNonWorkEmailsInput(Component){return /*#__PURE__*/forwardRef((props,ref)=>{const[store,setStore]=useBrixBlockEmailStore();const inputRef=useRef(null);const sync=useCallback(nextEmail=>{const{blocked,message}=computeValidation(nextEmail);setStore({email:nextEmail,blocked,message});setNativeValidity(inputRef.current,nextEmail,blocked,message);},[setStore]);// Initial sync + autofill guard\nuseEffect(()=>{const el=inputRef.current;if(!el)return;const initial=el.value??\"\";sync(initial);if(typeof window===\"undefined\")return;let last=el.value??\"\";const interval=window.setInterval(()=>{const now=el.value??\"\";if(now!==last){last=now;sync(now);}},200);const timeout=window.setTimeout(()=>{window.clearInterval(interval);},2e3);return()=>{window.clearInterval(interval);window.clearTimeout(timeout);};},[sync]);const handleChange=eventOrValue=>{const value=typeof eventOrValue===\"string\"?eventOrValue:eventOrValue?.target?.value??eventOrValue?.currentTarget?.value??\"\";setStore({touched:true});sync(value);if(typeof props.onChange===\"function\"){props.onChange(eventOrValue);}};const handleBlur=eventOrValue=>{setStore({touched:true});const value=typeof eventOrValue===\"string\"?eventOrValue:eventOrValue?.target?.value??eventOrValue?.currentTarget?.value??inputRef.current?.value??\"\";sync(value);if(typeof props.onBlur===\"function\"){props.onBlur(eventOrValue);}};return /*#__PURE__*/_jsx(Component,{...props,ref:mergeRefs(ref,inputRef),onChange:handleChange,onBlur:handleBlur});});}// SUBMIT BUTTON\n// Attach to the submit button inside the same Form.\nexport function brixBlockNonWorkEmailsButton(Component){return props=>{const[store]=useBrixBlockEmailStore();const shouldDisable=store.blocked;return /*#__PURE__*/_jsx(Component,{...props,disabled:shouldDisable||props.disabled,\"aria-disabled\":shouldDisable||props[\"aria-disabled\"],title:shouldDisable?store.message:props.title,style:{...props.style,opacity:shouldDisable?.5:props.style?.opacity,cursor:shouldDisable?\"not-allowed\":props.style?.cursor,pointerEvents:shouldDisable?\"none\":props.style?.pointerEvents}});};}// ERROR MESSAGE TEXT\n// Attach to a Text layer under the button that contains your \"work email only\" message.\nexport function brixBlockNonWorkEmailsError(Component){return props=>{const[store]=useBrixBlockEmailStore();const show=store.blocked&&(store.touched||store.email.length>0);return /*#__PURE__*/_jsx(Component,{...props,text:show?store.message:\"\",style:{...props.style,display:show?props.style?.display??\"block\":\"none\"}});};}/*3 - Connecting the overrides to your Framer form\nWith the code in place, you need to connect each override to the correct form element.\n\nAttaching overrides to Framer form elements\nFollow these steps to wire everything together:\n\nSelect your Email input: Click on the email input field in your form\nApply the input override: In the right panel under Overrides, select brixBlockNonWorkEmailsInput from the dropdown\nSelect your Submit button: Click on the submit button\nApply the button override: Choose brixBlockNonWorkEmailsButton from the override dropdown\nSelect your error Text layer: Click on the text layer you created for error messages\nApply the message override: Select brixBlockNonWorkEmailsError\nHow To Apply The Code Overrides To The Framer Form Fields\nRemember that overrides only run in Preview mode and on your published site, not on the canvas. You won't see the validation working until you preview or publish.\n\nOptional: Adding Russian and Chinese consumer email providers to your Framer blocklist\nIf your business doesn't serve Russian or Chinese markets, you may want to block consumer email providers from those regions. These are separate from the core blocklist to give you control over regional filtering.*/// Russia & CIS consumer providers (Mail.ru Group, Yandex, Rambler, etc.)\nconst RUSSIA_CONSUMER_DOMAINS=new Set([\"mail.ru\",\"bk.ru\",\"inbox.ru\",\"list.ru\",\"rambler.ru\",\"rambler.ua\",\"yandex.ru\",\"yandex.com\",\"yandex.ua\",\"yandex.kz\",\"yandex.by\"]);// China consumer providers (NetEase, QQ, Sina, etc.)\nconst CHINA_CONSUMER_DOMAINS=new Set([\"qq.com\",\"vip.qq.com\",\"foxmail.com\",\"163.com\",\"126.com\",\"yeah.net\",\"sina.com\",\"sina.cn\",\"sohu.com\",\"139.com\"]);\nexport const __FramerMetadata__ = {\"exports\":{\"brixBlockNonWorkEmailsError\":{\"type\":\"reactHoc\",\"name\":\"brixBlockNonWorkEmailsError\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"brixBlockNonWorkEmailsButton\":{\"type\":\"reactHoc\",\"name\":\"brixBlockNonWorkEmailsButton\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"brixBlockNonWorkEmailsInput\":{\"type\":\"reactHoc\",\"name\":\"brixBlockNonWorkEmailsInput\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./BlockPersonalEmails.map"],"mappings":"oLAA8E,SAAgB,EAAY,EAAO,CACjH,IAAM,EAAU,EAAK,CAAC,MAAM,OAAO,OAAO,CAAC,GAAG,CAAM,CAAC,CAAC,CAAC,EACjD,EAAa,GAAU,CAC1B,OAAO,GAAW,aAAY,EAAS,EAAS,EAAU,KAAK,GAAG,EAAU,MAAM,OAAO,OAAO,CAAC,GAAG,EAAU,MAAM,GAAG,CAAQ,CAAC,CAAE,EACjI,EAAW,OAAO,GAAS,SAAS,OAAO,OAAO,CAAC,GAAG,CAAM,CAAC,EAAE,EAC7D,EAAa,IAAI,IACjB,EAAc,GAAU,CAC3B,OAAO,GAAW,aAAY,EAAS,EAAS,CAAU,GAAG,EAAW,OAAO,GAAW,SAAS,OAAO,OAAO,CAAC,GAAG,EAAW,GAAG,CAAQ,CAAC,EAAE,EACjJ,EAAa,QAAQ,GAAQ,EAAO,CAAU,CAAC,CAAE,EACjD,SAAS,GAAU,CACnB,GAAK,CAAC,EAAM,GAAUA,EAAS,CAAU,EAKzC,OAHA,OACA,EAAa,IAAI,CAAQ,MAAY,EAAa,OAAO,CAAQ,GAAI,CAAC,CAAC,EACpE,EAAe,IAAI,IAAM,EAAe,EAAQ,CAAC,EAAU,MAAM,CAAY,GAC1E,CAAC,EAAM,CAAa,CAAG,CAAC,OAAO,CAAS,iBAfT,IAAwC,sBEwC7E,SAAgB,EAA6B,EAAU,CAAC,MAAO,IAAO,CAAC,GAAK,CAAC,GAAO,EAAuB,EAAQ,EAAc,EAAM,QAAQ,OAAoB,EAAK,EAAU,CAAC,GAAG,EAAM,SAAS,GAAe,EAAM,SAAS,gBAAgB,GAAe,EAAM,iBAAiB,MAAM,EAAc,EAAM,QAAQ,EAAM,MAAM,MAAM,CAAC,GAAG,EAAM,MAAM,QAAQ,EAAc,GAAG,EAAM,OAAO,QAAQ,OAAO,EAAc,cAAc,EAAM,OAAO,OAAO,cAAc,EAAc,OAAO,EAAM,OAAO,aAAa,CAAC,CAAC,CAAE,CAAE,uBA1B3d,IAA2D,IAAqE,EAGpK,EAAuB,EAAY,CAAC,MAAM,GAAG,QAAQ,GAAM,QAAQ,GAAG,QAAQ,EAAK,CAAC"}