{"version":3,"names":["serialize","form","formData","FormData","object","forEach","value","key","scFormCss","ScForm","async","this","formElement","scFormChange","emit","submitForm","getFormControls","querySelectorAll","formControls","formControlsThatReport","filter","el","reportValidity","novalidate","offsetWidth","offsetHeight","getClientRects","length","isValid","button","document","createElement","type","style","position","width","height","clip","clipPath","overflow","whiteSpace","append","click","remove","render","h","part","class","role","ref","onSubmit","e","preventDefault","validate","scSubmit","scFormSubmit"],"sources":["./src/functions/form.ts","./src/components/ui/form/sc-form.scss?tag=sc-form&encapsulation=shadow","./src/components/ui/form/sc-form.tsx"],"sourcesContent":["/**\n * Serializes a form and returns a plain object. If a form control with the same name appears more than once, the\n * property will be converted to an array.\n */\nexport function serialize(form: HTMLFormElement) {\n const formData = new FormData(form);\n const object: Record = {};\n\n formData.forEach((value, key) => {\n object[key] = value;\n });\n\n return object;\n}\n",":host {\n display: block;\n}\n\n::slotted(*:not(:last-child)) {\n margin-bottom: var(--sc-form-row-spacing, 0.75em);\n\n &.wp-block-spacer {\n margin-bottom: 0;\n }\n}\n::slotted(*:focus-within),\n::slotted(*:active) {\n position: relative;\n z-index: 5;\n}\n","import { Component, Element, Event, EventEmitter, h, Listen, Method, Prop } from '@stencil/core';\n\nimport { serialize } from '../../../functions/form';\n\n@Component({\n tag: 'sc-form',\n styleUrl: 'sc-form.scss',\n shadow: true,\n})\nexport class ScForm {\n @Element() form: HTMLElement;\n private formElement: HTMLFormElement;\n\n /** Prevent the form from validating inputs before submitting. */\n @Prop({ reflect: true, mutable: true }) novalidate: boolean = false;\n\n /**\n * Emitted when the form is submitted. This event will not be emitted if any form control inside of\n * it is in an invalid state, unless the form has the `novalidate` attribute. Note that there is never a need to prevent\n * this event, since it doen't send a GET or POST request like native forms. To \"prevent\" submission, use a conditional\n * around the XHR request you use to submit the form's data with.\n */\n @Event({ bubbles: true }) scSubmit: EventEmitter;\n\n /**\n * Backwards compat.\n */\n @Event() scFormSubmit: EventEmitter;\n\n /**\n * Emitted when the form is submitted. This event will not be emitted if any form control inside of\n * it is in an invalid state, unless the form has the `novalidate` attribute. Note that there is never a need to prevent\n * this event, since it doen't send a GET or POST request like native forms. To \"prevent\" submission, use a conditional\n * around the XHR request you use to submit the form's data with.\n */\n @Event() scFormChange: EventEmitter;\n\n /** Serializes all form controls elements and returns a `FormData` object. */\n @Method('getFormData')\n async getFormData() {\n return new FormData(this.formElement);\n }\n\n @Method('getFormJson')\n async getFormJson() {\n return serialize(this.formElement);\n }\n\n @Listen('scChange')\n async handleChange() {\n this.scFormChange.emit(serialize(this.formElement));\n }\n\n @Method('submit')\n async submit() {\n return this.submitForm();\n }\n\n /** Gets all form control elements (native and custom). */\n getFormControls() {\n return [...this.form.querySelectorAll('*')] as HTMLElement[];\n }\n\n @Method('validate')\n async validate() {\n const formControls = this.getFormControls();\n const formControlsThatReport = formControls.filter((el: any) => typeof el.reportValidity === 'function') as any;\n\n if (!this.novalidate) {\n for (const el of formControlsThatReport) {\n // element is hidden, don't client-side validate.\n if (!(el.offsetWidth || el.offsetHeight || el.getClientRects().length)) {\n continue;\n }\n\n const isValid = await el.reportValidity();\n\n if (!isValid) {\n return false;\n }\n }\n }\n\n return true;\n }\n\n submitForm() {\n // Calling form.submit() seems to bypass the submit event and constraint validation. Instead, we can inject a\n // native submit button into the form, click it, then remove it to simulate a standard form submission.\n const button = document.createElement('button');\n if (this.formElement) {\n button.type = 'submit';\n button.style.position = 'absolute';\n button.style.width = '0';\n button.style.height = '0';\n button.style.clip = 'rect(0 0 0 0)';\n button.style.clipPath = 'inset(50%)';\n button.style.overflow = 'hidden';\n button.style.whiteSpace = 'nowrap';\n this.formElement.append(button);\n button.click();\n button.remove();\n }\n }\n\n render() {\n return (\n
\n (this.formElement = el as HTMLFormElement)}\n class=\"test\"\n onSubmit={async e => {\n e.preventDefault();\n const isValid = await this.validate();\n if (!isValid) {\n return false;\n }\n this.scSubmit.emit();\n this.scFormSubmit.emit();\n }}\n novalidate={this.novalidate}\n >\n \n \n
\n );\n }\n}\n"],"mappings":"kEAIgBA,EAAUC,GACxB,MAAMC,EAAW,IAAIC,SAASF,GAC9B,MAAMG,EAAkC,GAExCF,EAASG,SAAQ,CAACC,EAAOC,KACvBH,EAAOG,GAAOD,CAAK,IAGrB,OAAOF,CACT,CCbA,MAAMI,EAAY,8O,MCSLC,EAAM,M,kKAK6C,K,CAyB9DC,oBACE,OAAO,IAAIP,SAASQ,KAAKC,Y,CAI3BF,oBACE,OAAOV,EAAUW,KAAKC,Y,CAIxBF,qBACEC,KAAKE,aAAaC,KAAKd,EAAUW,KAAKC,a,CAIxCF,eACE,OAAOC,KAAKI,Y,CAIdC,kBACE,MAAO,IAAIL,KAAKV,KAAKgB,iBAAiB,K,CAIxCP,iBACE,MAAMQ,EAAeP,KAAKK,kBAC1B,MAAMG,EAAyBD,EAAaE,QAAQC,UAAmBA,EAAGC,iBAAmB,aAE7F,IAAKX,KAAKY,WAAY,CACpB,IAAK,MAAMF,KAAMF,EAAwB,CAEvC,KAAME,EAAGG,aAAeH,EAAGI,cAAgBJ,EAAGK,iBAAiBC,QAAS,CACtE,Q,CAGF,MAAMC,QAAgBP,EAAGC,iBAEzB,IAAKM,EAAS,CACZ,OAAO,K,GAKb,OAAO,I,CAGTb,aAGE,MAAMc,EAASC,SAASC,cAAc,UACtC,GAAIpB,KAAKC,YAAa,CACpBiB,EAAOG,KAAO,SACdH,EAAOI,MAAMC,SAAW,WACxBL,EAAOI,MAAME,MAAQ,IACrBN,EAAOI,MAAMG,OAAS,IACtBP,EAAOI,MAAMI,KAAO,gBACpBR,EAAOI,MAAMK,SAAW,aACxBT,EAAOI,MAAMM,SAAW,SACxBV,EAAOI,MAAMO,WAAa,SAC1B7B,KAAKC,YAAY6B,OAAOZ,GACxBA,EAAOa,QACPb,EAAOc,Q,EAIXC,SACE,OACEC,EAAA,OAAKC,KAAK,OAAOC,MAAM,OAAOC,KAAK,QACjCH,EAAA,QACEC,KAAK,OACLG,IAAK5B,GAAOV,KAAKC,YAAcS,EAC/B0B,MAAM,OACNG,SAAUxC,MAAMyC,IACdA,EAAEC,iBACF,MAAMxB,QAAgBjB,KAAK0C,WAC3B,IAAKzB,EAAS,CACZ,OAAO,K,CAETjB,KAAK2C,SAASxC,OACdH,KAAK4C,aAAazC,MAAM,EAE1BS,WAAYZ,KAAKY,YAEjBsB,EAAA,c"}