diff --git a/npachpande/async/miawCustomPrechat/customPreChatForm.css b/npachpande/async/miawCustomPrechat/customPreChatForm.css
new file mode 100644
index 0000000000..fe8e7a1697
--- /dev/null
+++ b/npachpande/async/miawCustomPrechat/customPreChatForm.css
@@ -0,0 +1,13 @@
+:host {
+ display: flex;
+ flex-direction: column;
+ flex: 1 1 auto;
+ overflow: hidden;
+ background: #FFFFFF;
+ padding: 2em;
+}
+
+lightning-button {
+ padding-top: 2em;
+ text-align: center;
+}
diff --git a/npachpande/async/miawCustomPrechat/customPreChatForm.html b/npachpande/async/miawCustomPrechat/customPreChatForm.html
new file mode 100644
index 0000000000..5d1f8ef35c
--- /dev/null
+++ b/npachpande/async/miawCustomPrechat/customPreChatForm.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/npachpande/async/miawCustomPrechat/customPreChatForm.js b/npachpande/async/miawCustomPrechat/customPreChatForm.js
new file mode 100644
index 0000000000..83c6116d1d
--- /dev/null
+++ b/npachpande/async/miawCustomPrechat/customPreChatForm.js
@@ -0,0 +1,80 @@
+import { track, api, LightningElement } from "lwc";
+
+export default class CustomPreChatForm extends LightningElement {
+ /**
+ * Deployment configuration data.
+ * @type {Object}
+ */
+ @api configuration = {};
+
+ startConversationLabel;
+
+ get prechatForm() {
+ const forms = this.configuration.forms || [];
+ return forms.find(form => form.formType === "PreChat") || {};
+ }
+
+ get prechatFormFields() {
+ return this.prechatForm.formFields || [];
+ }
+
+ /**
+ * Returns prechat form fields sorted by their display order.
+ * @type {Object[]}
+ */
+ get fields() {
+ let fields = JSON.parse(JSON.stringify(this.prechatFormFields));
+ this.addChoiceListValues(fields);
+ return fields.sort((fieldA, fieldB) => fieldA.order - fieldB.order);
+ }
+
+ connectedCallback() {
+ this.startConversationLabel = "Start Conversation";
+ }
+
+ /**
+ * Adds values to fields of type choiceList (dropdown).
+ */
+ addChoiceListValues(fields) {
+ for (let field of fields) {
+ if (field.type === "ChoiceList") {
+ const valueList = this.configuration.choiceListConfig.choiceList.find(list => list.choiceListId === field.choiceListId) || {};
+ field.choiceListValues = valueList.choiceListValues || [];
+ }
+ }
+ }
+
+ /**
+ * Iterates over and reports validity for each form field. Returns true if all the fields are valid.
+ * @type {boolean}
+ */
+ isValid() {
+ let isFormValid = true;
+ this.template.querySelectorAll("c-custom-pre-chat-form-field").forEach(formField => {
+ if (!formField.reportValidity()) {
+ isFormValid = false;
+ }
+ });
+ return isFormValid;
+ }
+
+ /**
+ * Gathers and submits prechat data to the app on start converation button click.
+ * @type {boolean}
+ */
+ onStartConversationClick() {
+ const prechatData = {};
+ if (this.isValid()) {
+ this.template.querySelectorAll("c-custom-pre-chat-form-field").forEach(formField => {
+ prechatData[formField.name] = String(formField.value);
+ });
+
+ this.dispatchEvent(new CustomEvent(
+ "prechatsubmit",
+ {
+ detail: { value: prechatData }
+ }
+ ));
+ }
+ }
+}
diff --git a/npachpande/async/miawCustomPrechat/customPreChatForm.js-meta.xml b/npachpande/async/miawCustomPrechat/customPreChatForm.js-meta.xml
new file mode 100644
index 0000000000..c179b82f4b
--- /dev/null
+++ b/npachpande/async/miawCustomPrechat/customPreChatForm.js-meta.xml
@@ -0,0 +1,8 @@
+
+
+ 59.0
+ true
+
+ lightningSnapin__MessagingPreChat
+
+
diff --git a/npachpande/async/miawCustomPrechat/customPreChatFormField.html b/npachpande/async/miawCustomPrechat/customPreChatFormField.html
new file mode 100644
index 0000000000..c6e92858e6
--- /dev/null
+++ b/npachpande/async/miawCustomPrechat/customPreChatFormField.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/npachpande/async/miawCustomPrechat/customPreChatFormField.js b/npachpande/async/miawCustomPrechat/customPreChatFormField.js
new file mode 100644
index 0000000000..7ba92c0b42
--- /dev/null
+++ b/npachpande/async/miawCustomPrechat/customPreChatFormField.js
@@ -0,0 +1,68 @@
+import { track, api, LightningElement } from "lwc";
+
+export default class CustomPreChatFormField extends LightningElement {
+ choiceListDefaultValue;
+
+ /**
+ * Form field data.
+ * @type {Object}
+ */
+ @api fieldInfo = {};
+
+ @api
+ get name() {
+ return this.fieldInfo.name;
+ }
+
+ @api
+ get value() {
+ const lightningCmp = this.isTypeChoiceList ? this.template.querySelector("lightning-combobox") : this.template.querySelector("lightning-input");
+ return this.isTypeCheckbox ? lightningCmp.checked : lightningCmp.value;
+ }
+
+ @api
+ reportValidity() {
+ const lightningCmp = this.isTypeChoiceList ? this.template.querySelector("lightning-combobox") : this.template.querySelector("lightning-input");
+ return lightningCmp.reportValidity();
+ }
+
+ get type() {
+ switch (this.fieldInfo.type) {
+ case "Phone":
+ return "tel";
+ case "Text":
+ case "Email":
+ case "Number":
+ case "Checkbox":
+ case "ChoiceList":
+ return this.fieldInfo.type.toLowerCase();
+ default:
+ return "text";
+ }
+ }
+
+ get isTypeCheckbox() {
+ return this.type === "Checkbox".toLowerCase();
+ }
+
+ get isTypeChoiceList() {
+ return this.type === "ChoiceList".toLowerCase();
+ }
+
+ /**
+ * Formats choiceList options and sets the default value.
+ * @type {Array}
+ */
+ get choiceListOptions() {
+ let choiceListOptions = [];
+ const choiceListValues = [...this.fieldInfo.choiceListValues];
+ choiceListValues.sort((valueA, valueB) => valueA.order - valueB.order);
+ for (const listValue of choiceListValues) {
+ if (listValue.isDefaultValue) {
+ this.choiceListDefaultValue = listValue.choiceListValueName;
+ }
+ choiceListOptions.push({ label: listValue.label, value: listValue.choiceListValueName });
+ }
+ return choiceListOptions;
+ }
+}
diff --git a/npachpande/async/miawCustomPrechat/customPreChatFormField.js-meta.xml b/npachpande/async/miawCustomPrechat/customPreChatFormField.js-meta.xml
new file mode 100644
index 0000000000..ae48dcb034
--- /dev/null
+++ b/npachpande/async/miawCustomPrechat/customPreChatFormField.js-meta.xml
@@ -0,0 +1,7 @@
+
+
+ 59.0
+ true
+
+
+