{"version":3,"file":"forms-DbJz7y8Y.js","sources":["../../src/composables/forms.ts"],"sourcesContent":["import { computed, ref } from \"vue\"\nimport { initScriptTag } from \"./browser\"\n\n/**\n * password validation regex pattern\n * used with input type=\"password\" in the pattern attribute for html5 validation\n * exported as a raw string to support the escape backslash characters\n */\nexport const PasswordPattern = String.raw`(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*\\(\\)_+=\\-]).{8,}`\n\n/**\n * formats an array of strings into input fields options for radios, selects, checkboxes\n * @param options array of strings to format into input options\n */\nexport const arrayToOptions = (options: string[]) => {\n return options.map((o) => {\n return {\n label: o,\n value: o,\n }\n })\n}\n\n/**\n * maxDateToday is a valid date string for \"Today\" to help restict input type date fields\n * from allowing future date entries when they should be restricted to past dates.\n */\nexport const maxDateToday = new Date().toISOString().split(\"T\")[0]\n\n/**\n * minDateTomorrow returns a date string for \"Tomorrow\" to help restrict input type date fields\n * from allowing past date entries - including today - when they should be restricted to past dates.\n */\nexport const minDateTomorrow = () => {\n const d = new Date()\n d.setDate(new Date().getDate() + 1)\n\n return d.toISOString().split(\"T\")[0]\n}\n\nexport interface CaptchaRequest {\n captchaAction: string\n captchaResponse: string\n}\n\n/**\n * initCaptchaAssets loads the Google Captcha JS library\n * ensuring it is only loaded once.\n * https://developers.google.com/recaptcha/docs/v3#tips\n * https://web.dev/trusted-types/\n */\nconst initCaptchaAssets: () => Promise = (() => {\n let once: Promise | undefined\n\n const init = async (): Promise => {\n await initScriptTag(\n `https://www.google.com/recaptcha/api.js?render=${\n import.meta.env.VITE_APP_GOOGLE_CAPTCHA_KEY\n }&trustedtypes=true`\n )\n return await Promise.resolve(true)\n }\n\n return async () => {\n if (!once) {\n once = init()\n }\n\n return once\n }\n})()\n\n// https://developers.google.com/recaptcha/docs/v3\n// reCAPTCHA tokens expire after two minutes, and can only be verified once to prevent replay attacks.\n// make sure to call execute when the user takes the action rather than on page load.\nexport const useCaptcha = (action: string) => {\n let captcha: ReCaptchaV2.ReCaptcha | undefined = undefined\n const captchaReady = ref(false)\n const captchaRespToken = ref(\"\")\n\n initCaptchaAssets().then(() => {\n window.grecaptcha.ready(() => {\n captcha = window.grecaptcha\n captchaReady.value = true\n })\n })\n\n const captchaRequest = computed((): CaptchaRequest => {\n return {\n captchaAction: action,\n captchaResponse: captchaRespToken.value,\n }\n })\n\n const captchaExecute = async () => {\n if (captchaReady.value === false) {\n throw new Error(\"Captcha service unavailable\")\n }\n\n const token = await captcha.execute(\n import.meta.env.VITE_APP_GOOGLE_CAPTCHA_KEY,\n { action: action }\n )\n\n captchaRespToken.value = token\n return captchaRequest.value\n }\n\n return {\n captchaReady,\n captchaRequest,\n captchaExecute,\n }\n}\n\n/**\n * recordToMultiselectOptions formats a record of arrays into an\n * an options set suitable for MultiSelect components\n * @param records Record>\n * @return Array<{ label: string; options: Array<{ label: string; value: string }> }>\n */\nexport const recordToMultiselectOptions = (\n records: Record>\n): Array<{\n label: string\n options: Array<{\n label: string\n value: string\n }>\n}> => {\n const options: {\n label: string\n options: { label: string; value: string }[]\n }[] = []\n\n for (const [key, record] of Object.entries(records)) {\n options.push({\n label: key,\n options: record.map((v) => {\n return {\n label: v,\n value: v,\n }\n }),\n })\n }\n\n return options\n}\n"],"names":["PasswordPattern","arrayToOptions","options","o","maxDateToday","minDateTomorrow","d","initCaptchaAssets","once","init","initScriptTag","useCaptcha","action","captcha","captchaReady","ref","captchaRespToken","captchaRequest","computed","token","recordToMultiselectOptions","records","key","record","v"],"mappings":"yFAQO,MAAMA,EAAkB,OAAO,kEAMzBC,EAAkBC,GACtBA,EAAQ,IAAKC,IACX,CACL,MAAOA,EACP,MAAOA,CACT,EACD,EAOUC,MAAmB,KAAK,EAAE,cAAc,MAAM,GAAG,EAAE,CAAC,EAMpDC,EAAkB,IAAM,CAC7B,MAAAC,MAAQ,KACd,OAAAA,EAAE,QAAY,IAAA,KAAA,EAAO,UAAY,CAAC,EAE3BA,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC,CACrC,EAaMC,GAAgD,IAAA,CAChD,IAAAC,EAEJ,MAAMC,EAAO,UACL,MAAAC,EACJ,2GAGF,EACO,MAAM,QAAQ,QAAQ,EAAI,GAGnC,MAAO,WACAF,IACHA,EAAOC,EAAK,GAGPD,EAEX,GAAG,EAKUG,EAAcC,GAAmB,CAC5C,IAAIC,EACE,MAAAC,EAAeC,EAAa,EAAK,EACjCC,EAAmBD,EAAY,EAAE,EAErBR,EAAA,EAAE,KAAK,IAAM,CACtB,OAAA,WAAW,MAAM,IAAM,CAC5BM,EAAU,OAAO,WACjBC,EAAa,MAAQ,EAAA,CACtB,CAAA,CACF,EAEK,MAAAG,EAAiBC,EAAS,KACvB,CACL,cAAeN,EACf,gBAAiBI,EAAiB,KACpC,EACD,EAgBM,MAAA,CACL,aAAAF,EACA,eAAAG,EACA,eAjBqB,SAAY,CAC7B,GAAAH,EAAa,QAAU,GACnB,MAAA,IAAI,MAAM,6BAA6B,EAGzC,MAAAK,EAAQ,MAAMN,EAAQ,QAC1B,2CACA,CAAE,OAAAD,CAAe,CACnB,EAEA,OAAAI,EAAiB,MAAQG,EAClBF,EAAe,KACxB,CAMA,CACF,EAQaG,EACXC,GAOI,CACJ,MAAMnB,EAGA,CAAC,EAEP,SAAW,CAACoB,EAAKC,CAAM,IAAK,OAAO,QAAQF,CAAO,EAChDnB,EAAQ,KAAK,CACX,MAAOoB,EACP,QAASC,EAAO,IAAKC,IACZ,CACL,MAAOA,EACP,MAAOA,CACT,EACD,CAAA,CACF,EAGI,OAAAtB,CACT"}