quikchat 1.1.17 → 1.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +167 -276
- package/dist/build-manifest.json +157 -0
- package/dist/quikchat-md-full.cjs.js +2742 -0
- package/dist/quikchat-md-full.cjs.js.map +1 -0
- package/dist/quikchat-md-full.cjs.min.js +10 -0
- package/dist/quikchat-md-full.cjs.min.js.map +1 -0
- package/dist/quikchat-md-full.esm.js +2740 -0
- package/dist/quikchat-md-full.esm.js.map +1 -0
- package/dist/quikchat-md-full.esm.min.js +10 -0
- package/dist/quikchat-md-full.esm.min.js.map +1 -0
- package/dist/quikchat-md-full.umd.js +2748 -0
- package/dist/quikchat-md-full.umd.js.map +1 -0
- package/dist/quikchat-md-full.umd.min.js +10 -0
- package/dist/quikchat-md-full.umd.min.js.map +1 -0
- package/dist/quikchat-md.cjs.js +1641 -0
- package/dist/quikchat-md.cjs.js.map +1 -0
- package/dist/quikchat-md.cjs.min.js +8 -0
- package/dist/quikchat-md.cjs.min.js.map +1 -0
- package/dist/quikchat-md.esm.js +1639 -0
- package/dist/quikchat-md.esm.js.map +1 -0
- package/dist/quikchat-md.esm.min.js +8 -0
- package/dist/quikchat-md.esm.min.js.map +1 -0
- package/dist/quikchat-md.umd.js +1647 -0
- package/dist/quikchat-md.umd.js.map +1 -0
- package/dist/quikchat-md.umd.min.js +8 -0
- package/dist/quikchat-md.umd.min.js.map +1 -0
- package/dist/quikchat.cjs.js +454 -1729
- package/dist/quikchat.cjs.js.map +1 -1
- package/dist/quikchat.cjs.min.js +1 -1
- package/dist/quikchat.cjs.min.js.map +1 -1
- package/dist/quikchat.css +753 -226
- package/dist/quikchat.esm.js +454 -1729
- package/dist/quikchat.esm.js.map +1 -1
- package/dist/quikchat.esm.min.js +1 -1
- package/dist/quikchat.esm.min.js.map +1 -1
- package/dist/quikchat.min.css +1 -1
- package/dist/quikchat.react.js +63 -0
- package/dist/quikchat.umd.js +454 -1729
- package/dist/quikchat.umd.js.map +1 -1
- package/dist/quikchat.umd.min.js +1 -1
- package/dist/quikchat.umd.min.js.map +1 -1
- package/package.json +59 -39
- package/dist/quikchat.d.ts +0 -194
package/dist/quikchat.cjs.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";function t(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=Array(e);i<e;i++)n[i]=t[i];return n}function e(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,o(n.key),n)}}function n(t,e,n){return e&&i(t.prototype,e),n&&i(t,n),Object.defineProperty(t,"prototype",{writable:!1}),t}function s(t,e,i){return(e=o(e))in t?Object.defineProperty(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}function a(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,n)}return i}function r(t){for(var e=1;e<arguments.length;e++){var i=null!=arguments[e]?arguments[e]:{};e%2?a(Object(i),!0).forEach((function(e){s(t,e,i[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(i)):a(Object(i)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(i,e))}))}return t}function l(e){return function(e){if(Array.isArray(e))return t(e)}(e)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(e)||function(e,i){if(e){if("string"==typeof e)return t(e,i);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?t(e,i):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function o(t){var e=function(t,e){if("object"!=typeof t||!t)return t;var i=t[Symbol.toPrimitive];if(void 0!==i){var n=i.call(t,e||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"==typeof e?e:e+""}var h={version:"1.1.17",license:"BSD-2",url:"https://github/deftio/quikchat",fun:!0},u=function(){return n((function t(i){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};e(this,t),this.container=i,this.items=[],this.itemHeight=n.itemHeight||80,this.buffer=n.buffer||5,this.visibleRange={start:0,end:0},this.renderedElements=new Map,this.itemHeights=new Map,this.itemPositions=new Map,this.totalHeight=0,this.onRenderItem=n.onRenderItem||function(){},this.sanitizer=n.sanitizer||null,this._initStructure(),this._attachScrollListener()}),[{key:"_initStructure",value:function(){var t=this,e=this.container.className;if(this.container.innerHTML="",this.container.className=e,this.container.style.position="relative",this.container.style.overflow="auto",0===this.container.offsetHeight){var i=window.getComputedStyle(this.container).height;"0px"!==i&&"auto"!==i||(this.container.style.height="400px",console.warn("QuikChat Virtual Scrolling: Container has no height, setting to 400px"))}this.spacer=document.createElement("div"),this.spacer.style.cssText="position: absolute; top: 0; left: 0; width: 1px; pointer-events: none; z-index: -1;",this.content=document.createElement("div"),this.content.style.cssText="position: relative; width: 100%;",this.container.appendChild(this.spacer),this.container.appendChild(this.content),setTimeout((function(){t._updateVisibleRange(),t._renderVisibleItems()}),0)}},{key:"_attachScrollListener",value:function(){var t=this,e=!1;this.container.addEventListener("scroll",(function(){e||(requestAnimationFrame((function(){t._updateVisibleRange(),t._renderVisibleItems(),e=!1})),e=!0)}))}},{key:"_getItemHeight",value:function(t){return this.itemHeights.get(t)||this.itemHeight}},{key:"_getItemPosition",value:function(t){if(this.itemPositions.has(t))return this.itemPositions.get(t);for(var e=0,i=0;i<t;i++)e+=this._getItemHeight(i);return this.itemPositions.set(t,e),e}},{key:"_recalculatePositions",value:function(t){for(var e=t>0?this._getItemPosition(t):0,i=t;i<this.items.length;i++){this.itemPositions.set(i,e),e+=this._getItemHeight(i);var n=this.renderedElements.get(i);n&&(n.style.top="".concat(this.itemPositions.get(i),"px"))}this.totalHeight=e,this.spacer.style.height="".concat(this.totalHeight,"px")}},{key:"_updateVisibleRange",value:function(){var t=this.container.scrollTop,e=this.container.clientHeight;if(0!==e){var i=0,n=this.items.length;if(this.itemPositions.size>0){for(var s=0;s<this.items.length;s++){if(this._getItemPosition(s)+this._getItemHeight(s)>t){i=Math.max(0,s-this.buffer);break}}for(var a=i;a<this.items.length;a++){if(this._getItemPosition(a)>t+e){n=Math.min(this.items.length,a+this.buffer);break}}}else i=Math.max(0,Math.floor(t/this.itemHeight)-this.buffer),n=Math.min(this.items.length,Math.ceil((t+e)/this.itemHeight)+this.buffer);this.visibleRange={start:i,end:n}}else this.visibleRange={start:0,end:0}}},{key:"_renderVisibleItems",value:function(){var t=this,e=this.visibleRange,i=e.start,n=e.end;this.renderedElements.forEach((function(e,s){(s<i||s>=n)&&(e.remove(),t.renderedElements.delete(s))}));for(var s=function(e){var i=t.items[e];if(!i||t.renderedElements.has(e))return 1;var n=t._createItemElement(i,e);n.style.position="absolute",n.style.top="".concat(t._getItemPosition(e),"px"),n.style.left="0",n.style.right="0",t.renderedElements.set(e,n),t.content.appendChild(n),requestAnimationFrame((function(){if(t.renderedElements.has(e)){var i=n.offsetHeight;i&&i!==t._getItemHeight(e)&&(t.itemHeights.set(e,i),t._recalculatePositions(e))}}))},a=i;a<n;a++)s(a);this.onRenderItem(this.content)}},{key:"_createItemElement",value:function(t,e){var i=document.createElement("div");i.className="quikchat-message quikchat-message-".concat(t.align||"left"," quikchat-msgid-").concat(String(t.msgid).padStart(10,"0")),i.setAttribute("data-index",e),i.setAttribute("data-msgid",t.msgid),i.setAttribute("role","article"),i.setAttribute("aria-label","Message from ".concat(t.userString||"user")),t.tags&&t.tags.length>0&&t.tags.forEach((function(t){return i.classList.add("quikchat-tag-".concat(t))}));var n=document.createElement("div");n.className="quikchat-message-user",n.innerHTML=this.sanitizer?this.sanitizer(t.userString||""):t.userString||"",n.setAttribute("aria-label","User");var s=document.createElement("div");return s.className="quikchat-message-content",s.innerHTML=this.sanitizer?this.sanitizer(t.content||""):t.content||"",s.setAttribute("aria-label","Message content"),i.appendChild(n),i.appendChild(s),t.visible||(i.style.display="none"),i}},{key:"addItem",value:function(t){this.items.push(t);var e=this.items.length-1,i=e>0?this._getItemPosition(e-1)+this._getItemHeight(e-1):0;return this.itemPositions.set(e,i),this.totalHeight=i+this.itemHeight,this.spacer.style.height="".concat(this.totalHeight,"px"),e>=this.visibleRange.start&&e<this.visibleRange.end&&this._renderVisibleItems(),t.scrollIntoView&&(this.container.scrollTop=this.container.scrollHeight),e}},{key:"addItems",value:function(t){var e,i=this.items.length;(e=this.items).push.apply(e,l(t));for(var n=i>0?this._getItemPosition(i-1)+this._getItemHeight(i-1):0,s=i;s<this.items.length;s++)this.itemPositions.set(s,n),n+=this.itemHeight;this.totalHeight=n,this.spacer.style.height="".concat(this.totalHeight,"px"),this._updateVisibleRange(),this._renderVisibleItems(),t.length>0&&t[t.length-1].scrollIntoView&&(this.container.scrollTop=this.container.scrollHeight)}},{key:"clear",value:function(){this.items=[],this.renderedElements.clear(),this.itemHeights.clear(),this.itemPositions.clear(),this.totalHeight=0,this.content.innerHTML="",this.spacer.style.height="0px",this.visibleRange={start:0,end:0},this._updateVisibleRange(),this._renderVisibleItems()}},{key:"updateItem",value:function(t,e){t>=0&&t<this.items.length&&(this.items[t]=r(r({},this.items[t]),e),this.renderedElements.has(t)&&this._renderVisibleItems())}},{key:"destroy",value:function(){this.container.innerHTML="",this.items=[],this.renderedElements.clear()}}])}(),c=function(){return n((function t(i){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:function(){},s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};e(this,t);var a={theme:"quikchat-theme-light",trackHistory:!0,titleArea:{title:"Chat",show:!1,align:"center"},messagesArea:{alternating:!0},inputArea:{show:!0},sendOnEnter:!0,sendOnShiftEnter:!1,instanceClass:"",virtualScrolling:!0,virtualScrollingThreshold:500,lang:"en",dir:"ltr",translations:{en:{sendButton:"Send",inputPlaceholder:"Type a message...",titleDefault:"Chat"}},sanitizer:null},l=r(r({},a),s);s.translations&&(l.translations=r(r({},a.translations),s.translations)),"string"==typeof i&&(i=document.querySelector(i)),this._parentElement=i,this._theme=l.theme,this._onSend=n||function(){},this.lang=l.lang,this.dir=l.dir,this.translations=l.translations,this.currentTranslations=this.translations[this.lang]||this.translations.en,this._createWidget(),l.instanceClass&&this._chatWidget.classList.add(l.instanceClass),l.titleArea&&(this.titleAreaSetContents(l.titleArea.title,l.titleArea.align),!0===l.titleArea.show?this.titleAreaShow():this.titleAreaHide()),l.messagesArea&&this.messagesAreaAlternateColors(l.messagesArea.alternating),l.inputArea&&(!0===l.inputArea.show?this.inputAreaShow():this.inputAreaHide()),this._attachEventListeners(),this.trackHistory=l.trackHistory||!0,this._historyLimit=1e7,this._history=[],this._activeTags=new Set,this.sendOnEnter=l.sendOnEnter,this.sendOnShiftEnter=l.sendOnShiftEnter,this.virtualScrollingEnabled=l.virtualScrolling,this.virtualScrollingThreshold=l.virtualScrollingThreshold,this.virtualScroller=null,this._sanitizer=l.sanitizer||null}),[{key:"_initVirtualScrolling",value:function(){var t=this;this.virtualScrollingEnabled&&this._messagesArea&&!this.virtualScroller&&this._history.length>=this.virtualScrollingThreshold-1&&(this.virtualScroller=new u(this._messagesArea,{itemHeight:80,buffer:5,sanitizer:this._sanitizer,onRenderItem:function(e){t._messagesArea.classList.contains("quikchat-messages-area-alt")&&t._updateMessageStyles()}}),this._migrateToVirtualScrolling())}},{key:"_migrateToVirtualScrolling",value:function(){var t=this;if(this.virtualScroller){var e=this._history.map((function(t){return{msgid:t.msgid,content:t.content,userString:t.userString,align:t.align,role:t.role,visible:t.visible,tags:t.tags||[],scrollIntoView:!1}}));this.virtualScroller.addItems(e),setTimeout((function(){t.virtualScroller&&(t.virtualScroller._updateVisibleRange(),t.virtualScroller._renderVisibleItems())}),10)}}},{key:"_createWidget",value:function(){var t=this.currentTranslations.sendButton||"Send",e=this.currentTranslations.inputPlaceholder||"Type a message...",i='\n <div class="quikchat-base '.concat(this._theme,'" dir="').concat(this.dir,'" lang="').concat(this.lang,'" role="region" aria-label="Chat widget">\n <div class="quikchat-title-area" role="heading" aria-level="2">\n <span style="font-size: 1.5em; font-weight: 600;">Title Area</span>\n </div>\n <div class="quikchat-messages-area" role="log" aria-live="polite" aria-label="Chat messages"></div>\n <div class="quikchat-input-area" role="form" aria-label="Message input">\n <textarea class="quikchat-input-textbox" \n placeholder="').concat(e,'"\n aria-label="Type your message"\n autocomplete="off"\n autocapitalize="sentences"></textarea>\n <button class="quikchat-input-send-btn" \n aria-label="Send message"\n type="button">').concat(t,"</button>\n </div>\n </div>\n ");this._parentElement.innerHTML=i,this._chatWidget=this._parentElement.querySelector(".quikchat-base"),this._titleArea=this._chatWidget.querySelector(".quikchat-title-area"),this._messagesArea=this._chatWidget.querySelector(".quikchat-messages-area"),this._inputArea=this._chatWidget.querySelector(".quikchat-input-area"),this._textEntry=this._inputArea.querySelector(".quikchat-input-textbox"),this._sendButton=this._inputArea.querySelector(".quikchat-input-send-btn"),this.msgid=0,this._setupMobileSupport()}},{key:"_setupMobileSupport",value:function(){var t=this,e=document.querySelector('meta[name="viewport"]');e||((e=document.createElement("meta")).name="viewport",document.head.appendChild(e)),this._originalViewport=e.content,this._textEntry.addEventListener("focus",(function(){window.innerWidth<=768&&(e.content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0")})),this._textEntry.addEventListener("blur",(function(){t._originalViewport?e.content=t._originalViewport:e.content="width=device-width, initial-scale=1.0"})),"visualViewport"in window&&window.visualViewport.addEventListener("resize",(function(){t._handleVirtualKeyboard()}))}},{key:"_handleVirtualKeyboard",value:function(){var t=window.innerHeight-window.visualViewport.height;this._chatWidget.style.paddingBottom=t>0?"".concat(t,"px"):""}},{key:"_attachEventListeners",value:function(){var t=this;this._sendButton.addEventListener("click",(function(e){e.preventDefault(),t._onSend(t,t._textEntry.value.trim())})),window.addEventListener("resize",(function(){return t._handleContainerResize()})),this._chatWidget.addEventListener("resize",(function(){return t._handleContainerResize()})),this._textEntry.addEventListener("keydown",(function(e){e.shiftKey&&13===e.keyCode?t.sendOnShiftEnter&&(e.preventDefault(),t._onSend(t,t._textEntry.value.trim())):13===e.keyCode&&t.sendOnEnter&&(e.preventDefault(),t._onSend(t,t._textEntry.value.trim()))})),this._messagesArea.addEventListener("scroll",(function(){var e=t._messagesArea,i=e.scrollTop,n=e.scrollHeight,s=e.clientHeight;t.userScrolledUp=i+s<n}))}},{key:"setCallbackOnSend",value:function(t){this._onSend=t}},{key:"setCallbackonMessageAdded",value:function(t){this._onMessageAdded=t}},{key:"setCallbackonMessageAppend",value:function(t){this._onMessageAppend=t}},{key:"setCallbackonMessageReplace",value:function(t){this._onMessageReplace=t}},{key:"setCallbackonMessageDelete",value:function(t){this._onMessageDelete=t}},{key:"titleAreaToggle",value:function(){"none"===this._titleArea.style.display?this.titleAreaShow():this.titleAreaHide()}},{key:"titleAreaShow",value:function(){this._titleArea.style.display="",this._adjustMessagesAreaHeight()}},{key:"titleAreaHide",value:function(){this._titleArea.style.display="none",this._adjustMessagesAreaHeight()}},{key:"titleAreaSetContents",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"center";this._titleArea.innerHTML=this._sanitizeContent(t),this._titleArea.style.textAlign=e}},{key:"titleAreaGetContents",value:function(){return this._titleArea.innerHTML}},{key:"inputAreaToggle",value:function(){this._inputArea.classList.toggle("hidden"),"none"===this._inputArea.style.display?this.inputAreaShow():this.inputAreaHide()}},{key:"inputAreaShow",value:function(){this._inputArea.style.display="",this._adjustMessagesAreaHeight()}},{key:"inputAreaHide",value:function(){this._inputArea.style.display="none",this._adjustMessagesAreaHeight()}},{key:"_adjustMessagesAreaHeight",value:function(){var t=l(this._chatWidget.children).filter((function(t){return t.classList.contains("hidden")})).reduce((function(t,e){return t+e.offsetHeight}),0),e=this._chatWidget.offsetHeight;this._messagesArea.style.height="calc(100% - ".concat(e-t,"px)")}},{key:"_handleContainerResize",value:function(){return this._adjustMessagesAreaHeight(),this._adjustSendButtonWidth(),!0}},{key:"_adjustSendButtonWidth",value:function(){var t=this._sendButton.textContent.trim(),e=parseFloat(getComputedStyle(this._sendButton).fontSize)*t.length+16;return this._sendButton.style.minWidth="".concat(e,"px"),!0}},{key:"messagesAreaAlternateColors",value:function(){var t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];return t?this._messagesArea.classList.add("quikchat-messages-area-alt"):this._messagesArea.classList.remove("quikchat-messages-area-alt"),!0===t}},{key:"messagesAreaAlternateColorsToggle",value:function(){this._messagesArea.classList.toggle("quikchat-messages-area-alt")}},{key:"messagesAreaAlternateColorsGet",value:function(){return this._messagesArea.classList.contains("quikchat-messages-area-alt")}},{key:"messageAddFull",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{content:"",userString:"user",align:"right",role:"user",userID:-1,timestamp:!1,updatedtime:!1,scrollIntoView:!0,visible:!0,tags:[]},i=this.msgid;this.msgid++;var n=null;if(this.virtualScrollingEnabled&&!this.virtualScroller&&this._history.length>=this.virtualScrollingThreshold-1&&this._initVirtualScrolling(),this.virtualScroller){var s={msgid:i,content:e.content,userString:e.userString,align:e.align,role:e.role,visible:void 0===e.visible||e.visible,tags:e.tags||[],scrollIntoView:e.scrollIntoView};Array.isArray(e.tags)&&e.tags.forEach((function(e){"string"==typeof e&&/^[a-zA-Z0-9-]+$/.test(e)&&t._activeTags.add(e)})),this.virtualScroller.addItem(s),this._textEntry.value="",this._adjustMessagesAreaHeight()}else{n=document.createElement("div");var a="quikchat-msgid-"+String(i).padStart(10,"0");String(e.userString).padStart(10,"0"),n.classList.add("quikchat-message",a,"quikchat-structure"),n.setAttribute("role","article"),n.setAttribute("aria-label","Message from ".concat(e.userString||"user")),Array.isArray(e.tags)&&e.tags.forEach((function(e){"string"==typeof e&&/^[a-zA-Z0-9-]+$/.test(e)&&(n.classList.add("quikchat-tag-".concat(e)),t._activeTags.add(e))}));var l=document.createElement("div");l.innerHTML=this._sanitizeContent(e.userString),l.classList.add("quikchat-user-label"),l.style.textAlign=e.align;var o=document.createElement("div");if(o.classList.add("quikchat-message-content"),"right"===e.align){var h=e.content.includes("\n"),u=e.content.length>50;h||u?o.classList.add("quikchat-right-multiline"):o.classList.add("quikchat-right-singleline")}o.innerHTML=this._sanitizeContent(e.content),n.appendChild(l),n.appendChild(o),this._messagesArea.appendChild(n),!1===e.visible&&(n.style.display="none"),!0===e.scrollIntoView?this.messageScrollToBottom():"smart"!==e.scrollIntoView||this.userScrolledUp||this.messageScrollToBottom(),this._textEntry.value="",this._adjustMessagesAreaHeight(),this._handleShortLongMessageCSS(n,e.align),this._updateMessageStyles()}var c=e.timestamp?e.timestamp:(new Date).toISOString(),g=e.updatedtime?e.updatedtime:c,d=void 0===e.visible||e.visible;return this.trackHistory&&(this._history.push(r(r({msgid:i},e),{},{visible:d,timestamp:c,updatedtime:g,messageDiv:n||null})),this._history.length>this._historyLimit&&this._history.shift()),this._onMessageAdded&&this._onMessageAdded(this,i),i}},{key:"messageAddNew",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"user",i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"right",n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"user",s=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],a=!(arguments.length>5&&void 0!==arguments[5])||arguments[5],r=arguments.length>6&&void 0!==arguments[6]?arguments[6]:[];return this.messageAddFull({content:t,userString:e,align:i,role:n,scrollIntoView:s,visible:a,tags:r})}},{key:"messageRemove",value:function(t){var e=!1;try{this._messagesArea.removeChild(this._messagesArea.querySelector(".quikchat-msgid-".concat(String(t).padStart(10,"0")))),e=!0}catch(t){console.log("{String(n)} : Message ID not found")}return e&&(this._history.splice(this._history.findIndex((function(e){return e.msgid===t})),1),this._onMessageDelete&&this._onMessageDelete(this,t)),e}},{key:"messageGetDOMObject",value:function(t){var e=null;try{e=this._messagesArea.querySelector(".quikchat-msgid-".concat(String(t).padStart(10,"0")))}catch(t){console.log("{String(n)} : Message ID not found")}return e}},{key:"messageGetContent",value:function(t){var e="";try{e=this._history.filter((function(e){return e.msgid===t}))[0].content}catch(t){console.log("{String(n)} : Message ID not found")}return e}},{key:"messageGetContentDOMElement",value:function(t){var e=null;try{e=this._history.filter((function(e){return e.msgid===t}))[0].messageDiv.lastChild}catch(t){console.log("{String(n)} : Message ID not found")}return e}},{key:"messageAppendContent",value:function(t,e){var i=!1;try{var n=this._history.filter((function(e){return e.msgid===t}))[0];if(n.content+=e,n.updatedtime=(new Date).toISOString(),this.virtualScroller){var s=this.virtualScroller.items.findIndex((function(e){return e.msgid===t}));s>=0&&(this.virtualScroller.items[s].content+=e,this.virtualScroller.updateItem(s,{content:this.virtualScroller.items[s].content}))}else this._messagesArea.querySelector(".quikchat-msgid-".concat(String(t).padStart(10,"0"))).lastChild.innerHTML+=this._sanitizeContent(e);i=!0,this._onMessageAppend&&this._onMessageAppend(this,t,e)}catch(e){console.log("".concat(String(t)," : Message ID not found"))}return i}},{key:"messageReplaceContent",value:function(t,e){var i=!1;try{var n=this._history.filter((function(e){return e.msgid===t}))[0];if(n.content=e,n.updatedtime=(new Date).toISOString(),this.virtualScroller){var s=this.virtualScroller.items.findIndex((function(e){return e.msgid===t}));s>=0&&(this.virtualScroller.items[s].content=e,this.virtualScroller.updateItem(s,{content:e}))}else this._messagesArea.querySelector(".quikchat-msgid-".concat(String(t).padStart(10,"0"))).lastChild.innerHTML=this._sanitizeContent(e);i=!0,this._onMessageReplace&&this._onMessageReplace(this,t,e)}catch(e){console.log("".concat(String(t)," : Message ID not found"))}return i}},{key:"messageScrollToBottom",value:function(){this._messagesArea.scrollTop=this._messagesArea.scrollHeight}},{key:"messageRemoveLast",value:function(){if(this._history.length>=0){var t=this._history[this._history.length-1].msgid;return this.messageRemove(t)}return!1}},{key:"messageSetVisibility",value:function(t,e){var i=this._history.find((function(e){return e.msgid===t}));return!(!i||!i.messageDiv)&&(i.messageDiv.style.display=e?"":"none",i.visible=e,this._updateMessageStyles(),!0)}},{key:"messageGetVisibility",value:function(t){var e=this._history.find((function(e){return e.msgid===t}));return!(!e||!e.messageDiv)&&"none"!==e.messageDiv.style.display}},{key:"_updateMessageStyles",value:function(){l(this._messagesArea.children).filter((function(t){return"none"!==t.style.display})).forEach((function(t,e){t.classList.remove("quikchat-message-1","quikchat-message-2"),t.classList.add(e%2==0?"quikchat-message-1":"quikchat-message-2")}))}},{key:"_handleShortLongMessageCSS",value:function(t,e){t.classList.remove("left-singleline","left-multiline","center-singleline","center-multiline","right-singleline","right-multiline");var i=t.lastChild;window.lastDiv=i;var n,s=window.getComputedStyle(i),a=i.offsetHeight;"normal"===s.lineHeight?n=1.2*parseFloat(s.fontSize):n=parseFloat(s.lineHeight);var r=a>n;switch(e){case"center":r?t.classList.add("center-multiline"):t.classList.add("center-singleline");break;case"right":r?t.classList.add("right-multiline"):t.classList.add("right-singleline");break;default:r?t.classList.add("left-multiline"):t.classList.add("left-singleline")}}},{key:"historyGet",value:function(t,e){return null==t&&(t=0,e=this._history.length),void 0===e&&(e=t<0?e:t+1),this._history.slice(t,e)}},{key:"historyGetAllCopy",value:function(){return this._history.slice()}},{key:"historyGetPage",value:function(){var t,e,i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:50,s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"asc",a=this._history.length,r=Math.ceil(a/n),l=Math.max(1,Math.min(i,r||1));"desc"===s?(t=Math.max(0,a-l*n),e=a-(l-1)*n):(t=(l-1)*n,e=Math.min(t+n,a));var o=this._history.slice(t,e);return"desc"===s&&o.reverse(),{messages:o,pagination:{currentPage:l,pageSize:n,totalPages:r,totalMessages:a,hasNext:l<r,hasPrevious:l>1,order:s}}}},{key:"historySearch",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=this._history;if(t.text){var i=t.text.toLowerCase();e=e.filter((function(t){return t.content.toLowerCase().includes(i)}))}t.userString&&(e=e.filter((function(e){return e.userString===t.userString}))),t.role&&(e=e.filter((function(e){return e.role===t.role}))),t.tags&&t.tags.length>0&&(e=e.filter((function(e){return e.tags&&e.tags.some((function(e){return t.tags.includes(e)}))})));var n=t.limit||100;return e.length>n&&(e=e.slice(0,n)),e}},{key:"historyGetInfo",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:50,e=this._history.length;return{totalMessages:e,totalPages:Math.ceil(e/t),oldestMessage:e>0?{msgid:this._history[0].msgid,timestamp:this._history[0].timestamp,userString:this._history[0].userString}:null,newestMessage:e>0?{msgid:this._history[e-1].msgid,timestamp:this._history[e-1].timestamp,userString:this._history[e-1].userString}:null,memoryUsage:{estimatedSize:JSON.stringify(this._history).length,averageMessageSize:e>0?Math.round(JSON.stringify(this._history).length/e):0}}}},{key:"historyClear",value:function(){this.msgid=0,this.virtualScroller?this.virtualScroller.clear():this._messagesArea.innerHTML="",this._history=[],this._activeTags.clear()}},{key:"historyGetLength",value:function(){return this._history.length}},{key:"historyGetMessage",value:function(t){return t>=0&&t<this._history.length?this._history[t]:{}}},{key:"historyGetMessageContent",value:function(t){return t>=0&&t<this._history.length?this._history[t].content:""}},{key:"historyRestoreAll",value:function(t){var e=this;this.historyClear(),this._messagesArea.innerHTML="",t.forEach((function(t){e.messageAddFull(t)}))}},{key:"changeTheme",value:function(t){this._chatWidget.classList.remove(this._theme),this._chatWidget.classList.add(t),this._theme=t}},{key:"theme",get:function(){return this._theme}},{key:"setTagVisibility",value:function(t,e){if("string"!=typeof t||!/^[a-zA-Z0-9-]+$/.test(t))return!1;var i="quikchat-show-tag-".concat(t);return e?this._chatWidget.classList.add(i):this._chatWidget.classList.remove(i),this._updateMessageStyles(),!0}},{key:"getTagVisibility",value:function(t){return!("string"!=typeof t||!/^[a-zA-Z0-9-]+$/.test(t))&&this._chatWidget.classList.contains("quikchat-show-tag-".concat(t))}},{key:"getActiveTags",value:function(){return Array.from(this._activeTags)}},{key:"isVirtualScrollingEnabled",value:function(){return this.virtualScrollingEnabled&&null!==this.virtualScroller}},{key:"getVirtualScrollingConfig",value:function(){return{enabled:this.virtualScrollingEnabled,active:null!==this.virtualScroller,threshold:this.virtualScrollingThreshold}}},{key:"setLanguage",value:function(t,e){this.lang=t,e&&(this.translations[t]=r(r({},this.translations[t]),e)),this.currentTranslations=this.translations[t]||this.translations.en,this._updateUITranslations()}},{key:"getLanguage",value:function(){return this.lang}},{key:"setDirection",value:function(t){"ltr"!==t&&"rtl"!==t||(this.dir=t,this._chatWidget.setAttribute("dir",t))}},{key:"getDirection",value:function(){return this.dir}},{key:"_updateUITranslations",value:function(){this._sendButton&&(this._sendButton.textContent=this.currentTranslations.sendButton||"Send"),this._textEntry&&(this._textEntry.placeholder=this.currentTranslations.inputPlaceholder||"Type a message..."),this._chatWidget&&this._chatWidget.setAttribute("lang",this.lang)}},{key:"setSanitizer",value:function(t){null===t||"function"==typeof t?this._sanitizer=t:console.warn("Sanitizer must be a function or null")}},{key:"getSanitizer",value:function(){return this._sanitizer}},{key:"_sanitizeContent",value:function(t){return this._sanitizer&&"function"==typeof this._sanitizer?this._sanitizer(t):t}}],[{key:"version",value:function(){return h}},{key:"loremIpsum",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0,i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],n="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ";for("number"!=typeof t&&(t=Math.floor(150*Math.random())+25),void 0===e&&(e=Math.floor(446*Math.random())),e%=446;" "===n[e]||/[.,:;!?]/.test(n[e]);)e=(e+1)%446;var s=n.substring(e)+n.substring(0,e);"number"!=typeof t&&(t=s.length);for(var a="";t>0;)a+=t<s.length?s.substring(0,t):s,t-=s.length;if(" "===a[a.length-1]&&(a=a.substring(0,a.length-1)+"."),i){var r=a[0].toUpperCase();a=(r=/[A-Z]/.test(r)?r:"M")+a.substring(1)}return a}},{key:"tempMessageGenerator",value:function(t,e,i){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null;i=Math.max(i,100);var s=0;n&&"function"!=typeof n&&(n=null),n=n||function(t,e){return t+="."};var a=t;"string"==typeof a&&(a=document.querySelector(a));var r=a;if(r){r.innerHTML=e;var l=e,o=setInterval((function(){r.innerHTML===l?(l=String(n(l,s)),s++,r.innerHTML=l):clearInterval(o)}),i)}}},{key:"createTempMessageDOMStr",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1e3,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};e=Math.max(e,100),i&&"function"!=typeof i&&(i=null),i=i||function(t,e){return t+"."};var s=n.containerClass?n.containerClass:"",a="tempMsg_"+Date.now()+"_"+Math.floor(1e6*Math.random());return'\n <span id="'.concat(a,'" ').concat(s?'class="'.concat(s,'"'):"",">\n ").concat(t,'\n </span>\n <script>\n (function(){\n // Get our container element by its unique id.\n var container = document.getElementById("').concat(a,'");\n if (!container) return;\n var count = 0;\n var currentMsg = container.innerHTML;\n var interval = ').concat(e,";\n // Convert the callback function into its string representation.\n var cb = ").concat(i.toString(),";\n var intervalId = setInterval(function(){\n // If the content has been replaced, stop updating.\n if(container.innerHTML !== currentMsg){\n clearInterval(intervalId);\n return;\n }\n // Use the callback to generate the new message.\n currentMsg = String(cb(currentMsg, count));\n count++;\n container.innerHTML = currentMsg;\n }, interval);\n })();\n <\/script>\n ")}}])}();s(c,"sanitizers",{escapeHTML:function(t){return"string"!=typeof t?t:t.replace(/[&<>"']/g,(function(t){return{"&":"&","<":"<",">":">",'"':""","'":"'"}[t]}))},stripHTML:function(t){return"string"!=typeof t?t:t.replace(/<[^>]*>/g,"")}}),module.exports=c;
|
|
1
|
+
"use strict";function e(e,t){(null==t||t>e.length)&&(t=e.length);for(var s=0,i=Array(t);s<t;s++)i[s]=e[s];return i}function t(e,t){for(var s=0;s<t.length;s++){var i=t[s];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,n(i.key),i)}}function s(t,s){var i="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!i){if(Array.isArray(t)||(i=function(t,s){if(t){if("string"==typeof t)return e(t,s);var i={}.toString.call(t).slice(8,-1);return"Object"===i&&t.constructor&&(i=t.constructor.name),"Map"===i||"Set"===i?Array.from(t):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?e(t,s):void 0}}(t))||s){i&&(t=i);var a=0,r=function(){};return{s:r,n:function(){return a>=t.length?{done:!0}:{done:!1,value:t[a++]}},e:function(e){throw e},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var n,o=!0,l=!1;return{s:function(){i=i.call(t)},n:function(){var e=i.next();return o=e.done,e},e:function(e){l=!0,n=e},f:function(){try{o||null==i.return||i.return()}finally{if(l)throw n}}}}function i(e,t,s){return(t=n(t))in e?Object.defineProperty(e,t,{value:s,enumerable:!0,configurable:!0,writable:!0}):e[t]=s,e}function a(e,t){var s=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),s.push.apply(s,i)}return s}function r(e){for(var t=1;t<arguments.length;t++){var s=null!=arguments[t]?arguments[t]:{};t%2?a(Object(s),!0).forEach((function(t){i(e,t,s[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(s)):a(Object(s)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(s,t))}))}return e}function n(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var s=e[Symbol.toPrimitive];if(void 0!==s){var i=s.call(e,t);if("object"!=typeof i)return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e,"string");return"symbol"==typeof t?t:t+""}var o=function(){return e=function e(t){var s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:function(){},i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e);var a=r(r({},{theme:"quikchat-theme-light",trackHistory:!0,showTimestamps:!1,titleArea:{title:"Chat",show:!1,align:"center"},messagesArea:{alternating:!0}}),i);"string"==typeof t&&(t=document.querySelector(t)),this._parentElement=t,this._theme=a.theme,this._onSend=s||function(){},this._messageFormatter=a.messageFormatter||null,this._sanitize=a.sanitize||!1,this._createWidget(),a.titleArea&&(this.titleAreaSetContents(a.titleArea.title,a.titleArea.align),!0===a.titleArea.show?this.titleAreaShow():this.titleAreaHide()),a.messagesArea&&this.messagesAreaAlternateColors(a.messagesArea.alternating),a.showTimestamps&&this.messagesAreaShowTimestamps(!0),a.direction&&this.setDirection(a.direction),this._attachEventListeners(),this.trackHistory=!1!==a.trackHistory,this._historyLimit=1e7,this._history=[]},i=[{key:"_createWidget",value:function(){var e='\n <div class="quikchat-base '.concat(this.theme,'">\n <div class="quikchat-title-area"></div>\n <div class="quikchat-messages-wrapper"><div class="quikchat-messages-area" role="log" aria-live="polite" aria-label="Chat messages"></div><button class="quikchat-scroll-bottom" aria-label="Scroll to bottom"></button></div>\n <div class="quikchat-input-area">\n <textarea class="quikchat-input-textbox" rows="1" aria-label="Type a message"></textarea>\n <button class="quikchat-input-send-btn">Send</button>\n </div>\n </div>\n ');this._parentElement.innerHTML=e,this._chatWidget=this._parentElement.querySelector(".quikchat-base"),this._titleArea=this._chatWidget.querySelector(".quikchat-title-area"),this._messagesWrapper=this._chatWidget.querySelector(".quikchat-messages-wrapper"),this._messagesArea=this._chatWidget.querySelector(".quikchat-messages-area"),this._scrollBottomBtn=this._messagesWrapper.querySelector(".quikchat-scroll-bottom"),this._inputArea=this._chatWidget.querySelector(".quikchat-input-area"),this._textEntry=this._inputArea.querySelector(".quikchat-input-textbox"),this._sendButton=this._inputArea.querySelector(".quikchat-input-send-btn"),this.msgid=0}},{key:"_attachEventListeners",value:function(){var e=this;this._sendButton.addEventListener("click",(function(){var t=e._textEntry.value.trim();""!==t&&e._onSend(e,t)})),this._textEntry.addEventListener("keydown",(function(t){if(t.shiftKey&&13===t.keyCode){t.preventDefault();var s=e._textEntry.value.trim();if(""===s)return;e._onSend(e,s)}})),this._textEntry.addEventListener("input",(function(){return e._autoGrowTextarea()})),this._messagesArea.addEventListener("scroll",(function(){var t=e._messagesArea,s=t.scrollTop,i=t.scrollHeight,a=t.clientHeight;e.userScrolledUp=s+a<i-1,e._updateScrollBottomBtn()})),this._scrollBottomBtn.addEventListener("click",(function(){return e.scrollToBottom()})),this._chatWidget.addEventListener("keydown",(function(t){t.ctrlKey&&"End"===t.key&&(t.preventDefault(),e.scrollToBottom())})),"undefined"!=typeof ResizeObserver&&(this._resizeObserver=new ResizeObserver((function(){return e._handleContainerResize()})),this._resizeObserver.observe(this._parentElement))}},{key:"setCallbackOnSend",value:function(e){this._onSend=e}},{key:"setCallbackonMessageAdded",value:function(e){this._onMessageAdded=e}},{key:"setCallbackonMessageAppend",value:function(e){this._onMessageAppend=e}},{key:"setCallbackonMessageReplace",value:function(e){this._onMessageReplace=e}},{key:"setCallbackonMessageDelete",value:function(e){this._onMessageDelete=e}},{key:"titleAreaToggle",value:function(){"none"===this._titleArea.style.display?this.titleAreaShow():this.titleAreaHide()}},{key:"titleAreaShow",value:function(){this._titleArea.style.display=""}},{key:"titleAreaHide",value:function(){this._titleArea.style.display="none"}},{key:"titleAreaSetContents",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"center";this._titleArea.innerHTML=e,this._titleArea.style.textAlign=t}},{key:"titleAreaGetContents",value:function(){return this._titleArea.innerHTML}},{key:"inputAreaToggle",value:function(){"none"===this._inputArea.style.display?this.inputAreaShow():this.inputAreaHide()}},{key:"inputAreaShow",value:function(){this._inputArea.style.display=""}},{key:"inputAreaHide",value:function(){this._inputArea.style.display="none"}},{key:"inputAreaSetEnabled",value:function(e){this._textEntry.disabled=!e,this._sendButton.disabled=!e}},{key:"inputAreaSetButtonText",value:function(e){this._sendButton.textContent=e}},{key:"inputAreaGetButtonText",value:function(){return this._sendButton.textContent}},{key:"setDirection",value:function(e){var t="rtl"===e?"rtl":"ltr";this._chatWidget.setAttribute("dir",t),"rtl"===t?this._chatWidget.classList.add("quikchat-rtl"):this._chatWidget.classList.remove("quikchat-rtl")}},{key:"getDirection",value:function(){return this._chatWidget.getAttribute("dir")||"ltr"}},{key:"_handleContainerResize",value:function(){}},{key:"scrollToBottom",value:function(){this._messagesArea.scrollTop=this._messagesArea.scrollHeight,this.userScrolledUp=!1,this._updateScrollBottomBtn()}},{key:"_updateScrollBottomBtn",value:function(){this.userScrolledUp?this._scrollBottomBtn.classList.add("quikchat-scroll-bottom-visible"):this._scrollBottomBtn.classList.remove("quikchat-scroll-bottom-visible")}},{key:"_autoGrowTextarea",value:function(){var e=this._textEntry;e.style.height="auto";var t=parseInt(getComputedStyle(e).getPropertyValue("--quikchat-input-max-height"))||120;e.style.height=Math.min(e.scrollHeight,t)+"px",e.style.overflowY=e.scrollHeight>t?"auto":"hidden"}},{key:"_formatTimestamp",value:function(e){var t=new Date(e),s=t.getHours();return(s%12||12)+":"+String(t.getMinutes()).padStart(2,"0")+" "+(s>=12?"PM":"AM")}},{key:"messagesAreaShowTimestamps",value:function(e){e?this._messagesArea.classList.add("quikchat-show-timestamps"):this._messagesArea.classList.remove("quikchat-show-timestamps")}},{key:"messagesAreaShowTimestampsGet",value:function(){return this._messagesArea.classList.contains("quikchat-show-timestamps")}},{key:"messagesAreaShowTimestampsToggle",value:function(){this._messagesArea.classList.toggle("quikchat-show-timestamps")}},{key:"_escapeHTML",value:function(e){var t=document.createElement("div");return t.textContent=e,t.innerHTML}},{key:"_processContent",value:function(e){return!0===this._sanitize?e=this._escapeHTML(e):"function"==typeof this._sanitize&&(e=this._sanitize(e)),this._messageFormatter&&(e=this._messageFormatter(e)),e}},{key:"messagesAreaAlternateColors",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];return e?this._messagesArea.classList.add("quikchat-messages-area-alt"):this._messagesArea.classList.remove("quikchat-messages-area-alt"),!0===e}},{key:"messagesAreaAlternateColorsToggle",value:function(){this._messagesArea.classList.toggle("quikchat-messages-area-alt")}},{key:"messagesAreaAlternateColorsGet",value:function(){return this._messagesArea.classList.contains("quikchat-messages-area-alt")}},{key:"messageAddFull",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{content:"",userString:"user",align:"right",role:"user",userID:-1},t=this.msgid,s=document.createElement("div"),i="quikchat-msgid-"+String(t).padStart(10,"0");s.classList.add("quikchat-message",i),s.classList.add("quikchat-role-"+(e.role||"user")),s.classList.add("quikchat-align-"+(e.align||"right")),this.msgid++,s.classList.add(this._messagesArea.children.length%2==1?"quikchat-message-1":"quikchat-message-2");var a=!1!==e.visible;a||(s.style.display="none");var n=Array.isArray(e.tags)?e.tags.slice():[],o=document.createElement("div");o.classList.add("quikchat-user-label"),o.style.textAlign=e.align,o.innerHTML=e.userString;var l=document.createElement("div");l.classList.add("quikchat-message-content"),l.style.textAlign=e.align,l.innerHTML=this._processContent(e.content);var u=(new Date).toISOString(),c=document.createElement("span");c.classList.add("quikchat-timestamp"),c.textContent=this._formatTimestamp(u),s.appendChild(o),s.appendChild(l),s.appendChild(c),this._messagesArea.appendChild(s),this.userScrolledUp||(this._messagesArea.scrollTop=this._messagesArea.scrollHeight),this._textEntry.value="",this._autoGrowTextarea();var h=u;return this.trackHistory&&(this._history.push(r(r({msgid:t},e),{},{visible:a,tags:n,timestamp:u,updatedtime:h,messageDiv:s})),this._history.length>this._historyLimit&&this._history.shift()),this._onMessageAdded&&this._onMessageAdded(this,t),t}},{key:"messageAddNew",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"user",s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"right",i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"user";return this.messageAddFull({content:e,userString:t,align:s,role:i})}},{key:"messageRemove",value:function(e){var t=!1;try{this._messagesArea.removeChild(this._messagesArea.querySelector(".quikchat-msgid-".concat(String(e).padStart(10,"0")))),t=!0}catch(e){}return t&&(this._history.splice(this._history.findIndex((function(t){return t.msgid===e})),1),this._onMessageDelete&&this._onMessageDelete(this,e)),t}},{key:"messageGetDOMObject",value:function(e){var t=null;try{t=this._messagesArea.querySelector(".quikchat-msgid-".concat(String(e).padStart(10,"0")))}catch(e){}return t}},{key:"messageGetContent",value:function(e){var t="";try{t=this._history.filter((function(t){return t.msgid===e}))[0].content}catch(e){}return t}},{key:"messageSetVisible",value:function(e,t){var s=this.messageGetDOMObject(e);if(!s)return!1;s.style.display=t?"":"none";var i=this._history.find((function(t){return t.msgid===e}));return i&&(i.visible=t),!0}},{key:"messageGetVisible",value:function(e){var t=this._history.find((function(t){return t.msgid===e}));return!!t&&!1!==t.visible}},{key:"messageToggleVisible",value:function(e){var t=this.messageGetVisible(e);return this.messageSetVisible(e,!t)}},{key:"messageSetVisibleByTag",value:function(e,t){var i,a=0,r=s(this._history);try{for(r.s();!(i=r.n()).done;){var n=i.value;n.tags&&n.tags.includes(e)&&(this.messageSetVisible(n.msgid,t),a++)}}catch(e){r.e(e)}finally{r.f()}return a}},{key:"messageGetTags",value:function(e){var t=this._history.find((function(t){return t.msgid===e}));return t&&t.tags?t.tags.slice():[]}},{key:"messageSetTags",value:function(e,t){var s=this._history.find((function(t){return t.msgid===e}));return!!s&&(s.tags=Array.isArray(t)?t.slice():[],!0)}},{key:"messageAppendContent",value:function(e,t){var s=!1;try{var i=this._messagesArea.querySelector(".quikchat-msgid-".concat(String(e).padStart(10,"0"))),a=this._history.filter((function(t){return t.msgid===e}))[0];a.content+=t,a.updatedtime=(new Date).toISOString(),i.querySelector(".quikchat-message-content").innerHTML=this._processContent(a.content),i.classList.remove("quikchat-typing"),s=!0,this.userScrolledUp||(this._messagesArea.scrollTop=this._messagesArea.scrollHeight),this._onMessageAppend&&this._onMessageAppend(this,e,t)}catch(e){}return s}},{key:"messageReplaceContent",value:function(e,t){var s=!1;try{var i=this._messagesArea.querySelector(".quikchat-msgid-".concat(String(e).padStart(10,"0"))),a=this._history.filter((function(t){return t.msgid===e}))[0];a.content=t,a.updatedtime=(new Date).toISOString(),i.querySelector(".quikchat-message-content").innerHTML=this._processContent(t),i.classList.remove("quikchat-typing"),s=!0,this.userScrolledUp||(this._messagesArea.scrollTop=this._messagesArea.scrollHeight),this._onMessageReplace&&this._onMessageReplace(this,e,t)}catch(e){}return s}},{key:"messageAddTypingIndicator",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"left",s=this.messageAddFull({content:"",userString:e,align:t,role:"assistant"}),i=this.messageGetDOMObject(s);return i.classList.add("quikchat-typing"),i.querySelector(".quikchat-message-content").innerHTML='<span class="quikchat-typing-dots"><span>.</span><span>.</span><span>.</span></span>',s}},{key:"setMessageFormatter",value:function(e){this._messageFormatter=e}},{key:"setSanitize",value:function(e){this._sanitize=e}},{key:"historyGet",value:function(e,t){return void 0===e?this._history.slice():void 0===t?e<0?this._history.slice(e):this._history.slice(e,e+1):this._history.slice(e,t)}},{key:"historyClear",value:function(){this.msgid=0,this._history=[]}},{key:"historyGetLength",value:function(){return this._history.length}},{key:"historyGetMessage",value:function(e){return e>=0&&e<this._history.length?this._history[e]:{}}},{key:"historyGetMessageContent",value:function(e){return e>=0&&e<this._history.length?this._history[e].content:""}},{key:"historyExport",value:function(){return this._history.map((function(e){return{msgid:e.msgid,content:e.content,userString:e.userString,align:e.align,role:e.role,userID:e.userID,visible:e.visible,tags:e.tags?e.tags.slice():[],timestamp:e.timestamp,updatedtime:e.updatedtime}}))}},{key:"historyImport",value:function(e){this._messagesArea.innerHTML="",this._history=[],this.msgid=0;var t,i=s(e);try{for(i.s();!(t=i.n()).done;){var a=t.value;this.messageAddFull({content:a.content||"",userString:a.userString||"user",align:a.align||"right",role:a.role||"user",userID:a.userID,visible:a.visible,tags:a.tags})}}catch(e){i.e(e)}finally{i.f()}}},{key:"changeTheme",value:function(e){this._chatWidget.classList.remove(this._theme),this._chatWidget.classList.add(e),this._theme=e}},{key:"theme",get:function(){return this._theme}}],a=[{key:"version",value:function(){return{version:"1.2.4",license:"BSD-2",url:"https://github/deftio/quikchat"}}},{key:"loremIpsum",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0,s=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],i="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ";for("number"!=typeof e&&(e=Math.floor(126*Math.random())+25),void 0===t&&(t=Math.floor(446*Math.random())),t%=446;" "===i[t]||/[.,:;!?]/.test(i[t]);)t=(t+1)%446;for(var a=i.substring(t)+i.substring(0,t),r="";e>0;)r+=e<a.length?a.substring(0,e):a,e-=a.length;return" "===r[r.length-1]&&(r=r.substring(0,r.length-1)+"."),s&&(r=r[0].toUpperCase()+r.substring(1)),r}}],i&&t(e.prototype,i),a&&t(e,a),Object.defineProperty(e,"prototype",{writable:!1}),e;var e,i,a}();module.exports=o;
|
|
2
2
|
//# sourceMappingURL=quikchat.cjs.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quikchat.cjs.min.js","sources":["../src/quikchat_version.js","../src/quikchat.js"],"sourcesContent":["// Auto-generated version file - DO NOT EDIT MANUALLY\n// This file is automatically updated by tools/updateVersion.js\n\nexport const quikchatVersion = {\n version: \"1.1.17\",\n license: \"BSD-2\",\n url: \"https://github/deftio/quikchat\",\n fun: true\n};\n\nexport default quikchatVersion;","import { quikchatVersion } from './quikchat_version.js';\n\n/**\n * Simplified virtual scrolling implementation for QuikChat\n * @private\n */\nclass SimpleVirtualScroller {\n constructor(container, options = {}) {\n this.container = container;\n this.items = [];\n this.itemHeight = options.itemHeight || 80; // Default/estimate height\n this.buffer = options.buffer || 5;\n this.visibleRange = { start: 0, end: 0 };\n this.renderedElements = new Map();\n this.itemHeights = new Map(); // Cache actual heights\n this.itemPositions = new Map(); // Cache positions\n this.totalHeight = 0;\n this.onRenderItem = options.onRenderItem || (() => {});\n this.sanitizer = options.sanitizer || null; // Content sanitizer\n \n this._initStructure();\n this._attachScrollListener();\n }\n \n _initStructure() {\n const existingClasses = this.container.className;\n this.container.innerHTML = '';\n this.container.className = existingClasses;\n this.container.style.position = 'relative';\n this.container.style.overflow = 'auto';\n \n // Ensure container has height\n if (this.container.offsetHeight === 0) {\n // Try to get height from computed style or parent\n const computedHeight = window.getComputedStyle(this.container).height;\n if (computedHeight === '0px' || computedHeight === 'auto') {\n // If still no height, use a reasonable default\n this.container.style.height = '400px';\n console.warn('QuikChat Virtual Scrolling: Container has no height, setting to 400px');\n }\n }\n \n this.spacer = document.createElement('div');\n this.spacer.style.cssText = 'position: absolute; top: 0; left: 0; width: 1px; pointer-events: none; z-index: -1;';\n \n this.content = document.createElement('div');\n this.content.style.cssText = 'position: relative; width: 100%;';\n \n this.container.appendChild(this.spacer);\n this.container.appendChild(this.content);\n \n // Initial render after structure is set up\n setTimeout(() => {\n this._updateVisibleRange();\n this._renderVisibleItems();\n }, 0);\n }\n \n _attachScrollListener() {\n let ticking = false;\n this.container.addEventListener('scroll', () => {\n if (!ticking) {\n requestAnimationFrame(() => {\n this._updateVisibleRange();\n this._renderVisibleItems();\n ticking = false;\n });\n ticking = true;\n }\n });\n }\n \n _getItemHeight(index) {\n // Return cached height or estimate\n return this.itemHeights.get(index) || this.itemHeight;\n }\n \n _getItemPosition(index) {\n // Return cached position or calculate\n if (this.itemPositions.has(index)) {\n return this.itemPositions.get(index);\n }\n \n // Calculate position based on previous items\n let position = 0;\n for (let i = 0; i < index; i++) {\n position += this._getItemHeight(i);\n }\n \n this.itemPositions.set(index, position);\n return position;\n }\n \n _recalculatePositions(fromIndex) {\n // Recalculate positions from a specific index onwards\n let position = fromIndex > 0 ? this._getItemPosition(fromIndex) : 0;\n \n for (let i = fromIndex; i < this.items.length; i++) {\n this.itemPositions.set(i, position);\n position += this._getItemHeight(i);\n \n // Update position of rendered elements\n const element = this.renderedElements.get(i);\n if (element) {\n element.style.top = `${this.itemPositions.get(i)}px`;\n }\n }\n \n // Update total height\n this.totalHeight = position;\n this.spacer.style.height = `${this.totalHeight}px`;\n }\n \n _updateVisibleRange() {\n const scrollTop = this.container.scrollTop;\n const viewportHeight = this.container.clientHeight;\n \n // If container has no height, don't render anything (avoid infinite loop)\n if (viewportHeight === 0) {\n this.visibleRange = { start: 0, end: 0 };\n return;\n }\n \n // Find first visible item based on positions\n let startIndex = 0;\n let endIndex = this.items.length;\n \n // Use cached positions when available\n if (this.itemPositions.size > 0) {\n // Find start index\n for (let i = 0; i < this.items.length; i++) {\n const pos = this._getItemPosition(i);\n if (pos + this._getItemHeight(i) > scrollTop) {\n startIndex = Math.max(0, i - this.buffer);\n break;\n }\n }\n \n // Find end index\n for (let i = startIndex; i < this.items.length; i++) {\n const pos = this._getItemPosition(i);\n if (pos > scrollTop + viewportHeight) {\n endIndex = Math.min(this.items.length, i + this.buffer);\n break;\n }\n }\n } else {\n // Fallback to estimate if no positions cached yet\n startIndex = Math.max(0, Math.floor(scrollTop / this.itemHeight) - this.buffer);\n endIndex = Math.min(this.items.length, Math.ceil((scrollTop + viewportHeight) / this.itemHeight) + this.buffer);\n }\n \n this.visibleRange = { start: startIndex, end: endIndex };\n }\n \n _renderVisibleItems() {\n const { start, end } = this.visibleRange;\n \n // Remove elements outside range\n this.renderedElements.forEach((element, index) => {\n if (index < start || index >= end) {\n element.remove();\n this.renderedElements.delete(index);\n // Don't clear height cache - we might need it again\n }\n });\n \n // Add new visible elements\n for (let i = start; i < end; i++) {\n const item = this.items[i];\n if (!item || this.renderedElements.has(i)) continue;\n \n const element = this._createItemElement(item, i);\n element.style.position = 'absolute';\n element.style.top = `${this._getItemPosition(i)}px`;\n element.style.left = '0';\n element.style.right = '0';\n \n this.renderedElements.set(i, element);\n this.content.appendChild(element);\n \n // Measure actual height after rendering\n requestAnimationFrame(() => {\n if (this.renderedElements.has(i)) {\n const actualHeight = element.offsetHeight;\n if (actualHeight && actualHeight !== this._getItemHeight(i)) {\n this.itemHeights.set(i, actualHeight);\n this._recalculatePositions(i);\n }\n }\n });\n }\n \n this.onRenderItem(this.content);\n }\n \n _createItemElement(item, index) {\n const messageDiv = document.createElement('div');\n messageDiv.className = `quikchat-message quikchat-message-${item.align || 'left'} quikchat-msgid-${String(item.msgid).padStart(10, '0')}`;\n messageDiv.setAttribute('data-index', index);\n messageDiv.setAttribute('data-msgid', item.msgid);\n messageDiv.setAttribute('role', 'article');\n messageDiv.setAttribute('aria-label', `Message from ${item.userString || 'user'}`);\n \n if (item.tags && item.tags.length > 0) {\n item.tags.forEach(tag => messageDiv.classList.add(`quikchat-tag-${tag}`));\n }\n \n const userDiv = document.createElement('div');\n userDiv.className = 'quikchat-message-user';\n userDiv.innerHTML = this.sanitizer ? this.sanitizer(item.userString || '') : (item.userString || '');\n userDiv.setAttribute('aria-label', 'User');\n \n const contentDiv = document.createElement('div');\n contentDiv.className = 'quikchat-message-content';\n contentDiv.innerHTML = this.sanitizer ? this.sanitizer(item.content || '') : (item.content || '');\n contentDiv.setAttribute('aria-label', 'Message content');\n \n messageDiv.appendChild(userDiv);\n messageDiv.appendChild(contentDiv);\n \n if (!item.visible) {\n messageDiv.style.display = 'none';\n }\n \n return messageDiv;\n }\n \n addItem(item) {\n this.items.push(item);\n const index = this.items.length - 1;\n \n // Calculate position for new item\n const position = index > 0 ? \n this._getItemPosition(index - 1) + this._getItemHeight(index - 1) : 0;\n this.itemPositions.set(index, position);\n \n // Update total height (using estimate for new item)\n this.totalHeight = position + this.itemHeight;\n this.spacer.style.height = `${this.totalHeight}px`;\n \n if (index >= this.visibleRange.start && index < this.visibleRange.end) {\n this._renderVisibleItems();\n }\n \n if (item.scrollIntoView) {\n this.container.scrollTop = this.container.scrollHeight;\n }\n \n return index;\n }\n \n addItems(items) {\n // Batch add items for better performance\n const startLength = this.items.length;\n this.items.push(...items);\n \n // Calculate positions for new items\n let position = startLength > 0 ? \n this._getItemPosition(startLength - 1) + this._getItemHeight(startLength - 1) : 0;\n \n for (let i = startLength; i < this.items.length; i++) {\n this.itemPositions.set(i, position);\n position += this.itemHeight; // Use estimate for new items\n }\n \n this.totalHeight = position;\n this.spacer.style.height = `${this.totalHeight}px`;\n \n // Update visible range and render\n this._updateVisibleRange();\n this._renderVisibleItems();\n \n // Handle scrollIntoView for last item if needed\n if (items.length > 0 && items[items.length - 1].scrollIntoView) {\n this.container.scrollTop = this.container.scrollHeight;\n }\n }\n \n clear() {\n this.items = [];\n this.renderedElements.clear();\n this.itemHeights.clear();\n this.itemPositions.clear();\n this.totalHeight = 0;\n this.content.innerHTML = '';\n this.spacer.style.height = '0px';\n this.visibleRange = { start: 0, end: 0 };\n \n // Force update after clear\n this._updateVisibleRange();\n this._renderVisibleItems();\n }\n \n updateItem(index, updates) {\n if (index >= 0 && index < this.items.length) {\n this.items[index] = { ...this.items[index], ...updates };\n if (this.renderedElements.has(index)) {\n this._renderVisibleItems();\n }\n }\n }\n \n destroy() {\n this.container.innerHTML = '';\n this.items = [];\n this.renderedElements.clear();\n }\n}\n\n/**\n * QuikChat - A zero-dependency JavaScript chat widget for modern web applications\n * @class quikchat\n */\nclass quikchat {\n /**\n * Creates a new QuikChat instance\n * @constructor\n * @param {string|HTMLElement} parentElement - CSS selector or DOM element to attach the chat widget to\n * @param {Function} [onSend] - Callback function triggered when user sends a message\n * @param {Object} [options] - Configuration options\n * @param {string} [options.theme='quikchat-theme-light'] - CSS theme class name\n * @param {boolean} [options.trackHistory=true] - Whether to track message history\n * @param {Object} [options.titleArea] - Title area configuration\n * @param {string} [options.titleArea.title='Chat'] - Title text/HTML\n * @param {boolean} [options.titleArea.show=false] - Whether to show title area initially\n * @param {'left'|'center'|'right'} [options.titleArea.align='center'] - Title alignment\n * @param {Object} [options.messagesArea] - Messages area configuration\n * @param {boolean} [options.messagesArea.alternating=true] - Alternate message colors\n * @param {Object} [options.inputArea] - Input area configuration\n * @param {boolean} [options.inputArea.show=true] - Whether to show input area initially\n * @param {boolean} [options.sendOnEnter=true] - Send message on Enter key\n * @param {boolean} [options.sendOnShiftEnter=false] - Send message on Shift+Enter\n * @param {string} [options.instanceClass=''] - Additional CSS class for the widget instance\n * @example\n * // Basic usage\n * const chat = new quikchat('#chat-container', (instance, message) => {\n * console.log('User sent:', message);\n * });\n * \n * @example\n * // With options\n * const chat = new quikchat('#chat', handleMessage, {\n * theme: 'quikchat-theme-dark',\n * titleArea: { title: 'Support Chat', show: true },\n * sendOnEnter: false,\n * sendOnShiftEnter: true\n * });\n */\n constructor(parentElement, onSend = () => { }, options = {}) {\n const defaultOpts = {\n theme: 'quikchat-theme-light',\n trackHistory: true,\n titleArea: { title: \"Chat\", show: false, align: \"center\" },\n messagesArea: { alternating: true },\n inputArea: { show: true },\n sendOnEnter: true,\n sendOnShiftEnter: false,\n instanceClass: '',\n virtualScrolling: true, // Default to true for better performance\n virtualScrollingThreshold: 500, // Lower threshold since it performs so well\n // i18n support\n lang: 'en',\n dir: 'ltr', // 'ltr' or 'rtl'\n translations: {\n 'en': {\n sendButton: 'Send',\n inputPlaceholder: 'Type a message...',\n titleDefault: 'Chat'\n }\n },\n // Security: content sanitizer callback\n sanitizer: null // null = no sanitization (backward compatible)\n };\n const meta = { ...defaultOpts, ...options }; // merge options with defaults\n \n // Merge user translations with defaults\n if (options.translations) {\n meta.translations = { ...defaultOpts.translations, ...options.translations };\n }\n\n if (typeof parentElement === 'string') {\n parentElement = document.querySelector(parentElement);\n }\n //console.log(parentElement, meta);\n this._parentElement = parentElement;\n this._theme = meta.theme;\n this._onSend = onSend ? onSend : () => { }; // call back function for onSend\n \n // i18n settings\n this.lang = meta.lang;\n this.dir = meta.dir;\n this.translations = meta.translations;\n this.currentTranslations = this.translations[this.lang] || this.translations['en'];\n this._createWidget();\n\n if (meta.instanceClass) {\n this._chatWidget.classList.add(meta.instanceClass);\n }\n\n // title area\n if (meta.titleArea) {\n this.titleAreaSetContents(meta.titleArea.title, meta.titleArea.align);\n if (meta.titleArea.show === true) {\n this.titleAreaShow();\n } else {\n this.titleAreaHide();\n }\n }\n // messages area\n if (meta.messagesArea) {\n this.messagesAreaAlternateColors(meta.messagesArea.alternating);\n }\n\n // input area\n if (meta.inputArea) {\n if (meta.inputArea.show === true)\n this.inputAreaShow();\n else\n this.inputAreaHide();\n }\n // plumbing\n this._attachEventListeners();\n this.trackHistory = meta.trackHistory || true;\n this._historyLimit = 10000000;\n this._history = [];\n this._activeTags = new Set();\n\n // send on enter / shift enter\n this.sendOnEnter = meta.sendOnEnter;\n this.sendOnShiftEnter = meta.sendOnShiftEnter;\n \n // Virtual scrolling setup\n this.virtualScrollingEnabled = meta.virtualScrolling;\n this.virtualScrollingThreshold = meta.virtualScrollingThreshold;\n this.virtualScroller = null;\n \n // Sanitizer setup\n this._sanitizer = meta.sanitizer || null;\n \n // Don't initialize virtual scrolling immediately - wait for threshold\n // Virtual scrolling will be initialized when message count exceeds threshold\n }\n \n /**\n * Initialize virtual scrolling\n * @private\n */\n _initVirtualScrolling() {\n if (this.virtualScrollingEnabled && this._messagesArea && !this.virtualScroller) {\n // Check if we've hit the threshold (or about to with the next message)\n if (this._history.length >= this.virtualScrollingThreshold - 1) {\n this.virtualScroller = new SimpleVirtualScroller(this._messagesArea, {\n itemHeight: 80,\n buffer: 5,\n sanitizer: this._sanitizer, // Pass sanitizer to virtual scroller\n onRenderItem: (content) => {\n // Apply alternating colors if enabled\n if (this._messagesArea.classList.contains('quikchat-messages-area-alt')) {\n this._updateMessageStyles();\n }\n }\n });\n \n // Migrate existing messages to virtual scroller\n this._migrateToVirtualScrolling();\n }\n }\n }\n \n /**\n * Migrate existing messages to virtual scrolling\n * @private\n */\n _migrateToVirtualScrolling() {\n if (!this.virtualScroller) return;\n \n // Don't clear DOM here - virtual scroller will do it in _initStructure\n \n // Add all messages to virtual scroller\n const items = this._history.map(msg => ({\n msgid: msg.msgid,\n content: msg.content,\n userString: msg.userString,\n align: msg.align,\n role: msg.role,\n visible: msg.visible,\n tags: msg.tags || [],\n scrollIntoView: false\n }));\n \n this.virtualScroller.addItems(items);\n \n // Force a render in case container needs time to get dimensions\n setTimeout(() => {\n if (this.virtualScroller) {\n this.virtualScroller._updateVisibleRange();\n this.virtualScroller._renderVisibleItems();\n }\n }, 10);\n }\n\n _createWidget() {\n const sendButtonText = this.currentTranslations.sendButton || 'Send';\n const inputPlaceholder = this.currentTranslations.inputPlaceholder || 'Type a message...';\n \n const widgetHTML =\n `\n <div class=\"quikchat-base ${this._theme}\" dir=\"${this.dir}\" lang=\"${this.lang}\" role=\"region\" aria-label=\"Chat widget\">\n <div class=\"quikchat-title-area\" role=\"heading\" aria-level=\"2\">\n <span style=\"font-size: 1.5em; font-weight: 600;\">Title Area</span>\n </div>\n <div class=\"quikchat-messages-area\" role=\"log\" aria-live=\"polite\" aria-label=\"Chat messages\"></div>\n <div class=\"quikchat-input-area\" role=\"form\" aria-label=\"Message input\">\n <textarea class=\"quikchat-input-textbox\" \n placeholder=\"${inputPlaceholder}\"\n aria-label=\"Type your message\"\n autocomplete=\"off\"\n autocapitalize=\"sentences\"></textarea>\n <button class=\"quikchat-input-send-btn\" \n aria-label=\"Send message\"\n type=\"button\">${sendButtonText}</button>\n </div>\n </div>\n `;\n\n this._parentElement.innerHTML = widgetHTML;\n this._chatWidget = this._parentElement.querySelector('.quikchat-base');\n this._titleArea = this._chatWidget.querySelector('.quikchat-title-area');\n this._messagesArea = this._chatWidget.querySelector('.quikchat-messages-area');\n this._inputArea = this._chatWidget.querySelector('.quikchat-input-area');\n this._textEntry = this._inputArea.querySelector('.quikchat-input-textbox');\n this._sendButton = this._inputArea.querySelector('.quikchat-input-send-btn');\n this.msgid = 0;\n \n // Add mobile viewport handling\n this._setupMobileSupport();\n }\n\n /**\n * Setup mobile support - prevent zoom on input focus and handle virtual keyboard\n * @private\n */\n _setupMobileSupport() {\n // Prevent zoom on input focus for mobile\n let meta = document.querySelector('meta[name=\"viewport\"]');\n if (!meta) {\n meta = document.createElement('meta');\n meta.name = 'viewport';\n document.head.appendChild(meta);\n }\n \n // Store original content\n this._originalViewport = meta.content;\n \n // Prevent zoom on focus\n this._textEntry.addEventListener('focus', () => {\n if (window.innerWidth <= 768) { // Mobile device width\n meta.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0';\n }\n });\n \n this._textEntry.addEventListener('blur', () => {\n if (this._originalViewport) {\n meta.content = this._originalViewport;\n } else {\n meta.content = 'width=device-width, initial-scale=1.0';\n }\n });\n \n // Handle virtual keyboard resize\n if ('visualViewport' in window) {\n window.visualViewport.addEventListener('resize', () => {\n this._handleVirtualKeyboard();\n });\n }\n }\n \n /**\n * Handle virtual keyboard appearance/disappearance\n * @private\n */\n _handleVirtualKeyboard() {\n // Adjust layout when virtual keyboard appears\n const keyboardHeight = window.innerHeight - window.visualViewport.height;\n if (keyboardHeight > 0) {\n // Keyboard is visible - adjust chat widget height\n this._chatWidget.style.paddingBottom = `${keyboardHeight}px`;\n } else {\n // Keyboard hidden - restore original padding\n this._chatWidget.style.paddingBottom = '';\n }\n }\n\n /**\n * Attach event listeners to the widget\n */\n _attachEventListeners() {\n this._sendButton.addEventListener('click', (event) => { event.preventDefault(); this._onSend(this, this._textEntry.value.trim()) });\n window.addEventListener('resize', () => this._handleContainerResize());\n this._chatWidget.addEventListener('resize', () => this._handleContainerResize());\n this._textEntry.addEventListener('keydown', (event) => {\n\n // Check if Shift + Enter is pressed then we just do carraige\n if (event.shiftKey && event.keyCode === 13) {\n // Prevent default behavior (adding new line)\n if (this.sendOnShiftEnter) {\n event.preventDefault();\n this._onSend(this, this._textEntry.value.trim());\n }\n } else if (event.keyCode === 13) {// Enter but not Shift + Enter\n if (this.sendOnEnter) {\n event.preventDefault();\n this._onSend(this, this._textEntry.value.trim());\n }\n }\n });\n\n this._messagesArea.addEventListener('scroll', () => {\n const { scrollTop, scrollHeight, clientHeight } = this._messagesArea;\n this.userScrolledUp = scrollTop + clientHeight < scrollHeight;\n });\n }\n\n // set the onSend function callback.\n setCallbackOnSend(callback) {\n this._onSend = callback;\n }\n // set a callback for everytime a message is added (listener)\n setCallbackonMessageAdded(callback) {\n this._onMessageAdded = callback;\n }\n \n /**\n * Sets the callback function for when content is appended to a message\n * @param {Function} callback - Function to call when content is appended\n * @param {quikchat} callback.instance - The QuikChat instance\n * @param {number} callback.msgId - The ID of the message being appended to\n * @param {string} callback.content - The content being appended\n * @since 1.1.15\n * @example\n * chat.setCallbackonMessageAppend((instance, msgId, content) => {\n * console.log(`Appended \"${content}\" to message ${msgId}`);\n * });\n */\n setCallbackonMessageAppend(callback) {\n this._onMessageAppend = callback;\n }\n \n /**\n * Sets the callback function for when a message's content is replaced\n * @param {Function} callback - Function to call when content is replaced\n * @param {quikchat} callback.instance - The QuikChat instance\n * @param {number} callback.msgId - The ID of the message being replaced\n * @param {string} callback.content - The new content\n * @since 1.1.15\n * @example\n * chat.setCallbackonMessageReplace((instance, msgId, content) => {\n * console.log(`Message ${msgId} replaced with: ${content}`);\n * });\n */\n setCallbackonMessageReplace(callback) {\n this._onMessageReplace = callback;\n }\n \n /**\n * Sets the callback function for when a message is deleted\n * @param {Function} callback - Function to call when a message is deleted\n * @param {quikchat} callback.instance - The QuikChat instance\n * @param {number} callback.msgId - The ID of the deleted message\n * @since 1.1.15\n * @example\n * chat.setCallbackonMessageDelete((instance, msgId) => {\n * console.log(`Message ${msgId} was deleted`);\n * });\n */\n setCallbackonMessageDelete(callback) {\n this._onMessageDelete = callback;\n }\n\n // Public methods\n /**\n * Toggles the visibility of the title area\n * @returns {void}\n */\n titleAreaToggle() {\n this._titleArea.style.display === 'none' ? this.titleAreaShow() : this.titleAreaHide();\n }\n\n /**\n * Shows the title area\n * @returns {void}\n */\n titleAreaShow() {\n this._titleArea.style.display = '';\n this._adjustMessagesAreaHeight();\n }\n\n /**\n * Hides the title area\n * @returns {void}\n */\n titleAreaHide() {\n this._titleArea.style.display = 'none';\n this._adjustMessagesAreaHeight();\n }\n\n /**\n * Sets the contents of the title area\n * @param {string} title - HTML content to display in the title area\n * @param {'left'|'center'|'right'} [align='center'] - Text alignment\n * @returns {void}\n * @example\n * chat.titleAreaSetContents('<h2>Support Chat</h2>', 'center');\n */\n titleAreaSetContents(title, align = 'center') {\n this._titleArea.innerHTML = this._sanitizeContent(title);\n this._titleArea.style.textAlign = align;\n }\n\n /**\n * Gets the current contents of the title area\n * @returns {string} The HTML content of the title area\n */\n titleAreaGetContents() {\n return this._titleArea.innerHTML;\n }\n\n inputAreaToggle() {\n this._inputArea.classList.toggle('hidden');\n this._inputArea.style.display === 'none' ? this.inputAreaShow() : this.inputAreaHide();\n }\n\n inputAreaShow() {\n this._inputArea.style.display = '';\n this._adjustMessagesAreaHeight();\n }\n\n inputAreaHide() {\n this._inputArea.style.display = 'none';\n this._adjustMessagesAreaHeight();\n }\n\n _adjustMessagesAreaHeight() {\n const hiddenElements = [...this._chatWidget.children].filter(child => child.classList.contains('hidden'));\n const totalHiddenHeight = hiddenElements.reduce((sum, child) => sum + child.offsetHeight, 0);\n const containerHeight = this._chatWidget.offsetHeight;\n this._messagesArea.style.height = `calc(100% - ${containerHeight - totalHiddenHeight}px)`;\n }\n\n _handleContainerResize() {\n this._adjustMessagesAreaHeight();\n this._adjustSendButtonWidth();\n return true;\n }\n\n _adjustSendButtonWidth() {\n const sendButtonText = this._sendButton.textContent.trim();\n const fontSize = parseFloat(getComputedStyle(this._sendButton).fontSize);\n const minWidth = fontSize * sendButtonText.length + 16;\n this._sendButton.style.minWidth = `${minWidth}px`;\n return true;\n }\n\n //messagesArea functions\n messagesAreaAlternateColors(alt = true) {\n if (alt) {\n this._messagesArea.classList.add('quikchat-messages-area-alt');\n }\n else {\n this._messagesArea.classList.remove('quikchat-messages-area-alt');\n }\n return alt === true;\n }\n messagesAreaAlternateColorsToggle() {\n this._messagesArea.classList.toggle('quikchat-messages-area-alt');\n }\n messagesAreaAlternateColorsGet() {\n return this._messagesArea.classList.contains('quikchat-messages-area-alt');\n }\n /**\n * Adds a new message to the chat with full configuration options\n * @param {Object} input - Message configuration object\n * @param {string} [input.content=''] - Message content (HTML allowed)\n * @param {string} [input.userString='user'] - Display name for the message sender\n * @param {'left'|'right'|'center'} [input.align='right'] - Message alignment\n * @param {string} [input.role='user'] - Role identifier (user, assistant, system)\n * @param {number} [input.userID=-1] - User ID for the message\n * @param {string|false} [input.timestamp=false] - ISO timestamp or false for auto\n * @param {string|false} [input.updatedtime=false] - Last updated timestamp\n * @param {boolean|'smart'} [input.scrollIntoView=true] - Scroll behavior (true/false/'smart')\n * @param {boolean} [input.visible=true] - Whether message is initially visible\n * @param {string[]} [input.tags=[]] - Tags for message categorization\n * @returns {number} Message ID for the newly added message\n * @example\n * const msgId = chat.messageAddFull({\n * content: 'Hello!',\n * userString: 'Bot',\n * align: 'left',\n * scrollIntoView: 'smart',\n * tags: ['greeting']\n * });\n */\n messageAddFull(input = { content: \"\", userString: \"user\", align: \"right\", role: \"user\", userID: -1, timestamp: false, updatedtime: false, scrollIntoView: true, visible: true, tags: [] }) {\n const msgid = this.msgid;\n this.msgid++;\n let messageDiv = null; // Initialize messageDiv to null\n \n // Check if we should initialize virtual scrolling\n if (this.virtualScrollingEnabled && !this.virtualScroller && this._history.length >= this.virtualScrollingThreshold - 1) {\n this._initVirtualScrolling();\n }\n \n // If virtual scrolling is enabled, use the virtual scroller\n if (this.virtualScroller) {\n const messageData = {\n msgid: msgid,\n content: input.content,\n userString: input.userString,\n align: input.align,\n role: input.role,\n visible: input.visible !== undefined ? input.visible : true,\n tags: input.tags || [],\n scrollIntoView: input.scrollIntoView\n };\n \n // Add tags to active tags set\n if (Array.isArray(input.tags)) {\n input.tags.forEach(tag => {\n if (typeof tag === 'string' && /^[a-zA-Z0-9-]+$/.test(tag)) {\n this._activeTags.add(tag);\n }\n });\n }\n \n // Add to virtual scroller\n this.virtualScroller.addItem(messageData);\n \n // Clear text entry\n this._textEntry.value = '';\n this._adjustMessagesAreaHeight();\n } else {\n // Original DOM-based implementation\n messageDiv = document.createElement('div');\n const msgidClass = 'quikchat-msgid-' + String(msgid).padStart(10, '0');\n const userIdClass = 'quikchat-userid-' + String(input.userString).padStart(10, '0'); // hash this..\n messageDiv.classList.add('quikchat-message', msgidClass, 'quikchat-structure');\n messageDiv.setAttribute('role', 'article');\n messageDiv.setAttribute('aria-label', `Message from ${input.userString || 'user'}`);\n\n if (Array.isArray(input.tags)) {\n input.tags.forEach(tag => {\n if (typeof tag === 'string' && /^[a-zA-Z0-9-]+$/.test(tag)) {\n messageDiv.classList.add(`quikchat-tag-${tag}`);\n this._activeTags.add(tag);\n }\n });\n }\n\n const userDiv = document.createElement('div');\n userDiv.innerHTML = this._sanitizeContent(input.userString);\n userDiv.classList.add('quikchat-user-label');\n userDiv.style.textAlign = input.align;\n \n const contentDiv = document.createElement('div');\n contentDiv.classList.add('quikchat-message-content');\n \n // Determine text alignment for right-aligned messages\n if (input.align === \"right\") {\n const isMultiLine = input.content.includes(\"\\n\");\n const isLong = input.content.length > 50; // Adjust length threshold\n \n if (isMultiLine || isLong) {\n contentDiv.classList.add(\"quikchat-right-multiline\");\n } else {\n contentDiv.classList.add(\"quikchat-right-singleline\");\n }\n }\n \n contentDiv.innerHTML = this._sanitizeContent(input.content);\n \n messageDiv.appendChild(userDiv);\n messageDiv.appendChild(contentDiv);\n this._messagesArea.appendChild(messageDiv);\n \n if (input.visible === false) {\n messageDiv.style.display = 'none';\n }\n \n // Handle scroll behavior based on scrollIntoView parameter\n // 'smart' = only scroll if near bottom, true = always scroll, false = never scroll\n if (input.scrollIntoView === true) {\n this.messageScrollToBottom();\n } else if (input.scrollIntoView === 'smart' && !this.userScrolledUp) {\n this.messageScrollToBottom();\n }\n // If scrollIntoView is false, don't scroll at all\n \n this._textEntry.value = '';\n this._adjustMessagesAreaHeight();\n this._handleShortLongMessageCSS(messageDiv, input.align); // Handle CSS for short/long messages\n this._updateMessageStyles();\n }\n \n // Add timestamp now, unless it is passed in \n const timestamp = input.timestamp ? input.timestamp : new Date().toISOString();\n const updatedtime = input.updatedtime ? input.updatedtime : timestamp;\n const visible = input.visible !== undefined ? input.visible : true;\n \n if (this.trackHistory) {\n this._history.push({ msgid, ...input, visible, timestamp, updatedtime, messageDiv: messageDiv || null });\n if (this._history.length > this._historyLimit) {\n this._history.shift();\n }\n }\n \n if (this._onMessageAdded) {\n this._onMessageAdded(this, msgid);\n }\n \n return msgid;\n }\n \n\n\n /**\n * Adds a new message to the chat (simplified version of messageAddFull)\n * @param {string} [content=''] - Message content (HTML allowed)\n * @param {string} [userString='user'] - Display name for the message sender\n * @param {'left'|'right'|'center'} [align='right'] - Message alignment\n * @param {string} [role='user'] - Role identifier (user, assistant, system)\n * @param {boolean|'smart'} [scrollIntoView=true] - Scroll behavior\n * @param {boolean} [visible=true] - Whether message is initially visible\n * @param {string[]} [tags=[]] - Tags for message categorization\n * @returns {number} Message ID for the newly added message\n * @example\n * // Simple message\n * chat.messageAddNew('Hello!', 'User', 'right');\n * \n * // Bot message with smart scroll\n * chat.messageAddNew('Hi there!', 'Bot', 'left', 'assistant', 'smart');\n */\n messageAddNew(content = \"\", userString = \"user\", align = \"right\", role = \"user\", scrollIntoView = true, visible = true, tags = []) {\n let retvalue = this.messageAddFull(\n { content: content, userString: userString, align: align, role: role, scrollIntoView: scrollIntoView, visible: visible, tags: tags }\n );\n // this.messageScrollToBottom();\n return retvalue;\n }\n\n /**\n * Removes a message from the chat by its ID\n * @param {number} n - Message ID to remove\n * @returns {boolean} True if message was removed, false if not found\n * @example\n * const success = chat.messageRemove(5);\n */\n messageRemove(n) {\n // use css selector to remove the message\n let sucess = false;\n try {\n this._messagesArea.removeChild(this._messagesArea.querySelector(`.quikchat-msgid-${String(n).padStart(10, '0')}`));\n sucess = true;\n }\n catch (error) {\n console.log(`{String(n)} : Message ID not found`);\n }\n if (sucess) {\n // slow way to remove from history\n //this._history = this._history.filter((item) => item.msgid !== n); // todo make this more efficient\n\n // better way to delete this from history\n this._history.splice(this._history.findIndex((item) => item.msgid === n), 1);\n \n // Call the onMessageDelete callback if it exists\n if (this._onMessageDelete) {\n this._onMessageDelete(this, n);\n }\n }\n return sucess;\n }\n /* returns the message html object from the DOM\n */\n /**\n * Gets the DOM element for a message by its ID\n * @param {number} n - Message ID\n * @returns {HTMLElement|null} The message DOM element or null if not found\n */\n messageGetDOMObject(n) {\n let msg = null;\n // now use css selector to get the message \n try {\n msg = this._messagesArea.querySelector(`.quikchat-msgid-${String(n).padStart(10, '0')}`);\n }\n catch (error) {\n console.log(`{String(n)} : Message ID not found`);\n }\n return msg;\n }\n /* returns the message content only\n */\n /**\n * Gets the content of a message by its ID\n * @param {number} n - Message ID\n * @returns {string} The message content or empty string if not found\n */\n messageGetContent(n) {\n let content = \"\"\n // now use css selector to get the message \n try {\n // get from history..\n content = this._history.filter((item) => item.msgid === n)[0].content;\n //content = this._messagesArea.querySelector(`.quikchat-msgid-${String(n).padStart(10, '0')}`).lastChild.textContent;\n }\n catch (error) {\n console.log(`{String(n)} : Message ID not found`);\n }\n return content;\n }\n\n /* returns the DOM Content element of a given message\n */\n messageGetContentDOMElement(n) {\n let contentElement = null;\n // now use css selector to get the message\n try {\n //contentElement = this._messagesArea.querySelector(`.quikchat-msgid-${String(n).padStart(10, '0')}`).lastChild;\n contentElement = this._history.filter((item) => item.msgid === n)[0].messageDiv.lastChild;\n }\n catch (error) {\n console.log(`{String(n)} : Message ID not found`);\n }\n return contentElement;\n }\n\n /* append message to the message content\n */\n\n messageAppendContent(n, content) {\n let success = false;\n try {\n // Update history first\n let item = this._history.filter((item) => item.msgid === n)[0];\n item.content += content;\n item.updatedtime = new Date().toISOString();\n \n // If virtual scrolling is active, update the virtual scroller\n if (this.virtualScroller) {\n // Find the item index in virtual scroller\n const index = this.virtualScroller.items.findIndex(item => item.msgid === n);\n if (index >= 0) {\n this.virtualScroller.items[index].content += content; // Don't double-sanitize, it's done on render\n // Re-render if the item is currently visible\n this.virtualScroller.updateItem(index, { content: this.virtualScroller.items[index].content });\n }\n } else {\n // Regular DOM manipulation\n this._messagesArea.querySelector(`.quikchat-msgid-${String(n).padStart(10, '0')}`).lastChild.innerHTML += this._sanitizeContent(content);\n }\n \n success = true;\n \n // Call the onMessageAppend callback if it exists\n if (this._onMessageAppend) {\n this._onMessageAppend(this, n, content);\n }\n\n // Don't auto-scroll on append - let user control this\n // Users can call messageScrollToBottom() if they want to scroll\n } catch (error) {\n console.log(`${String(n)} : Message ID not found`);\n }\n return success;\n }\n\n /* replace message content\n */\n messageReplaceContent(n, content) {\n let success = false;\n try {\n // Update history first\n let item = this._history.filter((item) => item.msgid === n)[0];\n item.content = content;\n item.updatedtime = new Date().toISOString();\n \n // If virtual scrolling is active, update the virtual scroller\n if (this.virtualScroller) {\n // Find the item index in virtual scroller\n const index = this.virtualScroller.items.findIndex(item => item.msgid === n);\n if (index >= 0) {\n this.virtualScroller.items[index].content = content; // Don't double-sanitize, it's done on render\n // Re-render if the item is currently visible\n this.virtualScroller.updateItem(index, { content: content });\n }\n } else {\n // Regular DOM manipulation\n this._messagesArea.querySelector(`.quikchat-msgid-${String(n).padStart(10, '0')}`).lastChild.innerHTML = this._sanitizeContent(content);\n }\n \n success = true;\n \n // Call the onMessageReplace callback if it exists\n if (this._onMessageReplace) {\n this._onMessageReplace(this, n, content);\n }\n\n // Don't auto-scroll on append - let user control this\n // Users can call messageScrollToBottom() if they want to scroll\n } catch (error) {\n console.log(`${String(n)} : Message ID not found`);\n }\n return success;\n }\n\n /**\n * Scrolls the messages area to the bottom.\n */\n messageScrollToBottom() {\n // Always use scrollTop to avoid page jumping\n // This ensures only the chat container scrolls, not the entire page\n this._messagesArea.scrollTop = this._messagesArea.scrollHeight;\n }\n\n /**\n * Removes the last message from the messages area.\n */\n messageRemoveLast() {\n // find the last message by id:\n if (this._history.length >= 0) {\n let lastMsgId = this._history[this._history.length - 1].msgid;\n return this.messageRemove(lastMsgId);\n }\n return false;\n }\n\n messageSetVisibility(msgid, isVisible) {\n const message = this._history.find(item => item.msgid === msgid);\n if (message && message.messageDiv) {\n message.messageDiv.style.display = isVisible ? '' : 'none';\n message.visible = isVisible;\n this._updateMessageStyles();\n return true;\n }\n return false;\n }\n\n messageGetVisibility(msgid) {\n const message = this._history.find(item => item.msgid === msgid);\n if (message && message.messageDiv) {\n return message.messageDiv.style.display !== 'none';\n }\n return false; // Return false if not found or no messageDiv\n }\n\n _updateMessageStyles() {\n const visibleMessages = [...this._messagesArea.children].filter(\n child => child.style.display !== 'none'\n );\n\n visibleMessages.forEach((messageDiv, index) => {\n messageDiv.classList.remove('quikchat-message-1', 'quikchat-message-2');\n messageDiv.classList.add(index % 2 === 0 ? 'quikchat-message-1' : 'quikchat-message-2');\n });\n }\n\n /**\n * For right sided or centered messages, we need to handle the CSS for short and long messages.\n * for short messages we use simple justifying, for long messages we need to wrap and perform multiline\n * formatting. \n * \n * @param {*} messageElement \n * @returns nothing\n */\n _handleShortLongMessageCSS(messageElement, align) {\n // console.log(messageElement);\n // Reset classes\n messageElement.classList.remove(\n 'left-singleline', 'left-multiline',\n 'center-singleline', 'center-multiline',\n 'right-singleline', 'right-multiline');\n let contentDiv = messageElement.lastChild;\n window.lastDiv = contentDiv; // for debugging \n // Determine if the message is short or long\n\n const computedStyle = window.getComputedStyle(contentDiv);\n\n // Get the element's height\n const elementHeight = contentDiv.offsetHeight;\n\n // Calculate or estimate line height\n let lineHeight;\n if (computedStyle.lineHeight === \"normal\") {\n const fontSize = parseFloat(computedStyle.fontSize);\n lineHeight = fontSize * 1.2; // approximate \"normal\" as 1.2 times font-size\n } else {\n lineHeight = parseFloat(computedStyle.lineHeight);\n }\n\n // Check if the element height is more than one line-height\n const isMultiLine = elementHeight > lineHeight;\n\n // Using scrollHeight and clientHeight to check for overflow (multi-line)\n switch (align) {\n case 'center':\n if (isMultiLine) {\n messageElement.classList.add('center-multiline');\n }\n else {\n messageElement.classList.add('center-singleline');\n }\n break;\n case 'right':\n if (isMultiLine) {\n messageElement.classList.add('right-multiline');\n }\n else {\n messageElement.classList.add('right-singleline');\n }\n break;\n case 'left':\n default:\n if (isMultiLine) {\n messageElement.classList.add('left-multiline');\n }\n else {\n messageElement.classList.add('left-singleline');\n }\n break;\n }\n\n }\n // history functions\n /**\n * \n * @param {*} n \n * @param {*} m \n * @returns array of history messages\n */\n /**\n * Gets a slice of message history\n * @param {number} [n] - Start index (defaults to 0)\n * @param {number} [m] - End index (defaults to history length)\n * @returns {Array} Array of message objects\n * @example\n * // Get first 10 messages\n * const messages = chat.historyGet(0, 10);\n * \n * // Get all messages\n * const allMessages = chat.historyGet();\n */\n historyGet(n, m) {\n\n if (n == undefined) {\n n = 0;\n m = this._history.length;\n }\n if (m === undefined) {\n m = n < 0 ? m : n + 1;\n }\n // remember that entries could be deleted. TODO: So we need to return the actual history entries\n // so now we need to find the array index that correspondes to messageIds n (start) and m (end)\n\n return this._history.slice(n, m);\n }\n\n /**\n * Gets a copy of the entire message history\n * @returns {Array} Complete array of all message objects\n * @example\n * const history = chat.historyGetAllCopy();\n * console.log(`Total messages: ${history.length}`);\n */\n historyGetAllCopy() {\n return this._history.slice();\n }\n \n /**\n * Get a page of history messages with pagination support\n * @param {number} page - Page number (1-based)\n * @param {number} pageSize - Number of messages per page (default 50)\n * @param {string} order - 'asc' for oldest first, 'desc' for newest first (default 'asc')\n * @returns {object} Object with messages array, pagination info\n */\n historyGetPage(page = 1, pageSize = 50, order = 'asc') {\n const totalMessages = this._history.length;\n const totalPages = Math.ceil(totalMessages / pageSize);\n const currentPage = Math.max(1, Math.min(page, totalPages || 1));\n \n let start, end;\n if (order === 'desc') {\n // For descending order, page 1 shows the newest messages\n start = Math.max(0, totalMessages - (currentPage * pageSize));\n end = totalMessages - ((currentPage - 1) * pageSize);\n } else {\n // For ascending order, page 1 shows the oldest messages\n start = (currentPage - 1) * pageSize;\n end = Math.min(start + pageSize, totalMessages);\n }\n \n const messages = this._history.slice(start, end);\n \n // Reverse messages array if descending order requested\n if (order === 'desc') {\n messages.reverse();\n }\n \n return {\n messages: messages,\n pagination: {\n currentPage: currentPage,\n pageSize: pageSize,\n totalPages: totalPages,\n totalMessages: totalMessages,\n hasNext: currentPage < totalPages,\n hasPrevious: currentPage > 1,\n order: order\n }\n };\n }\n \n /**\n * Get information about history size and pagination\n * @param {number} pageSize - Size to calculate pages for (default 50)\n * @returns {object} History metadata\n */\n /**\n * Search history for messages matching criteria\n * @param {object} criteria - Search criteria object\n * @param {string} criteria.text - Text to search for in message content\n * @param {string} criteria.userString - Filter by user name\n * @param {string} criteria.role - Filter by role\n * @param {array} criteria.tags - Filter by tags (messages with any of these tags)\n * @param {number} criteria.limit - Maximum results to return (default 100)\n * @returns {array} Array of matching messages\n */\n /**\n * Searches through message history with various filters\n * @param {Object} [criteria={}] - Search criteria\n * @param {string} [criteria.text] - Text to search for in message content\n * @param {string} [criteria.userString] - Filter by specific user\n * @param {string} [criteria.role] - Filter by role (user, assistant, system)\n * @param {string[]} [criteria.tags] - Filter by tags (messages must have at least one)\n * @param {number} [criteria.limit=100] - Maximum number of results\n * @returns {Array} Array of matching messages\n * @since 1.1.15\n * @example\n * // Search for messages containing 'error'\n * const errors = chat.historySearch({ text: 'error' });\n * \n * // Find all bot messages\n * const botMessages = chat.historySearch({ role: 'assistant' });\n * \n * // Complex search\n * const results = chat.historySearch({\n * text: 'help',\n * userString: 'Support',\n * tags: ['urgent'],\n * limit: 20\n * });\n */\n historySearch(criteria = {}) {\n let results = this._history;\n \n // Filter by text content (case-insensitive)\n if (criteria.text) {\n const searchText = criteria.text.toLowerCase();\n results = results.filter(msg => \n msg.content.toLowerCase().includes(searchText)\n );\n }\n \n // Filter by user\n if (criteria.userString) {\n results = results.filter(msg => \n msg.userString === criteria.userString\n );\n }\n \n // Filter by role\n if (criteria.role) {\n results = results.filter(msg => \n msg.role === criteria.role\n );\n }\n \n // Filter by tags (match any tag)\n if (criteria.tags && criteria.tags.length > 0) {\n results = results.filter(msg => \n msg.tags && msg.tags.some(tag => criteria.tags.includes(tag))\n );\n }\n \n // Limit results\n const limit = criteria.limit || 100;\n if (results.length > limit) {\n results = results.slice(0, limit);\n }\n \n return results;\n }\n \n /**\n * Gets metadata and statistics about the message history\n * @param {number} [pageSize=50] - Page size for calculating total pages\n * @returns {Object} History information object\n * @returns {number} returns.totalMessages - Total number of messages\n * @returns {number} returns.totalPages - Total pages based on page size\n * @returns {Object|null} returns.oldestMessage - First message info\n * @returns {Object|null} returns.newestMessage - Last message info\n * @returns {Object} returns.memoryUsage - Memory usage statistics\n * @since 1.1.15\n * @example\n * const info = chat.historyGetInfo();\n * console.log(`Messages: ${info.totalMessages}`);\n * console.log(`Memory: ${info.memoryUsage.estimatedSize} bytes`);\n */\n historyGetInfo(pageSize = 50) {\n const totalMessages = this._history.length;\n return {\n totalMessages: totalMessages,\n totalPages: Math.ceil(totalMessages / pageSize),\n oldestMessage: totalMessages > 0 ? {\n msgid: this._history[0].msgid,\n timestamp: this._history[0].timestamp,\n userString: this._history[0].userString\n } : null,\n newestMessage: totalMessages > 0 ? {\n msgid: this._history[totalMessages - 1].msgid,\n timestamp: this._history[totalMessages - 1].timestamp,\n userString: this._history[totalMessages - 1].userString\n } : null,\n memoryUsage: {\n estimatedSize: JSON.stringify(this._history).length,\n averageMessageSize: totalMessages > 0 ? \n Math.round(JSON.stringify(this._history).length / totalMessages) : 0\n }\n };\n }\n\n /**\n * Clears all messages and resets the chat\n * @returns {void}\n * @example\n * chat.historyClear(); // Removes all messages\n */\n historyClear() {\n this.msgid = 0;\n \n // Handle virtual scroller\n if (this.virtualScroller) {\n this.virtualScroller.clear();\n } else {\n this._messagesArea.innerHTML = \"\";\n }\n \n this._history = [];\n this._activeTags.clear();\n }\n\n historyGetLength() {\n return this._history.length;\n }\n\n historyGetMessage(n) {\n if (n >= 0 && n < this._history.length) {\n return this._history[n];\n }\n return {};\n\n }\n\n historyGetMessageContent(n) {\n if (n >= 0 && n < this._history.length)\n return this._history[n].content;\n else\n return \"\";\n }\n\n // expects an array of messages to be in the format of the history object\n historyRestoreAll(messageList) {\n // clear all messages and history\n this.historyClear();\n\n // clear the messages div \n this._messagesArea.innerHTML = \"\";\n\n // add all messages\n messageList.forEach((message) => {\n this.messageAddFull(message);\n });\n }\n /**\n * \n * @param {string} newTheme \n */\n changeTheme(newTheme) {\n this._chatWidget.classList.remove(this._theme);\n this._chatWidget.classList.add(newTheme);\n this._theme = newTheme;\n }\n\n /**\n * Get the current theme\n * @returns {string} - The current theme\n */\n get theme() {\n return this._theme;\n }\n\n /**\n * \n * @returns {object} - Returns the version and license information for the library.\n */\n /**\n * Gets the QuikChat version information\n * @static\n * @returns {Object} Version information object\n * @returns {string} returns.version - Version number (e.g., '1.1.15')\n * @returns {string} returns.license - License type (e.g., 'BSD-2')\n * @returns {string} returns.url - Project URL\n * @returns {boolean} returns.fun - Easter egg flag\n * @example\n * const version = quikchat.version();\n * console.log(`QuikChat v${version.version}`);\n */\n static version() {\n return quikchatVersion;\n }\n\n /**\n * Built-in content sanitizers for XSS protection\n * @static\n * @type {Object}\n * @property {Function} escapeHTML - Escapes HTML entities\n * @property {Function} stripHTML - Removes all HTML tags\n * @example\n * // Use built-in HTML escaper\n * const chat = new quikchat('#chat', onSend, {\n * sanitizer: quikchat.sanitizers.escapeHTML\n * });\n */\n static sanitizers = {\n /**\n * Escapes HTML entities to prevent XSS\n * @param {string} str - String to escape\n * @returns {string} Escaped string\n */\n escapeHTML: (str) => {\n if (typeof str !== 'string') return str;\n return str.replace(/[&<>\"']/g, (m) => ({\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n })[m]);\n },\n \n /**\n * Strips all HTML tags but keeps text content\n * @param {string} str - String to strip\n * @returns {string} Text without HTML tags\n */\n stripHTML: (str) => {\n if (typeof str !== 'string') return str;\n return str.replace(/<[^>]*>/g, '');\n }\n };\n\n /**\n * quikchat.loremIpsum() - Generate a simple string of Lorem Ipsum text (sample typographer's text) of numChars in length.\n * borrowed from github.com/deftio/bitwrench.js\n * @param {number} numChars - The number of characters to generate (random btw 25 and 150 if undefined). \n * @param {number} [startSpot=0] - The starting index in the Lorem Ipsum text. If undefined, a random startSpot will be generated.\n * @param {boolean} [startWithCapitalLetter=true] - If true, capitalize the first character or inject a capital letter if the first character isn't a capital letter.\n * \n * @returns {string} A string of Lorem Ipsum text.\n * \n * @example \n * // Returns 200 characters of Lorem Ipsum starting from index 50\n * loremIpsum(200, 50);\n * \n * @example \n * //Returns a 200 Lorem Ipsum characters starting from a random index\n * loremIpsum(200);\n */\n\n /**\n * Generates Lorem Ipsum placeholder text\n * @static\n * @param {number} [numChars] - Length of text to generate (random if not specified)\n * @param {number} [startSpot] - Starting offset in Lorem text (random if not specified)\n * @param {boolean} [startWithCapitalLetter=true] - Whether to capitalize first letter\n * @returns {string} Generated Lorem Ipsum text\n * @example\n * // Generate 100 characters\n * const text = quikchat.loremIpsum(100);\n * \n * // Generate random length\n * const randomText = quikchat.loremIpsum();\n */\n static loremIpsum(numChars, startSpot = undefined, startWithCapitalLetter = true) {\n const loremText = \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. \";\n\n if (typeof numChars !== \"number\") {\n numChars = Math.floor(Math.random() * (150)) + 25;\n }\n\n if (startSpot === undefined) {\n startSpot = Math.floor(Math.random() * loremText.length);\n }\n\n startSpot = startSpot % loremText.length;\n\n // Move startSpot to the next non-whitespace and non-punctuation character\n while (loremText[startSpot] === ' ' || /[.,:;!?]/.test(loremText[startSpot])) {\n startSpot = (startSpot + 1) % loremText.length;\n }\n\n let l = loremText.substring(startSpot) + loremText.substring(0, startSpot);\n\n if (typeof numChars !== \"number\") {\n numChars = l.length;\n }\n\n let s = \"\";\n while (numChars > 0) {\n s += numChars < l.length ? l.substring(0, numChars) : l;\n numChars -= l.length;\n }\n\n if (s[s.length - 1] === \" \") {\n s = s.substring(0, s.length - 1) + \".\"; // always end on non-whitespace. \".\" was chosen arbitrarily.\n }\n\n if (startWithCapitalLetter) {\n let c = s[0].toUpperCase();\n c = /[A-Z]/.test(c) ? c : \"M\";\n s = c + s.substring(1);\n }\n\n return s;\n };\n\n /**\n * Creates a temporary message that updates periodically\n * @static\n * @param {string|HTMLElement} domElement - Element selector or DOM element\n * @param {string} content - Initial message content\n * @param {number} interval - Update interval in milliseconds (min 100ms)\n * @param {Function} [cb=null] - Callback to generate new content\n * @param {string} cb.message - Current message\n * @param {number} cb.count - Update count\n * @returns {void}\n * @example\n * // Simple loading indicator\n * quikchat.tempMessageGenerator('#loading', 'Loading', 500);\n * \n * // Custom update function\n * quikchat.tempMessageGenerator('#status', 'Processing', 1000, (msg, count) => {\n * return `Processing... ${count}%`;\n * });\n */\n static tempMessageGenerator (domElement, content, interval, cb = null) {\n interval = Math.max(interval, 100); // Ensure at least 100ms interval\n \n let count = 0;\n\n let defaultCB = (msg, count) => {msg += \".\"; return msg; };\n\n if (cb && typeof cb !== 'function') {\n cb = null;\n }\n\n cb = cb || defaultCB;\n \n // if its a string, then get the element (css sel) or its an DOM element already \n let el = domElement;\n if (typeof el === 'string') {\n el = document.querySelector(el);\n } \n\n const element = el;\n\n \n // Ensure the element exists\n if (!element) return;\n \n element.innerHTML = content;\n let currentMsg = content;\n \n const intervalId = setInterval(() => {\n if (element.innerHTML !== currentMsg) {\n clearInterval(intervalId); // Stop updating if content is changed externally\n return;\n }\n \n currentMsg = String( cb(currentMsg, count)) ;// Use callback return value if provided\n \n count++;\n element.innerHTML = currentMsg;\n }, interval);\n }\n\n static createTempMessageDOMStr(initialContent, updateInterval = 1000, callback = null, options = {}) {\n // Make sure the interval is at least 100ms\n updateInterval = Math.max(updateInterval, 100);\n \n // Validate callback; if not a function, ignore it.\n if (callback && typeof callback !== 'function') {\n callback = null;\n }\n // Default callback simply appends a dot.\n callback = callback || function(msg, count) {\n return msg + \".\";\n };\n \n // Allow an optional CSS class for the container element\n const containerClass = options.containerClass ? options.containerClass : '';\n \n // Generate a unique id so that the inline script can reliably find the container.\n const uniqueId = \"tempMsg_\" + Date.now() + \"_\" + Math.floor(Math.random() * 1000000);\n \n // Build and return the HTML string.\n // Note the use of <\\/script> (with a backslash) so that the inline script is not terminated early.\n return `\n <span id=\"${uniqueId}\" ${containerClass ? `class=\"${containerClass}\"` : ''}>\n ${initialContent}\n </span>\n <script>\n (function(){\n // Get our container element by its unique id.\n var container = document.getElementById(\"${uniqueId}\");\n if (!container) return;\n var count = 0;\n var currentMsg = container.innerHTML;\n var interval = ${updateInterval};\n // Convert the callback function into its string representation.\n var cb = ${callback.toString()};\n var intervalId = setInterval(function(){\n // If the content has been replaced, stop updating.\n if(container.innerHTML !== currentMsg){\n clearInterval(intervalId);\n return;\n }\n // Use the callback to generate the new message.\n currentMsg = String(cb(currentMsg, count));\n count++;\n container.innerHTML = currentMsg;\n }, interval);\n })();\n <\\/script>\n `;\n }\n \n /**\n * Sets visibility for all messages with a specific tag\n * @param {string} tagName - Tag name to control\n * @param {boolean} isVisible - Whether to show or hide messages with this tag\n * @returns {boolean} True if successful, false if invalid tag name\n * @since 1.1.14\n * @example\n * // Hide all system messages\n * chat.setTagVisibility('system', false);\n * \n * // Show urgent messages\n * chat.setTagVisibility('urgent', true);\n */\n setTagVisibility(tagName, isVisible) {\n if (typeof tagName !== 'string' || !/^[a-zA-Z0-9-]+$/.test(tagName)) {\n return false;\n }\n const className = `quikchat-show-tag-${tagName}`;\n if (isVisible) {\n this._chatWidget.classList.add(className);\n } else {\n this._chatWidget.classList.remove(className);\n }\n this._updateMessageStyles();\n return true;\n }\n\n /**\n * Gets the visibility state of a tag\n * @param {string} tagName - Tag name to check\n * @returns {boolean} True if tag is visible, false otherwise\n * @since 1.1.14\n * @example\n * const isVisible = chat.getTagVisibility('system');\n */\n getTagVisibility(tagName) {\n if (typeof tagName !== 'string' || !/^[a-zA-Z0-9-]+$/.test(tagName)) {\n return false;\n }\n return this._chatWidget.classList.contains(`quikchat-show-tag-${tagName}`);\n }\n\n /**\n * Gets all active tags in the chat\n * @returns {string[]} Array of all tags currently in use\n * @since 1.1.14\n * @example\n * const tags = chat.getActiveTags();\n * console.log('Active tags:', tags);\n */\n getActiveTags() {\n return Array.from(this._activeTags);\n }\n\n /**\n * Checks if virtual scrolling is currently enabled\n * @returns {boolean} True if virtual scrolling is enabled, false otherwise\n * @since 1.1.16\n * @example\n * if (chat.isVirtualScrollingEnabled()) {\n * console.log('Virtual scrolling is active');\n * }\n */\n isVirtualScrollingEnabled() {\n return this.virtualScrollingEnabled && this.virtualScroller !== null;\n }\n\n /**\n * Gets the virtual scrolling configuration\n * @returns {Object} Virtual scrolling configuration with enabled status and threshold\n * @since 1.1.16\n * @example\n * const config = chat.getVirtualScrollingConfig();\n * console.log(`Virtual scrolling: ${config.enabled}, threshold: ${config.threshold}`);\n */\n getVirtualScrollingConfig() {\n return {\n enabled: this.virtualScrollingEnabled,\n active: this.virtualScroller !== null,\n threshold: this.virtualScrollingThreshold\n };\n }\n \n /**\n * Set the language for the widget\n * @param {string} lang - Language code (e.g., 'en', 'es', 'fr')\n * @param {Object} [translations] - Optional translations object for the language\n * @example\n * chat.setLanguage('es', {\n * sendButton: 'Enviar',\n * inputPlaceholder: 'Escribe un mensaje...',\n * titleDefault: 'Chat'\n * });\n */\n setLanguage(lang, translations) {\n this.lang = lang;\n \n // Add translations if provided\n if (translations) {\n this.translations[lang] = { ...this.translations[lang], ...translations };\n }\n \n // Update current translations\n this.currentTranslations = this.translations[lang] || this.translations['en'];\n \n // Update UI elements\n this._updateUITranslations();\n }\n \n /**\n * Get current language\n * @returns {string} Current language code\n */\n getLanguage() {\n return this.lang;\n }\n \n /**\n * Set text direction (LTR or RTL)\n * @param {string} dir - Direction ('ltr' or 'rtl')\n */\n setDirection(dir) {\n if (dir === 'ltr' || dir === 'rtl') {\n this.dir = dir;\n this._chatWidget.setAttribute('dir', dir);\n }\n }\n \n /**\n * Get current text direction\n * @returns {string} Current direction ('ltr' or 'rtl')\n */\n getDirection() {\n return this.dir;\n }\n \n /**\n * Update UI elements with current translations\n * @private\n */\n _updateUITranslations() {\n // Update send button text\n if (this._sendButton) {\n this._sendButton.textContent = this.currentTranslations.sendButton || 'Send';\n }\n \n // Update input placeholder\n if (this._textEntry) {\n this._textEntry.placeholder = this.currentTranslations.inputPlaceholder || 'Type a message...';\n }\n \n // Update widget language attribute\n if (this._chatWidget) {\n this._chatWidget.setAttribute('lang', this.lang);\n }\n }\n \n /**\n * Sets the content sanitizer function\n * @param {Function|null} sanitizer - Function to sanitize content or null to disable\n * @returns {void}\n * @example\n * // Use built-in HTML escaper\n * chat.setSanitizer(quikchat.sanitizers.escapeHTML);\n * \n * // Use custom sanitizer (e.g., DOMPurify)\n * chat.setSanitizer((content) => DOMPurify.sanitize(content));\n * \n * // Disable sanitization\n * chat.setSanitizer(null);\n */\n setSanitizer(sanitizer) {\n if (sanitizer === null || typeof sanitizer === 'function') {\n this._sanitizer = sanitizer;\n } else {\n console.warn('Sanitizer must be a function or null');\n }\n }\n \n /**\n * Gets the current content sanitizer function\n * @returns {Function|null} The current sanitizer function or null\n * @example\n * const sanitizer = chat.getSanitizer();\n * if (sanitizer) {\n * console.log('Sanitization is enabled');\n * }\n */\n getSanitizer() {\n return this._sanitizer;\n }\n \n /**\n * Internal method to apply sanitizer to content\n * @private\n * @param {string} content - Content to sanitize\n * @returns {string} Sanitized content\n */\n _sanitizeContent(content) {\n if (this._sanitizer && typeof this._sanitizer === 'function') {\n return this._sanitizer(content);\n }\n return content;\n }\n}\n\nexport default quikchat;\n"],"names":["quikchatVersion","version","license","url","fun","SimpleVirtualScroller","_createClass","container","options","arguments","length","undefined","_classCallCheck","this","items","itemHeight","buffer","visibleRange","start","end","renderedElements","Map","itemHeights","itemPositions","totalHeight","onRenderItem","sanitizer","_initStructure","_attachScrollListener","key","value","_this","existingClasses","className","innerHTML","style","position","overflow","offsetHeight","computedHeight","window","getComputedStyle","height","console","warn","spacer","document","createElement","cssText","content","appendChild","setTimeout","_updateVisibleRange","_renderVisibleItems","_this2","ticking","addEventListener","requestAnimationFrame","index","get","has","i","_getItemHeight","set","fromIndex","_getItemPosition","element","top","concat","scrollTop","viewportHeight","clientHeight","startIndex","endIndex","size","Math","max","min","floor","ceil","_this3","_this$visibleRange","forEach","remove","_loop","item","_createItemElement","left","right","actualHeight","_recalculatePositions","messageDiv","align","String","msgid","padStart","setAttribute","userString","tags","tag","classList","add","userDiv","contentDiv","visible","display","push","scrollIntoView","scrollHeight","_this$items","startLength","apply","_toConsumableArray","clear","updates","_objectSpread","quikchat","parentElement","onSend","defaultOpts","theme","trackHistory","titleArea","title","show","messagesArea","alternating","inputArea","sendOnEnter","sendOnShiftEnter","instanceClass","virtualScrolling","virtualScrollingThreshold","lang","dir","translations","en","sendButton","inputPlaceholder","titleDefault","meta","querySelector","_parentElement","_theme","_onSend","currentTranslations","_createWidget","_chatWidget","titleAreaSetContents","titleAreaShow","titleAreaHide","messagesAreaAlternateColors","inputAreaShow","inputAreaHide","_attachEventListeners","_historyLimit","_history","_activeTags","Set","virtualScrollingEnabled","virtualScroller","_sanitizer","_this4","_messagesArea","contains","_updateMessageStyles","_migrateToVirtualScrolling","_this5","map","msg","role","addItems","sendButtonText","widgetHTML","_titleArea","_inputArea","_textEntry","_sendButton","_setupMobileSupport","_this6","name","head","_originalViewport","innerWidth","visualViewport","_handleVirtualKeyboard","keyboardHeight","innerHeight","paddingBottom","_this7","event","preventDefault","trim","_handleContainerResize","shiftKey","keyCode","_this7$_messagesArea","userScrolledUp","callback","_onMessageAdded","_onMessageAppend","_onMessageReplace","_onMessageDelete","_adjustMessagesAreaHeight","_sanitizeContent","textAlign","toggle","totalHiddenHeight","children","filter","child","reduce","sum","containerHeight","_adjustSendButtonWidth","textContent","minWidth","parseFloat","fontSize","alt","_this8","input","userID","timestamp","updatedtime","_initVirtualScrolling","messageData","Array","isArray","test","addItem","msgidClass","isMultiLine","includes","isLong","messageScrollToBottom","_handleShortLongMessageCSS","Date","toISOString","shift","messageAddFull","n","sucess","removeChild","error","log","splice","findIndex","contentElement","lastChild","success","updateItem","lastMsgId","messageRemove","isVisible","message","find","messageElement","lastDiv","lineHeight","computedStyle","elementHeight","m","slice","page","pageSize","order","totalMessages","totalPages","currentPage","messages","reverse","pagination","hasNext","hasPrevious","criteria","results","text","searchText","toLowerCase","some","limit","oldestMessage","newestMessage","memoryUsage","estimatedSize","JSON","stringify","averageMessageSize","round","messageList","_this9","historyClear","newTheme","tagName","from","enabled","active","threshold","_updateUITranslations","placeholder","numChars","startSpot","startWithCapitalLetter","loremText","random","l","substring","s","c","toUpperCase","domElement","interval","cb","count","el","currentMsg","intervalId","setInterval","clearInterval","initialContent","updateInterval","containerClass","uniqueId","now","toString","_defineProperty","escapeHTML","str","replace","stripHTML"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"quikchat.cjs.min.js","sources":["../src/quikchat.js"],"sourcesContent":["\nclass quikchat {\n /**\n *\n * @param string or DOM element parentElement\n * @param {*} meta\n */\n constructor(parentElement, onSend = () => { }, options = {}) {\n const defaultOpts = {\n theme: 'quikchat-theme-light',\n trackHistory: true,\n showTimestamps: false,\n titleArea: { title: \"Chat\", show: false, align: \"center\" },\n messagesArea: { alternating: true },\n };\n const meta = { ...defaultOpts, ...options }; // merge options with defaults\n\n if (typeof parentElement === 'string') {\n parentElement = document.querySelector(parentElement);\n }\n this._parentElement = parentElement;\n this._theme = meta.theme;\n this._onSend = onSend ? onSend : () => { }; // call back function for onSend\n this._messageFormatter = meta.messageFormatter || null;\n this._sanitize = meta.sanitize || false;\n this._createWidget();\n // title area\n if (meta.titleArea) {\n this.titleAreaSetContents(meta.titleArea.title, meta.titleArea.align);\n if (meta.titleArea.show === true) {\n this.titleAreaShow();\n } else {\n this.titleAreaHide();\n }\n }\n // messages area\n if (meta.messagesArea) {\n this.messagesAreaAlternateColors(meta.messagesArea.alternating);\n }\n // timestamps\n if (meta.showTimestamps) {\n this.messagesAreaShowTimestamps(true);\n }\n // direction (ltr/rtl)\n if (meta.direction) {\n this.setDirection(meta.direction);\n }\n // plumbing\n this._attachEventListeners();\n this.trackHistory = meta.trackHistory !== false;\n this._historyLimit = 10000000;\n this._history = [];\n }\n\n _createWidget() {\n const widgetHTML =\n `\n <div class=\"quikchat-base ${this.theme}\">\n <div class=\"quikchat-title-area\"></div>\n <div class=\"quikchat-messages-wrapper\"><div class=\"quikchat-messages-area\" role=\"log\" aria-live=\"polite\" aria-label=\"Chat messages\"></div><button class=\"quikchat-scroll-bottom\" aria-label=\"Scroll to bottom\"></button></div>\n <div class=\"quikchat-input-area\">\n <textarea class=\"quikchat-input-textbox\" rows=\"1\" aria-label=\"Type a message\"></textarea>\n <button class=\"quikchat-input-send-btn\">Send</button>\n </div>\n </div>\n `;\n\n this._parentElement.innerHTML = widgetHTML;\n this._chatWidget = this._parentElement.querySelector('.quikchat-base');\n this._titleArea = this._chatWidget.querySelector('.quikchat-title-area');\n this._messagesWrapper = this._chatWidget.querySelector('.quikchat-messages-wrapper');\n this._messagesArea = this._chatWidget.querySelector('.quikchat-messages-area');\n this._scrollBottomBtn = this._messagesWrapper.querySelector('.quikchat-scroll-bottom');\n this._inputArea = this._chatWidget.querySelector('.quikchat-input-area');\n this._textEntry = this._inputArea.querySelector('.quikchat-input-textbox');\n this._sendButton = this._inputArea.querySelector('.quikchat-input-send-btn');\n this.msgid = 0;\n }\n\n /**\n * Attach event listeners to the widget\n */\n _attachEventListeners() {\n this._sendButton.addEventListener('click', () => {\n const text = this._textEntry.value.trim();\n if (text === '') return;\n this._onSend(this, text);\n });\n this._textEntry.addEventListener('keydown', (event) => {\n // Check if Shift + Enter is pressed\n if (event.shiftKey && event.keyCode === 13) {\n event.preventDefault();\n const text = this._textEntry.value.trim();\n if (text === '') return;\n this._onSend(this, text);\n }\n });\n\n // Auto-grow textarea\n this._textEntry.addEventListener('input', () => this._autoGrowTextarea());\n\n this._messagesArea.addEventListener('scroll', () => {\n const { scrollTop, scrollHeight, clientHeight } = this._messagesArea;\n this.userScrolledUp = scrollTop + clientHeight < scrollHeight - 1;\n this._updateScrollBottomBtn();\n });\n\n // Scroll-to-bottom button\n this._scrollBottomBtn.addEventListener('click', () => this.scrollToBottom());\n\n // Ctrl+End to scroll to bottom\n this._chatWidget.addEventListener('keydown', (event) => {\n if (event.ctrlKey && event.key === 'End') {\n event.preventDefault();\n this.scrollToBottom();\n }\n });\n\n // Use ResizeObserver to detect parent container resize\n if (typeof ResizeObserver !== 'undefined') {\n this._resizeObserver = new ResizeObserver(() => this._handleContainerResize());\n this._resizeObserver.observe(this._parentElement);\n }\n }\n\n // set the onSend function callback.\n setCallbackOnSend(callback) {\n this._onSend = callback;\n }\n // set a callback for everytime a message is added (listener)\n setCallbackonMessageAdded(callback) {\n this._onMessageAdded = callback;\n }\n setCallbackonMessageAppend(callback) {\n this._onMessageAppend = callback;\n }\n setCallbackonMessageReplace(callback) {\n this._onMessageReplace = callback;\n }\n setCallbackonMessageDelete(callback) {\n this._onMessageDelete = callback;\n }\n\n // Public methods\n titleAreaToggle() {\n if (this._titleArea.style.display === 'none') {\n this.titleAreaShow();\n } else {\n this.titleAreaHide();\n }\n }\n\n titleAreaShow() {\n this._titleArea.style.display = '';\n }\n\n titleAreaHide() {\n this._titleArea.style.display = 'none';\n }\n\n titleAreaSetContents(title, align = 'center') {\n this._titleArea.innerHTML = title;\n this._titleArea.style.textAlign = align;\n }\n\n titleAreaGetContents() {\n return this._titleArea.innerHTML;\n }\n\n inputAreaToggle() {\n if (this._inputArea.style.display === 'none') {\n this.inputAreaShow();\n } else {\n this.inputAreaHide();\n }\n }\n\n inputAreaShow() {\n this._inputArea.style.display = '';\n }\n\n inputAreaHide() {\n this._inputArea.style.display = 'none';\n }\n\n inputAreaSetEnabled(enabled) {\n this._textEntry.disabled = !enabled;\n this._sendButton.disabled = !enabled;\n }\n\n inputAreaSetButtonText(text) {\n this._sendButton.textContent = text;\n }\n\n inputAreaGetButtonText() {\n return this._sendButton.textContent;\n }\n\n setDirection(dir) {\n const d = dir === 'rtl' ? 'rtl' : 'ltr';\n this._chatWidget.setAttribute('dir', d);\n if (d === 'rtl') {\n this._chatWidget.classList.add('quikchat-rtl');\n } else {\n this._chatWidget.classList.remove('quikchat-rtl');\n }\n }\n\n getDirection() {\n return this._chatWidget.getAttribute('dir') || 'ltr';\n }\n\n _handleContainerResize() {\n // Layout is handled by CSS flexbox — no JS height calculation needed.\n // This hook exists for future use or custom resize callbacks.\n }\n\n scrollToBottom() {\n this._messagesArea.scrollTop = this._messagesArea.scrollHeight;\n this.userScrolledUp = false;\n this._updateScrollBottomBtn();\n }\n\n _updateScrollBottomBtn() {\n if (this.userScrolledUp) {\n this._scrollBottomBtn.classList.add('quikchat-scroll-bottom-visible');\n } else {\n this._scrollBottomBtn.classList.remove('quikchat-scroll-bottom-visible');\n }\n }\n\n _autoGrowTextarea() {\n const el = this._textEntry;\n el.style.height = 'auto';\n const maxHeight = parseInt(getComputedStyle(el).getPropertyValue('--quikchat-input-max-height')) || 120;\n el.style.height = Math.min(el.scrollHeight, maxHeight) + 'px';\n el.style.overflowY = el.scrollHeight > maxHeight ? 'auto' : 'hidden';\n }\n\n _formatTimestamp(isoString) {\n const d = new Date(isoString);\n const h = d.getHours();\n const m = String(d.getMinutes()).padStart(2, '0');\n const ampm = h >= 12 ? 'PM' : 'AM';\n const h12 = h % 12 || 12;\n return h12 + ':' + m + ' ' + ampm;\n }\n\n messagesAreaShowTimestamps(show) {\n if (show) {\n this._messagesArea.classList.add('quikchat-show-timestamps');\n } else {\n this._messagesArea.classList.remove('quikchat-show-timestamps');\n }\n }\n\n messagesAreaShowTimestampsGet() {\n return this._messagesArea.classList.contains('quikchat-show-timestamps');\n }\n\n messagesAreaShowTimestampsToggle() {\n this._messagesArea.classList.toggle('quikchat-show-timestamps');\n }\n\n _escapeHTML(str) {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n }\n\n _processContent(content) {\n if (this._sanitize === true) {\n content = this._escapeHTML(content);\n } else if (typeof this._sanitize === 'function') {\n content = this._sanitize(content);\n }\n if (this._messageFormatter) {\n content = this._messageFormatter(content);\n }\n return content;\n }\n\n //messagesArea functions\n messagesAreaAlternateColors(alt = true) {\n if (alt) {\n this._messagesArea.classList.add('quikchat-messages-area-alt');\n }\n else {\n this._messagesArea.classList.remove('quikchat-messages-area-alt');\n }\n return alt === true;\n }\n messagesAreaAlternateColorsToggle() {\n this._messagesArea.classList.toggle('quikchat-messages-area-alt');\n }\n messagesAreaAlternateColorsGet() {\n return this._messagesArea.classList.contains('quikchat-messages-area-alt');\n }\n // message functions\n messageAddFull(input = { content: \"\", userString: \"user\", align: \"right\", role: \"user\", userID: -1 }) {\n const msgid = this.msgid;\n const messageDiv = document.createElement('div');\n const msgidClass = 'quikchat-msgid-' + String(msgid).padStart(10, '0');\n messageDiv.classList.add('quikchat-message', msgidClass);\n messageDiv.classList.add('quikchat-role-' + (input.role || 'user'));\n messageDiv.classList.add('quikchat-align-' + (input.align || 'right'));\n this.msgid++;\n messageDiv.classList.add(this._messagesArea.children.length % 2 === 1 ? 'quikchat-message-1' : 'quikchat-message-2');\n\n // Visibility: default true, hidden messages get display:none\n const visible = input.visible !== false;\n if (!visible) {\n messageDiv.style.display = 'none';\n }\n\n // Tags: array of strings for group-based visibility control\n const tags = Array.isArray(input.tags) ? input.tags.slice() : [];\n\n const userDiv = document.createElement('div');\n userDiv.classList.add('quikchat-user-label');\n userDiv.style.textAlign = input.align;\n userDiv.innerHTML = input.userString;\n\n const contentDiv = document.createElement('div');\n contentDiv.classList.add('quikchat-message-content');\n contentDiv.style.textAlign = input.align;\n contentDiv.innerHTML = this._processContent(input.content);\n\n const timestamp = new Date().toISOString();\n const timestampSpan = document.createElement('span');\n timestampSpan.classList.add('quikchat-timestamp');\n timestampSpan.textContent = this._formatTimestamp(timestamp);\n\n messageDiv.appendChild(userDiv);\n messageDiv.appendChild(contentDiv);\n messageDiv.appendChild(timestampSpan);\n this._messagesArea.appendChild(messageDiv);\n\n // Scroll to the last message only if the user is not actively scrolling up\n if (!this.userScrolledUp) {\n this._messagesArea.scrollTop = this._messagesArea.scrollHeight;\n }\n\n this._textEntry.value = '';\n this._autoGrowTextarea();\n const updatedtime = timestamp;\n\n if (this.trackHistory) {\n this._history.push({ msgid, ...input, visible, tags, timestamp, updatedtime, messageDiv });\n if (this._history.length > this._historyLimit) {\n this._history.shift();\n }\n }\n\n if (this._onMessageAdded) {\n this._onMessageAdded(this, msgid);\n }\n\n return msgid;\n }\n\n\n messageAddNew(content = \"\", userString = \"user\", align = \"right\", role = \"user\") {\n return this.messageAddFull(\n { content: content, userString: userString, align: align, role: role }\n );\n }\n messageRemove(n) {\n let success = false;\n try {\n this._messagesArea.removeChild(this._messagesArea.querySelector(`.quikchat-msgid-${String(n).padStart(10, '0')}`));\n success = true;\n }\n catch (_error) {\n // Message ID not found\n }\n if (success) {\n this._history.splice(this._history.findIndex((item) => item.msgid === n), 1);\n if (this._onMessageDelete) {\n this._onMessageDelete(this, n);\n }\n }\n return success;\n }\n /* returns the message html object from the DOM\n */\n messageGetDOMObject(n) {\n let msg = null;\n try {\n msg = this._messagesArea.querySelector(`.quikchat-msgid-${String(n).padStart(10, '0')}`);\n }\n catch (_error) {\n // Message ID not found\n }\n return msg;\n }\n /* returns the message content only\n */\n messageGetContent(n) {\n let content = \"\";\n try {\n content = this._history.filter((item) => item.msgid === n)[0].content;\n }\n catch (_error) {\n // Message ID not found\n }\n return content;\n }\n\n messageSetVisible(n, visible) {\n const msgEl = this.messageGetDOMObject(n);\n if (!msgEl) return false;\n msgEl.style.display = visible ? '' : 'none';\n const item = this._history.find((entry) => entry.msgid === n);\n if (item) item.visible = visible;\n return true;\n }\n\n messageGetVisible(n) {\n const item = this._history.find((entry) => entry.msgid === n);\n return item ? item.visible !== false : false;\n }\n\n messageToggleVisible(n) {\n const current = this.messageGetVisible(n);\n return this.messageSetVisible(n, !current);\n }\n\n messageSetVisibleByTag(tag, visible) {\n let count = 0;\n for (const item of this._history) {\n if (item.tags && item.tags.includes(tag)) {\n this.messageSetVisible(item.msgid, visible);\n count++;\n }\n }\n return count;\n }\n\n messageGetTags(n) {\n const item = this._history.find((entry) => entry.msgid === n);\n return item && item.tags ? item.tags.slice() : [];\n }\n\n messageSetTags(n, tags) {\n const item = this._history.find((entry) => entry.msgid === n);\n if (!item) return false;\n item.tags = Array.isArray(tags) ? tags.slice() : [];\n return true;\n }\n\n /* append message to the message content\n */\n messageAppendContent(n, content) {\n let success = false;\n try {\n const msgEl = this._messagesArea.querySelector(`.quikchat-msgid-${String(n).padStart(10, '0')}`);\n const item = this._history.filter((entry) => entry.msgid === n)[0];\n item.content += content;\n item.updatedtime = new Date().toISOString();\n msgEl.querySelector('.quikchat-message-content').innerHTML = this._processContent(item.content);\n msgEl.classList.remove('quikchat-typing');\n success = true;\n\n if (!this.userScrolledUp) {\n this._messagesArea.scrollTop = this._messagesArea.scrollHeight;\n }\n if (this._onMessageAppend) {\n this._onMessageAppend(this, n, content);\n }\n } catch (_error) {\n // Message ID not found\n }\n return success;\n }\n\n /* replace message content\n */\n messageReplaceContent(n, content) {\n let success = false;\n try {\n const msgEl = this._messagesArea.querySelector(`.quikchat-msgid-${String(n).padStart(10, '0')}`);\n const item = this._history.filter((entry) => entry.msgid === n)[0];\n item.content = content;\n item.updatedtime = new Date().toISOString();\n msgEl.querySelector('.quikchat-message-content').innerHTML = this._processContent(content);\n msgEl.classList.remove('quikchat-typing');\n success = true;\n\n if (!this.userScrolledUp) {\n this._messagesArea.scrollTop = this._messagesArea.scrollHeight;\n }\n if (this._onMessageReplace) {\n this._onMessageReplace(this, n, content);\n }\n } catch (_error) {\n // Message ID not found\n }\n return success;\n }\n\n messageAddTypingIndicator(userString = '', align = 'left') {\n const msgid = this.messageAddFull({\n content: '',\n userString: userString,\n align: align,\n role: 'assistant',\n });\n const msgEl = this.messageGetDOMObject(msgid);\n msgEl.classList.add('quikchat-typing');\n const contentDiv = msgEl.querySelector('.quikchat-message-content');\n contentDiv.innerHTML = '<span class=\"quikchat-typing-dots\"><span>.</span><span>.</span><span>.</span></span>';\n return msgid;\n }\n\n setMessageFormatter(formatter) {\n this._messageFormatter = formatter;\n }\n\n setSanitize(sanitize) {\n this._sanitize = sanitize;\n }\n\n // history functions\n /**\n *\n * @param {*} n\n * @param {*} m\n * @returns array of history messages\n */\n historyGet(n, m) {\n if (n === undefined) {\n return this._history.slice();\n }\n if (m === undefined) {\n if (n < 0) {\n return this._history.slice(n);\n }\n return this._history.slice(n, n + 1);\n }\n return this._history.slice(n, m);\n }\n\n historyClear() {\n this.msgid = 0;\n this._history = [];\n }\n\n historyGetLength() {\n return this._history.length;\n }\n\n historyGetMessage(n) {\n if (n >= 0 && n < this._history.length) {\n return this._history[n];\n }\n return {};\n }\n\n historyGetMessageContent(n) {\n if (n >= 0 && n < this._history.length) {\n return this._history[n].content;\n }\n return \"\";\n }\n\n historyExport() {\n return this._history.map((item) => ({\n msgid: item.msgid,\n content: item.content,\n userString: item.userString,\n align: item.align,\n role: item.role,\n userID: item.userID,\n visible: item.visible,\n tags: item.tags ? item.tags.slice() : [],\n timestamp: item.timestamp,\n updatedtime: item.updatedtime,\n }));\n }\n\n historyImport(data) {\n // Clear existing messages from DOM and history\n this._messagesArea.innerHTML = '';\n this._history = [];\n this.msgid = 0;\n\n for (const entry of data) {\n this.messageAddFull({\n content: entry.content || '',\n userString: entry.userString || 'user',\n align: entry.align || 'right',\n role: entry.role || 'user',\n userID: entry.userID,\n visible: entry.visible,\n tags: entry.tags,\n });\n }\n }\n\n changeTheme(newTheme) {\n this._chatWidget.classList.remove(this._theme);\n this._chatWidget.classList.add(newTheme);\n this._theme = newTheme;\n }\n\n get theme() {\n return this._theme;\n }\n\n static version() {\n return { \"version\": \"1.2.4\", \"license\": \"BSD-2\", \"url\": \"https://github/deftio/quikchat\" };\n }\n\n /**\n * quikchat.loremIpsum() - Generate a simple string of Lorem Ipsum text (sample typographer's text) of numChars in length.\n * borrowed from github.com/deftio/bitwrench.js\n * @param {number} numChars - The number of characters to generate (random btw 25 and 150 if undefined).\n * @param {number} [startSpot=0] - The starting index in the Lorem Ipsum text. If undefined, a random startSpot will be generated.\n * @param {boolean} [startWithCapitalLetter=true] - If true, capitalize the first character or inject a capital letter if the first character isn't a capital letter.\n *\n * @returns {string} A string of Lorem Ipsum text.\n *\n * @example\n * // Returns 200 characters of Lorem Ipsum starting from index 50\n * loremIpsum(200, 50);\n *\n * @example\n * //Returns a 200 Lorem Ipsum characters starting from a random index\n * loremIpsum(200);\n */\n\n static loremIpsum(numChars, startSpot = undefined, startWithCapitalLetter = true) {\n const loremText = \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. \";\n\n if (typeof numChars !== \"number\") {\n numChars = Math.floor(Math.random() * 126) + 25;\n }\n\n if (startSpot === undefined) {\n startSpot = Math.floor(Math.random() * loremText.length);\n }\n\n startSpot = startSpot % loremText.length;\n\n // Move startSpot to the next non-whitespace and non-punctuation character\n while (loremText[startSpot] === ' ' || /[.,:;!?]/.test(loremText[startSpot])) {\n startSpot = (startSpot + 1) % loremText.length;\n }\n\n const l = loremText.substring(startSpot) + loremText.substring(0, startSpot);\n\n let s = \"\";\n while (numChars > 0) {\n s += numChars < l.length ? l.substring(0, numChars) : l;\n numChars -= l.length;\n }\n\n if (s[s.length - 1] === \" \") {\n s = s.substring(0, s.length - 1) + \".\"; // always end on non-whitespace. \".\" was chosen arbitrarily.\n }\n\n if (startWithCapitalLetter) {\n s = s[0].toUpperCase() + s.substring(1);\n }\n\n return s;\n };\n\n\n}\n\nexport default quikchat;\n"],"names":["quikchat","parentElement","onSend","arguments","length","undefined","options","_classCallCheck","meta","_objectSpread","theme","trackHistory","showTimestamps","titleArea","title","show","align","messagesArea","alternating","document","querySelector","this","_parentElement","_theme","_onSend","_messageFormatter","messageFormatter","_sanitize","sanitize","_createWidget","titleAreaSetContents","titleAreaShow","titleAreaHide","messagesAreaAlternateColors","messagesAreaShowTimestamps","direction","setDirection","_attachEventListeners","_historyLimit","_history","key","value","widgetHTML","concat","innerHTML","_chatWidget","_titleArea","_messagesWrapper","_messagesArea","_scrollBottomBtn","_inputArea","_textEntry","_sendButton","msgid","_this","addEventListener","text","trim","event","shiftKey","keyCode","preventDefault","_autoGrowTextarea","_this$_messagesArea","scrollTop","scrollHeight","clientHeight","userScrolledUp","_updateScrollBottomBtn","scrollToBottom","ctrlKey","ResizeObserver","_resizeObserver","_handleContainerResize","observe","callback","_onMessageAdded","_onMessageAppend","_onMessageReplace","_onMessageDelete","style","display","textAlign","inputAreaShow","inputAreaHide","enabled","disabled","textContent","dir","d","setAttribute","classList","add","remove","getAttribute","el","height","maxHeight","parseInt","getComputedStyle","getPropertyValue","Math","min","overflowY","isoString","Date","h","getHours","String","getMinutes","padStart","contains","toggle","str","div","createElement","content","_escapeHTML","alt","input","userString","role","userID","messageDiv","msgidClass","children","visible","tags","Array","isArray","slice","userDiv","contentDiv","_processContent","timestamp","toISOString","timestampSpan","_formatTimestamp","appendChild","updatedtime","push","shift","messageAddFull","n","success","removeChild","_error","splice","findIndex","item","msg","filter","msgEl","messageGetDOMObject","find","entry","current","messageGetVisible","messageSetVisible","tag","_step","count","_iterator","_createForOfIteratorHelper","s","done","includes","err","e","f","formatter","m","map","data","_step2","_iterator2","newTheme","get","version","license","url","numChars","startSpot","startWithCapitalLetter","loremText","floor","random","test","l","substring","toUpperCase"],"mappings":"gnEACMA,EAAQ,WAmDT,SA7CD,SAAAA,EAAYC,GAAiD,IAAlCC,EAAMC,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,WAAQ,EAAGG,EAAOH,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,+FAAEI,MAAAP,GACvD,IAOMQ,EAAIC,EAAAA,EAAA,CAAA,EAPU,CAChBC,MAAO,uBACPC,cAAc,EACdC,gBAAgB,EAChBC,UAAW,CAAEC,MAAO,OAAQC,MAAM,EAAOC,MAAO,UAChDC,aAAc,CAAEC,aAAa,KAECZ,GAEL,iBAAlBL,IACPA,EAAgBkB,SAASC,cAAcnB,IAE3CoB,KAAKC,eAAiBrB,EACtBoB,KAAKE,OAASf,EAAKE,MACnBW,KAAKG,QAAUtB,GAAkB,WAAQ,EACzCmB,KAAKI,kBAAoBjB,EAAKkB,kBAAoB,KAClDL,KAAKM,UAAYnB,EAAKoB,WAAY,EAClCP,KAAKQ,gBAEDrB,EAAKK,YACLQ,KAAKS,qBAAqBtB,EAAKK,UAAUC,MAAON,EAAKK,UAAUG,QACnC,IAAxBR,EAAKK,UAAUE,KACfM,KAAKU,gBAELV,KAAKW,iBAITxB,EAAKS,cACLI,KAAKY,4BAA4BzB,EAAKS,aAAaC,aAGnDV,EAAKI,gBACLS,KAAKa,4BAA2B,GAGhC1B,EAAK2B,WACLd,KAAKe,aAAa5B,EAAK2B,WAG3Bd,KAAKgB,wBACLhB,KAAKV,cAAqC,IAAtBH,EAAKG,aACzBU,KAAKiB,cAAgB,IACrBjB,KAAKkB,SAAW,EACpB,IAAC,CAAA,CAAAC,IAAA,gBAAAC,MAED,WACI,IAAMC,EAAU,2CAAAC,OAEgBtB,KAAKX,MAAK,slBAU1CW,KAAKC,eAAesB,UAAYF,EAChCrB,KAAKwB,YAAcxB,KAAKC,eAAeF,cAAc,kBACrDC,KAAKyB,WAAazB,KAAKwB,YAAYzB,cAAc,wBACjDC,KAAK0B,iBAAmB1B,KAAKwB,YAAYzB,cAAc,8BACvDC,KAAK2B,cAAgB3B,KAAKwB,YAAYzB,cAAc,2BACpDC,KAAK4B,iBAAmB5B,KAAK0B,iBAAiB3B,cAAc,2BAC5DC,KAAK6B,WAAa7B,KAAKwB,YAAYzB,cAAc,wBACjDC,KAAK8B,WAAa9B,KAAK6B,WAAW9B,cAAc,2BAChDC,KAAK+B,YAAc/B,KAAK6B,WAAW9B,cAAc,4BACjDC,KAAKgC,MAAQ,CACjB,GAEA,CAAAb,IAAA,wBAAAC,MAGA,WAAwB,IAAAa,EAAAjC,KACpBA,KAAK+B,YAAYG,iBAAiB,SAAS,WACvC,IAAMC,EAAOF,EAAKH,WAAWV,MAAMgB,OACtB,KAATD,GACJF,EAAK9B,QAAQ8B,EAAME,EACvB,IACAnC,KAAK8B,WAAWI,iBAAiB,WAAW,SAACG,GAEzC,GAAIA,EAAMC,UAA8B,KAAlBD,EAAME,QAAgB,CACxCF,EAAMG,iBACN,IAAML,EAAOF,EAAKH,WAAWV,MAAMgB,OACnC,GAAa,KAATD,EAAa,OACjBF,EAAK9B,QAAQ8B,EAAME,EACvB,CACJ,IAGAnC,KAAK8B,WAAWI,iBAAiB,SAAS,WAAA,OAAMD,EAAKQ,mBAAmB,IAExEzC,KAAK2B,cAAcO,iBAAiB,UAAU,WAC1C,IAAAQ,EAAkDT,EAAKN,cAA/CgB,EAASD,EAATC,UAAWC,EAAYF,EAAZE,aAAcC,EAAYH,EAAZG,aACjCZ,EAAKa,eAAiBH,EAAYE,EAAeD,EAAe,EAChEX,EAAKc,wBACT,IAGA/C,KAAK4B,iBAAiBM,iBAAiB,SAAS,WAAA,OAAMD,EAAKe,gBAAgB,IAG3EhD,KAAKwB,YAAYU,iBAAiB,WAAW,SAACG,GACtCA,EAAMY,SAAyB,QAAdZ,EAAMlB,MACvBkB,EAAMG,iBACNP,EAAKe,iBAEb,IAG8B,oBAAnBE,iBACPlD,KAAKmD,gBAAkB,IAAID,gBAAe,WAAA,OAAMjB,EAAKmB,wBAAwB,IAC7EpD,KAAKmD,gBAAgBE,QAAQrD,KAAKC,gBAE1C,GAEA,CAAAkB,IAAA,oBAAAC,MACA,SAAkBkC,GACdtD,KAAKG,QAAUmD,CACnB,GACA,CAAAnC,IAAA,4BAAAC,MACA,SAA0BkC,GACtBtD,KAAKuD,gBAAkBD,CAC3B,GAAC,CAAAnC,IAAA,6BAAAC,MACD,SAA2BkC,GACvBtD,KAAKwD,iBAAmBF,CAC5B,GAAC,CAAAnC,IAAA,8BAAAC,MACD,SAA4BkC,GACxBtD,KAAKyD,kBAAoBH,CAC7B,GAAC,CAAAnC,IAAA,6BAAAC,MACD,SAA2BkC,GACvBtD,KAAK0D,iBAAmBJ,CAC5B,GAEA,CAAAnC,IAAA,kBAAAC,MACA,WAC0C,SAAlCpB,KAAKyB,WAAWkC,MAAMC,QACtB5D,KAAKU,gBAELV,KAAKW,eAEb,GAAC,CAAAQ,IAAA,gBAAAC,MAED,WACIpB,KAAKyB,WAAWkC,MAAMC,QAAU,EACpC,GAAC,CAAAzC,IAAA,gBAAAC,MAED,WACIpB,KAAKyB,WAAWkC,MAAMC,QAAU,MACpC,GAAC,CAAAzC,IAAA,uBAAAC,MAED,SAAqB3B,GAAyB,IAAlBE,EAAKb,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,SAChCkB,KAAKyB,WAAWF,UAAY9B,EAC5BO,KAAKyB,WAAWkC,MAAME,UAAYlE,CACtC,GAAC,CAAAwB,IAAA,uBAAAC,MAED,WACI,OAAOpB,KAAKyB,WAAWF,SAC3B,GAAC,CAAAJ,IAAA,kBAAAC,MAED,WAC0C,SAAlCpB,KAAK6B,WAAW8B,MAAMC,QACtB5D,KAAK8D,gBAEL9D,KAAK+D,eAEb,GAAC,CAAA5C,IAAA,gBAAAC,MAED,WACIpB,KAAK6B,WAAW8B,MAAMC,QAAU,EACpC,GAAC,CAAAzC,IAAA,gBAAAC,MAED,WACIpB,KAAK6B,WAAW8B,MAAMC,QAAU,MACpC,GAAC,CAAAzC,IAAA,sBAAAC,MAED,SAAoB4C,GAChBhE,KAAK8B,WAAWmC,UAAYD,EAC5BhE,KAAK+B,YAAYkC,UAAYD,CACjC,GAAC,CAAA7C,IAAA,yBAAAC,MAED,SAAuBe,GACnBnC,KAAK+B,YAAYmC,YAAc/B,CACnC,GAAC,CAAAhB,IAAA,yBAAAC,MAED,WACI,OAAOpB,KAAK+B,YAAYmC,WAC5B,GAAC,CAAA/C,IAAA,eAAAC,MAED,SAAa+C,GACT,IAAMC,EAAY,QAARD,EAAgB,MAAQ,MAClCnE,KAAKwB,YAAY6C,aAAa,MAAOD,GAC3B,QAANA,EACApE,KAAKwB,YAAY8C,UAAUC,IAAI,gBAE/BvE,KAAKwB,YAAY8C,UAAUE,OAAO,eAE1C,GAAC,CAAArD,IAAA,eAAAC,MAED,WACI,OAAOpB,KAAKwB,YAAYiD,aAAa,QAAU,KACnD,GAAC,CAAAtD,IAAA,yBAAAC,MAED,WAEI,GACH,CAAAD,IAAA,iBAAAC,MAED,WACIpB,KAAK2B,cAAcgB,UAAY3C,KAAK2B,cAAciB,aAClD5C,KAAK8C,gBAAiB,EACtB9C,KAAK+C,wBACT,GAAC,CAAA5B,IAAA,yBAAAC,MAED,WACQpB,KAAK8C,eACL9C,KAAK4B,iBAAiB0C,UAAUC,IAAI,kCAEpCvE,KAAK4B,iBAAiB0C,UAAUE,OAAO,iCAE/C,GAAC,CAAArD,IAAA,oBAAAC,MAED,WACI,IAAMsD,EAAK1E,KAAK8B,WAChB4C,EAAGf,MAAMgB,OAAS,OAClB,IAAMC,EAAYC,SAASC,iBAAiBJ,GAAIK,iBAAiB,iCAAmC,IACpGL,EAAGf,MAAMgB,OAASK,KAAKC,IAAIP,EAAG9B,aAAcgC,GAAa,KACzDF,EAAGf,MAAMuB,UAAYR,EAAG9B,aAAegC,EAAY,OAAS,QAChE,GAAC,CAAAzD,IAAA,mBAAAC,MAED,SAAiB+D,GACb,IAAMf,EAAI,IAAIgB,KAAKD,GACbE,EAAIjB,EAAEkB,WAIZ,OADYD,EAAI,IAAM,IACT,IAHHE,OAAOnB,EAAEoB,cAAcC,SAAS,EAAG,KAGtB,KAFVJ,GAAK,GAAK,KAAO,KAGlC,GAAC,CAAAlE,IAAA,6BAAAC,MAED,SAA2B1B,GACnBA,EACAM,KAAK2B,cAAc2C,UAAUC,IAAI,4BAEjCvE,KAAK2B,cAAc2C,UAAUE,OAAO,2BAE5C,GAAC,CAAArD,IAAA,gCAAAC,MAED,WACI,OAAOpB,KAAK2B,cAAc2C,UAAUoB,SAAS,2BACjD,GAAC,CAAAvE,IAAA,mCAAAC,MAED,WACIpB,KAAK2B,cAAc2C,UAAUqB,OAAO,2BACxC,GAAC,CAAAxE,IAAA,cAAAC,MAED,SAAYwE,GACR,IAAMC,EAAM/F,SAASgG,cAAc,OAEnC,OADAD,EAAI3B,YAAc0B,EACXC,EAAItE,SACf,GAAC,CAAAJ,IAAA,kBAAAC,MAED,SAAgB2E,GASZ,OARuB,IAAnB/F,KAAKM,UACLyF,EAAU/F,KAAKgG,YAAYD,GACM,mBAAnB/F,KAAKM,YACnByF,EAAU/F,KAAKM,UAAUyF,IAEzB/F,KAAKI,oBACL2F,EAAU/F,KAAKI,kBAAkB2F,IAE9BA,CACX,GAEA,CAAA5E,IAAA,8BAAAC,MACA,WAAwC,IAAZ6E,IAAGnH,UAAAC,OAAA,QAAAC,IAAAF,UAAA,KAAAA,UAAA,GAO3B,OANImH,EACAjG,KAAK2B,cAAc2C,UAAUC,IAAI,8BAGjCvE,KAAK2B,cAAc2C,UAAUE,OAAO,+BAEzB,IAARyB,CACX,GAAC,CAAA9E,IAAA,oCAAAC,MACD,WACIpB,KAAK2B,cAAc2C,UAAUqB,OAAO,6BACxC,GAAC,CAAAxE,IAAA,iCAAAC,MACD,WACI,OAAOpB,KAAK2B,cAAc2C,UAAUoB,SAAS,6BACjD,GACA,CAAAvE,IAAA,iBAAAC,MACA,WAAsG,IAAvF8E,EAAKpH,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAEiH,QAAS,GAAII,WAAY,OAAQxG,MAAO,QAASyG,KAAM,OAAQC,QAAQ,GACtFrE,EAAQhC,KAAKgC,MACbsE,EAAaxG,SAASgG,cAAc,OACpCS,EAAa,kBAAoBhB,OAAOvD,GAAOyD,SAAS,GAAI,KAClEa,EAAWhC,UAAUC,IAAI,mBAAoBgC,GAC7CD,EAAWhC,UAAUC,IAAI,kBAAoB2B,EAAME,MAAQ,SAC3DE,EAAWhC,UAAUC,IAAI,mBAAqB2B,EAAMvG,OAAS,UAC7DK,KAAKgC,QACLsE,EAAWhC,UAAUC,IAAIvE,KAAK2B,cAAc6E,SAASzH,OAAS,GAAM,EAAI,qBAAuB,sBAG/F,IAAM0H,GAA4B,IAAlBP,EAAMO,QACjBA,IACDH,EAAW3C,MAAMC,QAAU,QAI/B,IAAM8C,EAAOC,MAAMC,QAAQV,EAAMQ,MAAQR,EAAMQ,KAAKG,QAAU,GAExDC,EAAUhH,SAASgG,cAAc,OACvCgB,EAAQxC,UAAUC,IAAI,uBACtBuC,EAAQnD,MAAME,UAAYqC,EAAMvG,MAChCmH,EAAQvF,UAAY2E,EAAMC,WAE1B,IAAMY,EAAajH,SAASgG,cAAc,OAC1CiB,EAAWzC,UAAUC,IAAI,4BACzBwC,EAAWpD,MAAME,UAAYqC,EAAMvG,MACnCoH,EAAWxF,UAAYvB,KAAKgH,gBAAgBd,EAAMH,SAElD,IAAMkB,GAAY,IAAI7B,MAAO8B,cACvBC,EAAgBrH,SAASgG,cAAc,QAC7CqB,EAAc7C,UAAUC,IAAI,sBAC5B4C,EAAcjD,YAAclE,KAAKoH,iBAAiBH,GAElDX,EAAWe,YAAYP,GACvBR,EAAWe,YAAYN,GACvBT,EAAWe,YAAYF,GACvBnH,KAAK2B,cAAc0F,YAAYf,GAG1BtG,KAAK8C,iBACN9C,KAAK2B,cAAcgB,UAAY3C,KAAK2B,cAAciB,cAGtD5C,KAAK8B,WAAWV,MAAQ,GACxBpB,KAAKyC,oBACL,IAAM6E,EAAcL,EAapB,OAXIjH,KAAKV,eACLU,KAAKkB,SAASqG,KAAInI,EAAAA,EAAA,CAAG4C,MAAAA,GAAUkE,GAAK,GAAA,CAAEO,QAAAA,EAASC,KAAAA,EAAMO,UAAAA,EAAWK,YAAAA,EAAahB,WAAAA,KACzEtG,KAAKkB,SAASnC,OAASiB,KAAKiB,eAC5BjB,KAAKkB,SAASsG,SAIlBxH,KAAKuD,iBACLvD,KAAKuD,gBAAgBvD,KAAMgC,GAGxBA,CACX,GAAC,CAAAb,IAAA,gBAAAC,MAGD,WAAiF,IAAnE2E,EAAOjH,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAAIqH,EAAUrH,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,OAAQa,EAAKb,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,QAASsH,EAAItH,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,OACrE,OAAOkB,KAAKyH,eACR,CAAE1B,QAASA,EAASI,WAAYA,EAAYxG,MAAOA,EAAOyG,KAAMA,GAExE,GAAC,CAAAjF,IAAA,gBAAAC,MACD,SAAcsG,GACV,IAAIC,GAAU,EACd,IACI3H,KAAK2B,cAAciG,YAAY5H,KAAK2B,cAAc5B,cAAa,mBAAAuB,OAAoBiE,OAAOmC,GAAGjC,SAAS,GAAI,QAC1GkC,GAAU,CACd,CACA,MAAOE,GACH,CAQJ,OANIF,IACA3H,KAAKkB,SAAS4G,OAAO9H,KAAKkB,SAAS6G,WAAU,SAACC,GAAI,OAAKA,EAAKhG,QAAU0F,CAAC,IAAG,GACtE1H,KAAK0D,kBACL1D,KAAK0D,iBAAiB1D,KAAM0H,IAG7BC,CACX,GACA,CAAAxG,IAAA,sBAAAC,MAEA,SAAoBsG,GAChB,IAAIO,EAAM,KACV,IACIA,EAAMjI,KAAK2B,cAAc5B,cAAa,mBAAAuB,OAAoBiE,OAAOmC,GAAGjC,SAAS,GAAI,MACrF,CACA,MAAOoC,GACH,CAEJ,OAAOI,CACX,GACA,CAAA9G,IAAA,oBAAAC,MAEA,SAAkBsG,GACd,IAAI3B,EAAU,GACd,IACIA,EAAU/F,KAAKkB,SAASgH,QAAO,SAACF,GAAI,OAAKA,EAAKhG,QAAU0F,CAAC,IAAE,GAAG3B,OAClE,CACA,MAAO8B,GACH,CAEJ,OAAO9B,CACX,GAAC,CAAA5E,IAAA,oBAAAC,MAED,SAAkBsG,EAAGjB,GACjB,IAAM0B,EAAQnI,KAAKoI,oBAAoBV,GACvC,IAAKS,EAAO,OAAO,EACnBA,EAAMxE,MAAMC,QAAU6C,EAAU,GAAK,OACrC,IAAMuB,EAAOhI,KAAKkB,SAASmH,MAAK,SAACC,GAAK,OAAKA,EAAMtG,QAAU0F,CAAC,IAE5D,OADIM,IAAMA,EAAKvB,QAAUA,IAClB,CACX,GAAC,CAAAtF,IAAA,oBAAAC,MAED,SAAkBsG,GACd,IAAMM,EAAOhI,KAAKkB,SAASmH,MAAK,SAACC,GAAK,OAAKA,EAAMtG,QAAU0F,CAAC,IAC5D,QAAOM,IAAwB,IAAjBA,EAAKvB,OACvB,GAAC,CAAAtF,IAAA,uBAAAC,MAED,SAAqBsG,GACjB,IAAMa,EAAUvI,KAAKwI,kBAAkBd,GACvC,OAAO1H,KAAKyI,kBAAkBf,GAAIa,EACtC,GAAC,CAAApH,IAAA,yBAAAC,MAED,SAAuBsH,EAAKjC,GACxB,IACgCkC,EAD5BC,EAAQ,EAAEC,EAAAC,EACK9I,KAAKkB,UAAQ,IAAhC,IAAA2H,EAAAE,MAAAJ,EAAAE,EAAAnB,KAAAsB,MAAkC,CAAA,IAAvBhB,EAAIW,EAAAvH,MACP4G,EAAKtB,MAAQsB,EAAKtB,KAAKuC,SAASP,KAChC1I,KAAKyI,kBAAkBT,EAAKhG,MAAOyE,GACnCmC,IAER,CAAC,CAAA,MAAAM,GAAAL,EAAAM,EAAAD,EAAA,CAAA,QAAAL,EAAAO,GAAA,CACD,OAAOR,CACX,GAAC,CAAAzH,IAAA,iBAAAC,MAED,SAAesG,GACX,IAAMM,EAAOhI,KAAKkB,SAASmH,MAAK,SAACC,GAAK,OAAKA,EAAMtG,QAAU0F,CAAC,IAC5D,OAAOM,GAAQA,EAAKtB,KAAOsB,EAAKtB,KAAKG,QAAU,EACnD,GAAC,CAAA1F,IAAA,iBAAAC,MAED,SAAesG,EAAGhB,GACd,IAAMsB,EAAOhI,KAAKkB,SAASmH,MAAK,SAACC,GAAK,OAAKA,EAAMtG,QAAU0F,CAAC,IAC5D,QAAKM,IACLA,EAAKtB,KAAOC,MAAMC,QAAQF,GAAQA,EAAKG,QAAU,IAC1C,EACX,GAEA,CAAA1F,IAAA,uBAAAC,MAEA,SAAqBsG,EAAG3B,GACpB,IAAI4B,GAAU,EACd,IACI,IAAMQ,EAAQnI,KAAK2B,cAAc5B,cAAa,mBAAAuB,OAAoBiE,OAAOmC,GAAGjC,SAAS,GAAI,OACnFuC,EAAOhI,KAAKkB,SAASgH,QAAO,SAACI,GAAK,OAAKA,EAAMtG,QAAU0F,CAAC,IAAE,GAChEM,EAAKjC,SAAWA,EAChBiC,EAAKV,aAAc,IAAIlC,MAAO8B,cAC9BiB,EAAMpI,cAAc,6BAA6BwB,UAAYvB,KAAKgH,gBAAgBgB,EAAKjC,SACvFoC,EAAM7D,UAAUE,OAAO,mBACvBmD,GAAU,EAEL3H,KAAK8C,iBACN9C,KAAK2B,cAAcgB,UAAY3C,KAAK2B,cAAciB,cAElD5C,KAAKwD,kBACLxD,KAAKwD,iBAAiBxD,KAAM0H,EAAG3B,EAEvC,CAAE,MAAO8B,GACL,CAEJ,OAAOF,CACX,GAEA,CAAAxG,IAAA,wBAAAC,MAEA,SAAsBsG,EAAG3B,GACrB,IAAI4B,GAAU,EACd,IACI,IAAMQ,EAAQnI,KAAK2B,cAAc5B,cAAa,mBAAAuB,OAAoBiE,OAAOmC,GAAGjC,SAAS,GAAI,OACnFuC,EAAOhI,KAAKkB,SAASgH,QAAO,SAACI,GAAK,OAAKA,EAAMtG,QAAU0F,CAAC,IAAE,GAChEM,EAAKjC,QAAUA,EACfiC,EAAKV,aAAc,IAAIlC,MAAO8B,cAC9BiB,EAAMpI,cAAc,6BAA6BwB,UAAYvB,KAAKgH,gBAAgBjB,GAClFoC,EAAM7D,UAAUE,OAAO,mBACvBmD,GAAU,EAEL3H,KAAK8C,iBACN9C,KAAK2B,cAAcgB,UAAY3C,KAAK2B,cAAciB,cAElD5C,KAAKyD,mBACLzD,KAAKyD,kBAAkBzD,KAAM0H,EAAG3B,EAExC,CAAE,MAAO8B,GACL,CAEJ,OAAOF,CACX,GAAC,CAAAxG,IAAA,4BAAAC,MAED,WAA2D,IAAjC+E,EAAUrH,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAAIa,EAAKb,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,OACzCkD,EAAQhC,KAAKyH,eAAe,CAC9B1B,QAAS,GACTI,WAAYA,EACZxG,MAAOA,EACPyG,KAAM,cAEJ+B,EAAQnI,KAAKoI,oBAAoBpG,GAIvC,OAHAmG,EAAM7D,UAAUC,IAAI,mBACD4D,EAAMpI,cAAc,6BAC5BwB,UAAY,uFAChBS,CACX,GAAC,CAAAb,IAAA,sBAAAC,MAED,SAAoBiI,GAChBrJ,KAAKI,kBAAoBiJ,CAC7B,GAAC,CAAAlI,IAAA,cAAAC,MAED,SAAYb,GACRP,KAAKM,UAAYC,CACrB,GAGA,CAAAY,IAAA,aAAAC,MAMA,SAAWsG,EAAG4B,GACV,YAAUtK,IAAN0I,EACO1H,KAAKkB,SAAS2F,aAEf7H,IAANsK,EACI5B,EAAI,EACG1H,KAAKkB,SAAS2F,MAAMa,GAExB1H,KAAKkB,SAAS2F,MAAMa,EAAGA,EAAI,GAE/B1H,KAAKkB,SAAS2F,MAAMa,EAAG4B,EAClC,GAAC,CAAAnI,IAAA,eAAAC,MAED,WACIpB,KAAKgC,MAAQ,EACbhC,KAAKkB,SAAW,EACpB,GAAC,CAAAC,IAAA,mBAAAC,MAED,WACI,OAAOpB,KAAKkB,SAASnC,MACzB,GAAC,CAAAoC,IAAA,oBAAAC,MAED,SAAkBsG,GACd,OAAIA,GAAK,GAAKA,EAAI1H,KAAKkB,SAASnC,OACrBiB,KAAKkB,SAASwG,GAElB,CAAA,CACX,GAAC,CAAAvG,IAAA,2BAAAC,MAED,SAAyBsG,GACrB,OAAIA,GAAK,GAAKA,EAAI1H,KAAKkB,SAASnC,OACrBiB,KAAKkB,SAASwG,GAAG3B,QAErB,EACX,GAAC,CAAA5E,IAAA,gBAAAC,MAED,WACI,OAAOpB,KAAKkB,SAASqI,KAAI,SAACvB,GAAI,MAAM,CAChChG,MAAOgG,EAAKhG,MACZ+D,QAASiC,EAAKjC,QACdI,WAAY6B,EAAK7B,WACjBxG,MAAOqI,EAAKrI,MACZyG,KAAM4B,EAAK5B,KACXC,OAAQ2B,EAAK3B,OACbI,QAASuB,EAAKvB,QACdC,KAAMsB,EAAKtB,KAAOsB,EAAKtB,KAAKG,QAAU,GACtCI,UAAWe,EAAKf,UAChBK,YAAaU,EAAKV,YACrB,GACL,GAAC,CAAAnG,IAAA,gBAAAC,MAED,SAAcoI,GAEVxJ,KAAK2B,cAAcJ,UAAY,GAC/BvB,KAAKkB,SAAW,GAChBlB,KAAKgC,MAAQ,EAAE,IAESyH,EAFTC,EAAAZ,EAEKU,GAAI,IAAxB,IAAAE,EAAAX,MAAAU,EAAAC,EAAAhC,KAAAsB,MAA0B,CAAA,IAAfV,EAAKmB,EAAArI,MACZpB,KAAKyH,eAAe,CAChB1B,QAASuC,EAAMvC,SAAW,GAC1BI,WAAYmC,EAAMnC,YAAc,OAChCxG,MAAO2I,EAAM3I,OAAS,QACtByG,KAAMkC,EAAMlC,MAAQ,OACpBC,OAAQiC,EAAMjC,OACdI,QAAS6B,EAAM7B,QACfC,KAAM4B,EAAM5B,MAEpB,CAAC,CAAA,MAAAwC,GAAAQ,EAAAP,EAAAD,EAAA,CAAA,QAAAQ,EAAAN,GAAA,CACL,GAAC,CAAAjI,IAAA,cAAAC,MAED,SAAYuI,GACR3J,KAAKwB,YAAY8C,UAAUE,OAAOxE,KAAKE,QACvCF,KAAKwB,YAAY8C,UAAUC,IAAIoF,GAC/B3J,KAAKE,OAASyJ,CAClB,GAAC,CAAAxI,IAAA,QAAAyI,IAED,WACI,OAAO5J,KAAKE,MAChB,MAAC,CAAA,CAAAiB,IAAA,UAAAC,MAED,WACI,MAAO,CAAEyI,QAAW,QAASC,QAAW,QAASC,IAAO,iCAC5D,GAEA,CAAA5I,IAAA,aAAAC,MAkBA,SAAkB4I,GAAgE,IAAtDC,EAASnL,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,QAAGE,EAAWkL,IAAsBpL,UAAAC,OAAA,QAAAC,IAAAF,UAAA,KAAAA,UAAA,GAC/DqL,EAAY,icAalB,IAXwB,iBAAbH,IACPA,EAAWhF,KAAKoF,MAAsB,IAAhBpF,KAAKqF,UAAkB,SAG/BrL,IAAdiL,IACAA,EAAYjF,KAAKoF,MAAsBD,IAAhBnF,KAAKqF,WAGhCJ,GAAwBE,IAGQ,MAAzBA,EAAUF,IAAsB,WAAWK,KAAKH,EAAUF,KAC7DA,GAAaA,EAAY,GAAKE,IAMlC,IAHA,IAAMI,EAAIJ,EAAUK,UAAUP,GAAaE,EAAUK,UAAU,EAAGP,GAE9DlB,EAAI,GACDiB,EAAW,GACdjB,GAAKiB,EAAWO,EAAExL,OAASwL,EAAEC,UAAU,EAAGR,GAAYO,EACtDP,GAAYO,EAAExL,OAWlB,MARwB,MAApBgK,EAAEA,EAAEhK,OAAS,KACbgK,EAAIA,EAAEyB,UAAU,EAAGzB,EAAEhK,OAAS,GAAK,KAGnCmL,IACAnB,EAAIA,EAAE,GAAG0B,cAAgB1B,EAAEyB,UAAU,IAGlCzB,CACX,gGAAC,CA1pBS"}
|