{"version":3,"sources":["jsdelivr-header.js","/npm/@hot-page/hotfx-form@0.0.0/hotfx-form.js"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA,OCJO,MAAM,kBAAkB,YAG7B,GAEA,WAAA,GACE,QAGA,KAAK,iBAAiB,SAAY,MAAK,GACvC,KAAK,iBAAiB,QAAW,MAAK,GAGtC,KAAK,iBAAiB,UAAa,MAAK,EAAY,CAAE,SAAS,IAE/D,MAAK,EAAa,KAAK,iBACzB,CAMA,OAAM,CAAU,GAId,EAAM,iBAEN,MAAM,EAAO,EAAM,OAInB,IAAK,EAAK,OAER,YADA,QAAQ,MAAM,kFAKhB,MAAK,EAAW,OAAO,OAAO,WAC9B,MAAK,EAAW,OAAO,OAAO,WAC9B,KAAK,MAAM,eAAe,yBAG1B,MAAK,EAAW,OAAO,IAAI,WAG3B,EAAM,UAAU,UAAW,EAG3B,MAAM,EAAO,IAAI,SAAS,EAAM,QAChC,IAGE,IAAI,EAQF,EADiB,OAAf,EAAK,aACU,MAAM,GAAG,EAAK,UAAU,IAAI,gBAAgB,MAIpC,uBAAhB,EAAK,cACG,MAAM,EAAK,OAAQ,CAAE,OAAQ,OAAQ,KAAM,UAM3C,MAAM,EAAK,OAAQ,CAClC,OAAQ,OACR,KAAM,IAAI,gBAAgB,KAO9B,MAAM,QAAa,EAAS,OAC5B,KAAK,MAAM,YAAY,wBAAyB,IAAI,MAEhD,EAAS,GAGX,MAAK,EAAW,OAAO,IAAI,YAG3B,MAAK,EAAW,OAAO,IAAI,WAG3B,QAAQ,MACN,iDAAiD,EAAS,YAAY,MAI5E,CAAE,MAAM,GAGN,KAAK,MAAM,YAAY,wBAAyB,2BAA2B,EAAM,eACjF,MAAK,EAAW,OAAO,IAAI,WAC3B,QAAQ,MAAM,oBAAqB,EACrC,CAAE,QAIA,MAAK,EAAW,OAAO,OAAO,WAC9B,EAAM,UAAU,UAAW,CAC7B,CACF,CAMA,EAAA,CAAW,GAKJ,KAAK,aAAa,cAGvB,MAAK,EAAW,OAAO,IAAI,WAG3B,EAAM,iBACR,CAKA,EAAA,GAGE,KAAK,MAAM,eAAe,yBAC1B,MAAK,EAAW,OAAO,OAAO,WAC9B,MAAK,EAAW,OAAO,OAAO,UAChC,EAMF,MAAM,OAAS,IAAI,gBAAgB,KAAK,aAAa,IAAI,UAI3C,SAAV,QAAmB,eAAe,OAAO,aAAc","file":"/npm/@hot-page/hotfx-form@0.0.0/hotfx-form.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/@hot-page/hotfx-form@0.0.0/hotfx-form.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","// The <hotfx-form> is a custom HTML element so we must extend the `HTMLElement`\n// class.\nexport class HotFXForm extends HTMLElement {\n  // The `ElementInternals` object will let us add custom states to this element\n  // that can be read in CSS with the `:state()` pseudo class.\n  #internals\n\n  constructor() {\n    super()\n    // These three event handlers represent the entire functionality of the\n    // element.\n    this.addEventListener(('submit'), this.#onSubmit)\n    this.addEventListener(('reset'), this.#onReset)\n    // Since the `invalid` event does not bubble, we need to grab it during the\n    // capturing phase.\n    this.addEventListener(('invalid'), this.#onInvalid, { capture: true })\n    // ElementInternals must be enabled manually.\n    this.#internals = this.attachInternals();\n  }\n\n  // The `submit` event is fired when the user clicks the button to submit the\n  // form or hits enter while typing in an `<input>` element. This will only\n  // fire if the form has passed validation, so we can assume the data is ready\n  // to go.\n  async #onSubmit(event) {\n    // The default action of the form is to load a new page, so we always need\n    // to call `preventDefault` on the `submit` event to make sure that doesn't\n    // happen.\n    event.preventDefault()\n    // The event's `target` is the wrapped `<form>` element.\n    const form = event.target\n    // We require the `action=` attribute to be set on the form or we won't know\n    // where to submit the data. This is an URL for the server that accepts your\n    // data, such as a Zapier webhook.\n    if (!form.action) {\n      console.error('HotFX Form Error: missing the `action=\"https://....\"` attribute on your <form>')\n      return\n    }\n    // Before submitting the form, we clean up the state from any previous\n    // attempt.\n    this.#internals.states.delete('success')\n    this.#internals.states.delete('failure')\n    this.style.removeProperty('--hotfx-form-response')\n    // This adds the `loading` state while we're waiting for a response from\n    // the server. In the demo, this is used to show a spinner.\n    this.#internals.states.add('loading')\n    // `event.submitter` is the button that was clicked to submit the form. We\n    // want to disable it for now so there are no double submissions.\n    event.submitter.disabled = true\n    // The browser APIs for forms are quite useful. The `FormData` class takes a\n    // form element and turns it into an iterable list of fields and values.\n    const data = new FormData(event.target)\n    try {\n      // The `response` variable is going to be the server's response to our\n      // `fetch()` request.\n      let response\n      // There are several diferent ways we can submit the form depending on\n      // the attributes set on it.\n      //\n      // A GET request adds the data as query parameters to the URL. So, for\n      // example, it will create an URL like  `https://example.site/webhook?name=Foo&message=Bar`\n      // with the form data added in the query string after `?`.\n      if (form.method == 'get') {\n        response = await fetch(`${form.action}?${new URLSearchParams(data)}`)\n      // A form created like `<form enctype=\"multipart/form-data\" ...>` is \n      // typically used for file uploads. It specifies a different way of\n      // encoding the data that works for binary data like images.\n      } else if (form.enctype == 'multipart/form-data') {\n        response = await fetch(form.action, { method: 'POST', body: data })\n      // The default for most forms sends the data as the body of a POST request\n      // with the `content-type: application/x-www-form-urlencoded` header. The\n      // body is an URL-encoded string like `name=Foo&message=Bar`, much the\n      // same as the data encoded at the end of the URL in a GET request.\n      } else {\n        response = await fetch(form.action, {\n          method: 'POST',\n          body: new URLSearchParams(data),\n        })\n      }\n      // Read the server's response as text and save it to a custom CSS\n      // property. This can be used to show the server's response to the user\n      // in a `::before` or `::after` element with `content:\n      // var(--hotfx-form-response)`.\n      const text = await response.text()\n      this.style.setProperty('--hotfx-form-response', `\"${text}\"`)\n      // An HTTP status code in the 200s is considered a success or okay.\n      if (response.ok) {\n        // This adds the `success` state, which can be used in CSS to show a\n        // success message to the user.\n        this.#internals.states.add('success');\n      // Otherwise, add the `failure` state.\n      } else {\n        this.#internals.states.add('failure');\n        // Also log the error to the console for developers who might be\n        // looking there.\n        console.error(\n          `HotFX Form got a bad response from the server ${response.status}: \"${text}\"`,\n        )\n      }\n    // If the server is unreachable, `fetch()` will throw an error.\n    } catch(error) {\n      // We add the error message to the same CSS variable as if it was the\n      // response, so it can be shown on the form and the user knows what's up.\n      this.style.setProperty('--hotfx-form-response', `\"Couldn’t reach server: ${error.toString()}\"`)\n      this.#internals.states.add('failure');\n      console.error('HotFX Form error:', error)\n    } finally {\n      // The `finally` block runs whether there was an error or not and we use\n      // it here to clean up the form to be ready for the next submission,\n      // removing the loading state and re-enabling the submit button.\n      this.#internals.states.delete('loading');\n      event.submitter.disabled = false\n    }\n  }\n\n  // The `invalid` event is fired when the form is submitted by the user but one\n  // of the fields doesn't pass validation. So, for example, if an element with\n  // `<input required>` is empty, this event will fire instead of `submit` when\n  // the user hits the submit button.\n  #onInvalid(event) {\n    // If we don't have the `validate` attribute on the form, the developer has\n    // not opted-in to writing their own valiation messages and we return early.\n    // In this case, the browser will show its own validation message using the\n    // native styles.\n    if (!this.hasAttribute('validate')) return\n    // This adds the `failure` state so that error messages can be shown to the\n    // user.\n    this.#internals.states.add('failure')\n    // Calling `preventDefault` prevents the browser from showing its own\n    // validation message.\n    event.preventDefault()\n  }\n\n  // The reset event is fired from a button with the `type=\"reset\"` attribute.\n  // This can be used to clear the form and remove any error messages and\n  // states from the previous submission.\n  #onReset() {\n    // Here we just clean up our states and the response variable and it's like \n    // nothing ever happend here.\n    this.style.removeProperty('--hotfx-form-response')\n    this.#internals.states.delete('success')\n    this.#internals.states.delete('failure')\n  }\n}\n\n// Checks for a `?define` query parameter in the URL that was used to load this\n// script. So, for instance, if you load the script with `<script type=\"module\" src=\"https://cdn.jsdelivr.net/npm/@hot-page/hotfx-form@0.0.0?define=false\">`,\n// this variable will contain the text `false`.\nconst define = new URL(import.meta.url).searchParams.get(\"define\")\n// By default we register the above class as a custom element so that we can use\n// it in HTML with the `<hotfx-form>` tag. That is, unless called with the query\n// parameter to prevent this.\nif (define != 'false') customElements.define('hotfx-form', HotFXForm)\n"]}