{"version":3,"file":"controller.js","sources":["../src/js/componentCatTrack.js","../src/js/util.js","../src/js/componentAccordion.js","../src/js/componentCloseOpen.js","../src/js/componentCodeBlockFix.js","../src/js/componentCopyButtons.js","../src/js/componentFastLoad.js","../src/node_modules/prop-types/lib/ReactPropTypesSecret.js","../src/node_modules/prop-types/factoryWithThrowingShims.js","../src/node_modules/prop-types/index.js","../src/node_modules/preact/dist/preact.mjs","../src/widgets/deluge/FreeformQuestion.js","../src/widgets/deluge/InputField.js","../src/widgets/deluge/MainWidget.js","../src/widgets/deluge/deluge.js","../src/widgets/suggestion/SuggestionCardList.js","../src/widgets/suggestion/suggestion.js","../src/widgets/widgets.js","../src/js/componentFeedback.js","../src/js/componentTabs.js","../src/js/componentGuides.js","../src/js/componentLightbox.js","../src/js/componentOpenAPI.js","../src/js/componentOpenLink.js","../src/js/componentPillStrip.js","../src/js/componentSidebar.js","../src/js/componentStitchSidebar.js","../src/js/componentToggleController.js","../src/main/controller.js"],"sourcesContent":["function setAuthKey(key) {\n window.__ctlst_authkey = key;\n}\n\nexport function setup() {\n setAuthKey(\n 'Basic OGY1OGIxMDMtODQwOS00OTM1LWE5MDEtMjhmYzgzMWQ3ZmY1Ojg4OVYxbE1lNG9FYU5Mbmo3RFFnWTVEalNMT1g5ZHVuSGNIZmNUaVlwTEJDYWs3UmhQZzR3bzB1ajJnZk1wMmc='\n );\n\n const catTrackFn = window.__cat_track_event\n ? window.__cat_track_event\n : function () {\n console.log('__cat_track_event not found');\n };\n\n // console.log('[*] CatTrack initialized.');\n const sessionId = 'unknown';\n const userId = {};\n\n catTrackFn(\n {\n TRACKING_ENABLED: true,\n CONSOLE_TRACKING: false,\n },\n 'docs',\n {type: 'VISIT', subType: 'DIRECT_LINK_HIT'},\n sessionId,\n userId,\n {},\n {}\n );\n}\n","export function isLeafNode($node) {\n return !$node.siblings('ul:not(.simple)').length;\n}\n\nexport function toArray(arrayLike) {\n const result = [];\n for (let i = 0; i < arrayLike.length; i += 1) {\n result.push(arrayLike[i]);\n }\n\n return result;\n}\n\n/* Checks a whitelist for non-leaf nodes that should trigger a full page reload */\nexport function requiresPageload($node) {\n const docsExcludedNav = window.docsExcludedNav;\n\n if (!docsExcludedNav || !docsExcludedNav.length) {\n return false;\n }\n\n for (let i = 0; i < docsExcludedNav.length; i += 1) {\n if ($node[0].href.indexOf(docsExcludedNav[i]) !== -1) {\n return true;\n }\n }\n return false;\n}\n\nexport function throttle(func, wait) {\n let args = null;\n let result = null;\n let timeout = null;\n let previous = 0;\n\n function later() {\n previous = Date.now();\n timeout = null;\n result = func.apply(...args);\n if (!timeout) {\n args = null;\n }\n }\n\n return function (...newArgs) {\n const now = Date.now();\n const remaining = wait - (now - previous);\n args = newArgs;\n if (remaining <= 0 || remaining > wait) {\n if (timeout) {\n window.clearTimeout(timeout);\n timeout = null;\n }\n\n previous = now;\n result = func(...args);\n if (!timeout) {\n args = null;\n }\n } else if (!timeout) {\n timeout = window.setTimeout(later, remaining);\n }\n\n return result;\n };\n}\n\nexport function reportAnalytics(eventName, data) {\n console.log('report analytics', eventName, data);\n}\n\nexport class Dispatcher {\n constructor() {\n this.listeners = [];\n }\n\n listen(handler) {\n this.listeners.push(handler);\n }\n\n dispatch(ctx) {\n for (let i = 0; i < this.listeners.length; i += 1) {\n this.listeners[i](ctx);\n }\n }\n}\n","import {reportAnalytics} from './util';\n\nconst COLLAPSED_PROPERTY = 'accordion--collapsed';\n\n/**\n * Expands and collapses the accordion. Changes the label for the\n * action, i.e., \"Expand\" or \"Collapse\"\n * @param {object} element The accordion element.\n * @returns {void}\n */\nfunction accordionShowHide(element) {\n element.classList.toggle(COLLAPSED_PROPERTY);\n\n const control = element.querySelector('.accordion__action');\n control.innerHTML = (control.innerHTML === 'Expand') ? 'Collapse' : 'Expand';\n\n const title = element.querySelector('.accordion__title').innerText;\n reportAnalytics('Accordion Toggled', {\n 'title': title,\n 'status': element.classList.contains(COLLAPSED_PROPERTY) ? 'collapsed' : 'expanded'\n });\n}\n\nexport function setup() {\n // Get accordions and assign listeners to handle expand/collapse\n const accordionElements = document.getElementsByClassName('accordion');\n for (let i = 0; i < accordionElements.length; i += 1) {\n const element = accordionElements[i];\n const button = element.querySelector('.accordion__button');\n\n button.addEventListener('click', accordionShowHide.bind(this, element));\n }\n}\n","export function setup() {\n const showNavButton = document.getElementById('showNav');\n if (showNavButton) {\n showNavButton.onclick = () => {\n document.getElementById('sphinxsidebar').style.display = 'block';\n document.getElementById('left-column').style.display = 'flex';\n document.getElementById('showNav').style.display = 'none';\n };\n }\n\n const closeNavButton = document.getElementById('closeNav');\n if (closeNavButton) {\n closeNavButton.onclick = () => {\n document.getElementById('showNav').style.display = 'flex';\n document.getElementById('left-column').style.display = 'none';\n };\n }\n}\n","/*\ncode-blocks with the :linenos: options render an html table, unlike\nregular code-blocks. This component moves the button row into a new row\nof the html table to fix the visual alignment.\n\n*/\n\nfunction isLineNumberBlock(block) {\n return Boolean(block.getElementsByClassName('linenos').length);\n}\n\nfunction isCaptionBlock(block) {\n return Boolean(block.getElementsByClassName('caption-text').length);\n}\n\nfunction hasButtonRow(block) {\n return Boolean(block.getElementsByClassName('button-row')[0]);\n}\n\nfunction moveButtonRowToTable(block) {\n // Select existing elements\n const buttonRow = block.getElementsByClassName('button-row')[0];\n const tableBody = block.getElementsByClassName('highlighttable')[0].childNodes[0];\n\n // Create new table elements\n const tableButtonRow = document.createElement('tr');\n const linenosSpacer = document.createElement('td');\n const buttonRowDestination = document.createElement('td');\n\n // Add class for { table-layout: fixed; } styling\n linenosSpacer.className = 'linenos-button-row-spacer';\n\n // Manipulate the DOM\n tableBody.insertBefore(tableButtonRow, tableBody.firstChild);\n tableButtonRow.appendChild(linenosSpacer);\n tableButtonRow.appendChild(buttonRowDestination);\n buttonRowDestination.appendChild(buttonRow);\n}\n\nfunction moveButtonRowBelowCaption(block) {\n // Select existing elements\n const buttonRow = block.getElementsByClassName('button-row')[0];\n const caption = block.getElementsByClassName('code-block-caption')[0];\n\n // console.log('MOVING BELOW CAPTION');\n\n // Manipulate the DOM\n caption.parentNode.insertBefore(buttonRow, caption.nextSibling);\n}\n\nfunction fixCodeBlock(block) {\n if (isLineNumberBlock(block)) {\n moveButtonRowToTable(block);\n }\n else if (isCaptionBlock(block)) {\n moveButtonRowBelowCaption(block);\n }\n}\n\nexport function setup() {\n const codeblocks = document.getElementsByClassName('button-code-block');\n for (const codeblock of codeblocks) {\n if (hasButtonRow(codeblock)) {\n fixCodeBlock(codeblock);\n }\n }\n}\n","import {reportAnalytics, toArray} from './util';\n\nconst TOOLTIP_STATE_ACTIVE = 'code-button__tooltip--active';\nconst TOOLTIP_STATE_INACTIVE = 'code-button__tooltip--inactive';\n\nfunction cancelAndWait(f, timeoutID, ms) {\n if (timeoutID >= 0) {\n window.clearTimeout(timeoutID);\n }\n\n return window.setTimeout(f, ms);\n}\n\nfunction isCopyableCodeBlock(block) {\n return Boolean(block.getElementsByClassName('copyable-code-block')[0]);\n}\n\nexport function setup() {\n const buttonCodeBlocks = document.getElementsByClassName('button-code-block');\n const copyableBlocks = toArray(buttonCodeBlocks).filter(isCopyableCodeBlock);\n\n for (const block of copyableBlocks) {\n const highlightElement = block.getElementsByClassName('highlight')[0];\n if (!highlightElement) {\n return;\n }\n\n const buttonRow = block.getElementsByClassName('button-row')[0];\n const copyButton = buttonRow.getElementsByClassName('code-button--copy')[0];\n if (!copyButton) {\n return;\n }\n\n const popupElement = document.createElement('div');\n popupElement.innerText = 'copied';\n popupElement.classList.add('code-button__tooltip');\n popupElement.classList.add(TOOLTIP_STATE_INACTIVE);\n let closePopupTimer = -1;\n\n copyButton.appendChild(popupElement);\n copyButton.addEventListener('click', () => {\n const tempElement = document.createElement('textarea');\n tempElement.style.position = 'fixed';\n document.body.appendChild(tempElement);\n const text = highlightElement.innerText.trim();\n tempElement.value = text;\n tempElement.select();\n\n try {\n const successful = document.execCommand('copy');\n if (!successful) {\n throw new Error('Failed to copy');\n }\n\n popupElement.classList.replace(TOOLTIP_STATE_INACTIVE, TOOLTIP_STATE_ACTIVE);\n closePopupTimer = cancelAndWait(() => {\n popupElement.classList.replace(TOOLTIP_STATE_ACTIVE, TOOLTIP_STATE_INACTIVE);\n }, closePopupTimer, 1500);\n } catch (err) {\n console.error(err);\n }\n\n document.body.removeChild(tempElement);\n\n reportAnalytics('Codeblock Copied', {'code': text});\n });\n }\n}\n","import * as util from './util';\n\n/* Wrapper around XMLHttpRequest to make it more convenient\n * Calls options.success(response, url), providing the response text and\n * the canonical URL after redirects.\n * Calls options.error() on error.\n * jQuery's wrapper does not supply XMLHttpRequest.responseURL, making\n * this rewrite necessary. */\nfunction xhrGet(url, options) {\n const xhr = new XMLHttpRequest();\n\n xhr.onload = function() {\n if (xhr.status >= 200 && xhr.status < 400) {\n options.success(xhr.responseText, xhr.responseURL);\n options.complete();\n } else {\n options.error();\n options.complete();\n }\n };\n\n xhr.onerror = function() {\n options.error();\n options.complete();\n };\n\n xhr.open('GET', url, true);\n try {\n xhr.send();\n } catch (err) {\n options.error();\n options.complete();\n }\n}\n\n// Because this is a SPA, the browser can't scroll to find hashes\n// on its own.\nwindow.addEventListener('hashchange', () => {\n if (!window.location.hash) { return; }\n\n const el = document.getElementById(window.location.hash.slice(1));\n if (!el) { return; }\n el.scrollIntoView(true);\n});\n\n// If the browser is sufficiently modern, make navbar links load only\n// content pieces to avoid a full page load.\nexport function setup(fastNav) {\n const project = $('body').attr('data-project');\n const isStitch = project === 'stitch' || project === 'realm';\n if (isStitch) {\n return false;\n }\n\n if (window.history === undefined ||\n document.querySelectorAll === undefined ||\n document.body.classList === undefined ||\n (new XMLHttpRequest()).responseURL === undefined) {\n return false;\n }\n\n let navRootElement = document.querySelector('.sphinxsidebarwrapper');\n let bodyElement = document.querySelector('.body');\n let curLoading = {};\n\n // Set up initial state so we can return to our initial landing page.\n window.history.replaceState({'href': window.location.href},\n document.querySelector('title').textContent,\n window.location.href);\n\n // Stop loading the currently-in-progress page.\n function abortLoading() {\n if (curLoading.timeoutID !== undefined) {\n window.clearTimeout(curLoading.timeoutID);\n }\n\n if (curLoading.xhr !== undefined) {\n curLoading.xhr.abort();\n }\n\n curLoading = {};\n }\n\n // Load the specified URL.\n function loadPage(href, createHistory) {\n if (href === undefined) {\n console.error('Going to undefined path');\n }\n\n abortLoading();\n bodyElement.classList.add('loading');\n\n // If something goes wrong while loading, we don't want to leave\n // people without a paddle. If we can't load after a long period of\n // time, bring back the original content.\n curLoading.timeoutID = window.setTimeout(() => {\n bodyElement.classList.remove('loading');\n curLoading.timeoutID = -1;\n }, 10000);\n\n const startTime = new Date();\n curLoading.xhr = xhrGet(href, {\n 'complete': () => {\n abortLoading();\n },\n 'error': (error) => {\n // Some browsers consider any file://-type request to be cross-origin.\n // Upon any kind of error, fall back to classic behavior\n console.error(`Failed to load ${href}`);\n window.location = href;\n },\n 'success': (pageText, trueUrl) => {\n const enlapsedMs = (new Date()) - startTime;\n bodyElement.classList.remove('loading');\n\n // Change URL before loading the DOM to properly resolve URLs\n if (createHistory && trueUrl !== window.location.href) {\n window.history.pushState({'href': trueUrl}, '', trueUrl);\n }\n\n const page = document.createElement('html');\n page.innerHTML = pageText;\n const title = page.querySelector('title').textContent;\n const newBody = page.querySelector('.body');\n const newNav = page.querySelector('.sphinxsidebarwrapper');\n\n // Fade in ONLY if we had enough time to start fading out.\n if (enlapsedMs > (250 / 4)) {\n newBody.classList.add('loading');\n }\n\n // Replace the DOM elements\n bodyElement.parentElement.replaceChild(newBody, bodyElement);\n bodyElement = newBody;\n navRootElement.parentElement.replaceChild(newNav, navRootElement);\n navRootElement = newNav;\n document.title = title;\n\n // Update dynamic page features\n fastNav.update();\n\n if (window.history.onnavigate) {\n window.history.onnavigate();\n }\n\n // Prime the new DOM so that we can set up our fade-in\n // animation and scroll the new contents to the top.\n window.setTimeout(() => {\n bodyElement.classList.remove('loading');\n\n // Scroll to the top of the page only if this is a new history entry.\n if (createHistory) {\n window.scroll(0, 0);\n }\n }, 1);\n }\n });\n }\n\n // Set up fastnav links\n const nodes = document.querySelectorAll('.sphinxsidebarwrapper > ul a.reference.internal');\n function handleClickFunction(ev) {\n // Ignore anything but vanilla click events, so that people can\n // still use special browser behaviors like open in new tab.\n if (!(ev.button !== 0 || ev.shiftKey || ev.altKey || ev.metaKey || ev.ctrlKey)) {\n ev.preventDefault();\n loadPage(ev.currentTarget.href, true);\n }\n }\n for (let i = 0; i < nodes.length; i += 1) {\n const node = nodes[i];\n if (!util.isLeafNode($(node)) && !util.requiresPageload($(node))) { continue; }\n\n node.addEventListener('click', handleClickFunction);\n }\n\n window.onpopstate = function(ev) {\n if (ev.state === null) { return; }\n loadPage(ev.state.href, false);\n };\n\n\n return true;\n}\n","/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nvar ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';\n\nmodule.exports = ReactPropTypesSecret;\n","/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nvar ReactPropTypesSecret = require('./lib/ReactPropTypesSecret');\n\nfunction emptyFunction() {}\nfunction emptyFunctionWithReset() {}\nemptyFunctionWithReset.resetWarningCache = emptyFunction;\n\nmodule.exports = function() {\n function shim(props, propName, componentName, location, propFullName, secret) {\n if (secret === ReactPropTypesSecret) {\n // It is still safe when called from React.\n return;\n }\n var err = new Error(\n 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +\n 'Use PropTypes.checkPropTypes() to call them. ' +\n 'Read more at http://fb.me/use-check-prop-types'\n );\n err.name = 'Invariant Violation';\n throw err;\n };\n shim.isRequired = shim;\n function getShim() {\n return shim;\n };\n // Important!\n // Keep this list in sync with production version in `./factoryWithTypeCheckers.js`.\n var ReactPropTypes = {\n array: shim,\n bigint: shim,\n bool: shim,\n func: shim,\n number: shim,\n object: shim,\n string: shim,\n symbol: shim,\n\n any: shim,\n arrayOf: getShim,\n element: shim,\n elementType: shim,\n instanceOf: getShim,\n node: shim,\n objectOf: getShim,\n oneOf: getShim,\n oneOfType: getShim,\n shape: getShim,\n exact: getShim,\n\n checkPropTypes: emptyFunctionWithReset,\n resetWarningCache: emptyFunction\n };\n\n ReactPropTypes.PropTypes = ReactPropTypes;\n\n return ReactPropTypes;\n};\n","/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nif (process.env.NODE_ENV !== 'production') {\n var ReactIs = require('react-is');\n\n // By explicitly using `prop-types` you are opting into new development behavior.\n // http://fb.me/prop-types-in-prod\n var throwOnDirectAccess = true;\n module.exports = require('./factoryWithTypeCheckers')(ReactIs.isElement, throwOnDirectAccess);\n} else {\n // By explicitly using `prop-types` you are opting into new production behavior.\n // http://fb.me/prop-types-in-prod\n module.exports = require('./factoryWithThrowingShims')();\n}\n","var VNode = function VNode() {};\n\nvar options = {};\n\nvar stack = [];\n\nvar EMPTY_CHILDREN = [];\n\nfunction h(nodeName, attributes) {\n\tvar children = EMPTY_CHILDREN,\n\t lastSimple,\n\t child,\n\t simple,\n\t i;\n\tfor (i = arguments.length; i-- > 2;) {\n\t\tstack.push(arguments[i]);\n\t}\n\tif (attributes && attributes.children != null) {\n\t\tif (!stack.length) stack.push(attributes.children);\n\t\tdelete attributes.children;\n\t}\n\twhile (stack.length) {\n\t\tif ((child = stack.pop()) && child.pop !== undefined) {\n\t\t\tfor (i = child.length; i--;) {\n\t\t\t\tstack.push(child[i]);\n\t\t\t}\n\t\t} else {\n\t\t\tif (typeof child === 'boolean') child = null;\n\n\t\t\tif (simple = typeof nodeName !== 'function') {\n\t\t\t\tif (child == null) child = '';else if (typeof child === 'number') child = String(child);else if (typeof child !== 'string') simple = false;\n\t\t\t}\n\n\t\t\tif (simple && lastSimple) {\n\t\t\t\tchildren[children.length - 1] += child;\n\t\t\t} else if (children === EMPTY_CHILDREN) {\n\t\t\t\tchildren = [child];\n\t\t\t} else {\n\t\t\t\tchildren.push(child);\n\t\t\t}\n\n\t\t\tlastSimple = simple;\n\t\t}\n\t}\n\n\tvar p = new VNode();\n\tp.nodeName = nodeName;\n\tp.children = children;\n\tp.attributes = attributes == null ? undefined : attributes;\n\tp.key = attributes == null ? undefined : attributes.key;\n\n\tif (options.vnode !== undefined) options.vnode(p);\n\n\treturn p;\n}\n\nfunction extend(obj, props) {\n for (var i in props) {\n obj[i] = props[i];\n }return obj;\n}\n\nvar defer = typeof Promise == 'function' ? Promise.resolve().then.bind(Promise.resolve()) : setTimeout;\n\nfunction cloneElement(vnode, props) {\n return h(vnode.nodeName, extend(extend({}, vnode.attributes), props), arguments.length > 2 ? [].slice.call(arguments, 2) : vnode.children);\n}\n\nvar IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i;\n\nvar items = [];\n\nfunction enqueueRender(component) {\n\tif (!component._dirty && (component._dirty = true) && items.push(component) == 1) {\n\t\t(options.debounceRendering || defer)(rerender);\n\t}\n}\n\nfunction rerender() {\n\tvar p,\n\t list = items;\n\titems = [];\n\twhile (p = list.pop()) {\n\t\tif (p._dirty) renderComponent(p);\n\t}\n}\n\nfunction isSameNodeType(node, vnode, hydrating) {\n\tif (typeof vnode === 'string' || typeof vnode === 'number') {\n\t\treturn node.splitText !== undefined;\n\t}\n\tif (typeof vnode.nodeName === 'string') {\n\t\treturn !node._componentConstructor && isNamedNode(node, vnode.nodeName);\n\t}\n\treturn hydrating || node._componentConstructor === vnode.nodeName;\n}\n\nfunction isNamedNode(node, nodeName) {\n\treturn node.normalizedNodeName === nodeName || node.nodeName.toLowerCase() === nodeName.toLowerCase();\n}\n\nfunction getNodeProps(vnode) {\n\tvar props = extend({}, vnode.attributes);\n\tprops.children = vnode.children;\n\n\tvar defaultProps = vnode.nodeName.defaultProps;\n\tif (defaultProps !== undefined) {\n\t\tfor (var i in defaultProps) {\n\t\t\tif (props[i] === undefined) {\n\t\t\t\tprops[i] = defaultProps[i];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn props;\n}\n\nfunction createNode(nodeName, isSvg) {\n\tvar node = isSvg ? document.createElementNS('http://www.w3.org/2000/svg', nodeName) : document.createElement(nodeName);\n\tnode.normalizedNodeName = nodeName;\n\treturn node;\n}\n\nfunction removeNode(node) {\n\tvar parentNode = node.parentNode;\n\tif (parentNode) parentNode.removeChild(node);\n}\n\nfunction setAccessor(node, name, old, value, isSvg) {\n\tif (name === 'className') name = 'class';\n\n\tif (name === 'key') {} else if (name === 'ref') {\n\t\tif (old) old(null);\n\t\tif (value) value(node);\n\t} else if (name === 'class' && !isSvg) {\n\t\tnode.className = value || '';\n\t} else if (name === 'style') {\n\t\tif (!value || typeof value === 'string' || typeof old === 'string') {\n\t\t\tnode.style.cssText = value || '';\n\t\t}\n\t\tif (value && typeof value === 'object') {\n\t\t\tif (typeof old !== 'string') {\n\t\t\t\tfor (var i in old) {\n\t\t\t\t\tif (!(i in value)) node.style[i] = '';\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (var i in value) {\n\t\t\t\tnode.style[i] = typeof value[i] === 'number' && IS_NON_DIMENSIONAL.test(i) === false ? value[i] + 'px' : value[i];\n\t\t\t}\n\t\t}\n\t} else if (name === 'dangerouslySetInnerHTML') {\n\t\tif (value) node.innerHTML = value.__html || '';\n\t} else if (name[0] == 'o' && name[1] == 'n') {\n\t\tvar useCapture = name !== (name = name.replace(/Capture$/, ''));\n\t\tname = name.toLowerCase().substring(2);\n\t\tif (value) {\n\t\t\tif (!old) node.addEventListener(name, eventProxy, useCapture);\n\t\t} else {\n\t\t\tnode.removeEventListener(name, eventProxy, useCapture);\n\t\t}\n\t\t(node._listeners || (node._listeners = {}))[name] = value;\n\t} else if (name !== 'list' && name !== 'type' && !isSvg && name in node) {\n\t\ttry {\n\t\t\tnode[name] = value == null ? '' : value;\n\t\t} catch (e) {}\n\t\tif ((value == null || value === false) && name != 'spellcheck') node.removeAttribute(name);\n\t} else {\n\t\tvar ns = isSvg && name !== (name = name.replace(/^xlink:?/, ''));\n\n\t\tif (value == null || value === false) {\n\t\t\tif (ns) node.removeAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase());else node.removeAttribute(name);\n\t\t} else if (typeof value !== 'function') {\n\t\t\tif (ns) node.setAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase(), value);else node.setAttribute(name, value);\n\t\t}\n\t}\n}\n\nfunction eventProxy(e) {\n\treturn this._listeners[e.type](options.event && options.event(e) || e);\n}\n\nvar mounts = [];\n\nvar diffLevel = 0;\n\nvar isSvgMode = false;\n\nvar hydrating = false;\n\nfunction flushMounts() {\n\tvar c;\n\twhile (c = mounts.pop()) {\n\t\tif (options.afterMount) options.afterMount(c);\n\t\tif (c.componentDidMount) c.componentDidMount();\n\t}\n}\n\nfunction diff(dom, vnode, context, mountAll, parent, componentRoot) {\n\tif (!diffLevel++) {\n\t\tisSvgMode = parent != null && parent.ownerSVGElement !== undefined;\n\n\t\thydrating = dom != null && !('__preactattr_' in dom);\n\t}\n\n\tvar ret = idiff(dom, vnode, context, mountAll, componentRoot);\n\n\tif (parent && ret.parentNode !== parent) parent.appendChild(ret);\n\n\tif (! --diffLevel) {\n\t\thydrating = false;\n\n\t\tif (!componentRoot) flushMounts();\n\t}\n\n\treturn ret;\n}\n\nfunction idiff(dom, vnode, context, mountAll, componentRoot) {\n\tvar out = dom,\n\t prevSvgMode = isSvgMode;\n\n\tif (vnode == null || typeof vnode === 'boolean') vnode = '';\n\n\tif (typeof vnode === 'string' || typeof vnode === 'number') {\n\t\tif (dom && dom.splitText !== undefined && dom.parentNode && (!dom._component || componentRoot)) {\n\t\t\tif (dom.nodeValue != vnode) {\n\t\t\t\tdom.nodeValue = vnode;\n\t\t\t}\n\t\t} else {\n\t\t\tout = document.createTextNode(vnode);\n\t\t\tif (dom) {\n\t\t\t\tif (dom.parentNode) dom.parentNode.replaceChild(out, dom);\n\t\t\t\trecollectNodeTree(dom, true);\n\t\t\t}\n\t\t}\n\n\t\tout['__preactattr_'] = true;\n\n\t\treturn out;\n\t}\n\n\tvar vnodeName = vnode.nodeName;\n\tif (typeof vnodeName === 'function') {\n\t\treturn buildComponentFromVNode(dom, vnode, context, mountAll);\n\t}\n\n\tisSvgMode = vnodeName === 'svg' ? true : vnodeName === 'foreignObject' ? false : isSvgMode;\n\n\tvnodeName = String(vnodeName);\n\tif (!dom || !isNamedNode(dom, vnodeName)) {\n\t\tout = createNode(vnodeName, isSvgMode);\n\n\t\tif (dom) {\n\t\t\twhile (dom.firstChild) {\n\t\t\t\tout.appendChild(dom.firstChild);\n\t\t\t}\n\t\t\tif (dom.parentNode) dom.parentNode.replaceChild(out, dom);\n\n\t\t\trecollectNodeTree(dom, true);\n\t\t}\n\t}\n\n\tvar fc = out.firstChild,\n\t props = out['__preactattr_'],\n\t vchildren = vnode.children;\n\n\tif (props == null) {\n\t\tprops = out['__preactattr_'] = {};\n\t\tfor (var a = out.attributes, i = a.length; i--;) {\n\t\t\tprops[a[i].name] = a[i].value;\n\t\t}\n\t}\n\n\tif (!hydrating && vchildren && vchildren.length === 1 && typeof vchildren[0] === 'string' && fc != null && fc.splitText !== undefined && fc.nextSibling == null) {\n\t\tif (fc.nodeValue != vchildren[0]) {\n\t\t\tfc.nodeValue = vchildren[0];\n\t\t}\n\t} else if (vchildren && vchildren.length || fc != null) {\n\t\t\tinnerDiffNode(out, vchildren, context, mountAll, hydrating || props.dangerouslySetInnerHTML != null);\n\t\t}\n\n\tdiffAttributes(out, vnode.attributes, props);\n\n\tisSvgMode = prevSvgMode;\n\n\treturn out;\n}\n\nfunction innerDiffNode(dom, vchildren, context, mountAll, isHydrating) {\n\tvar originalChildren = dom.childNodes,\n\t children = [],\n\t keyed = {},\n\t keyedLen = 0,\n\t min = 0,\n\t len = originalChildren.length,\n\t childrenLen = 0,\n\t vlen = vchildren ? vchildren.length : 0,\n\t j,\n\t c,\n\t f,\n\t vchild,\n\t child;\n\n\tif (len !== 0) {\n\t\tfor (var i = 0; i < len; i++) {\n\t\t\tvar _child = originalChildren[i],\n\t\t\t props = _child['__preactattr_'],\n\t\t\t key = vlen && props ? _child._component ? _child._component.__key : props.key : null;\n\t\t\tif (key != null) {\n\t\t\t\tkeyedLen++;\n\t\t\t\tkeyed[key] = _child;\n\t\t\t} else if (props || (_child.splitText !== undefined ? isHydrating ? _child.nodeValue.trim() : true : isHydrating)) {\n\t\t\t\tchildren[childrenLen++] = _child;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (vlen !== 0) {\n\t\tfor (var i = 0; i < vlen; i++) {\n\t\t\tvchild = vchildren[i];\n\t\t\tchild = null;\n\n\t\t\tvar key = vchild.key;\n\t\t\tif (key != null) {\n\t\t\t\tif (keyedLen && keyed[key] !== undefined) {\n\t\t\t\t\tchild = keyed[key];\n\t\t\t\t\tkeyed[key] = undefined;\n\t\t\t\t\tkeyedLen--;\n\t\t\t\t}\n\t\t\t} else if (min < childrenLen) {\n\t\t\t\t\tfor (j = min; j < childrenLen; j++) {\n\t\t\t\t\t\tif (children[j] !== undefined && isSameNodeType(c = children[j], vchild, isHydrating)) {\n\t\t\t\t\t\t\tchild = c;\n\t\t\t\t\t\t\tchildren[j] = undefined;\n\t\t\t\t\t\t\tif (j === childrenLen - 1) childrenLen--;\n\t\t\t\t\t\t\tif (j === min) min++;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tchild = idiff(child, vchild, context, mountAll);\n\n\t\t\tf = originalChildren[i];\n\t\t\tif (child && child !== dom && child !== f) {\n\t\t\t\tif (f == null) {\n\t\t\t\t\tdom.appendChild(child);\n\t\t\t\t} else if (child === f.nextSibling) {\n\t\t\t\t\tremoveNode(f);\n\t\t\t\t} else {\n\t\t\t\t\tdom.insertBefore(child, f);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (keyedLen) {\n\t\tfor (var i in keyed) {\n\t\t\tif (keyed[i] !== undefined) recollectNodeTree(keyed[i], false);\n\t\t}\n\t}\n\n\twhile (min <= childrenLen) {\n\t\tif ((child = children[childrenLen--]) !== undefined) recollectNodeTree(child, false);\n\t}\n}\n\nfunction recollectNodeTree(node, unmountOnly) {\n\tvar component = node._component;\n\tif (component) {\n\t\tunmountComponent(component);\n\t} else {\n\t\tif (node['__preactattr_'] != null && node['__preactattr_'].ref) node['__preactattr_'].ref(null);\n\n\t\tif (unmountOnly === false || node['__preactattr_'] == null) {\n\t\t\tremoveNode(node);\n\t\t}\n\n\t\tremoveChildren(node);\n\t}\n}\n\nfunction removeChildren(node) {\n\tnode = node.lastChild;\n\twhile (node) {\n\t\tvar next = node.previousSibling;\n\t\trecollectNodeTree(node, true);\n\t\tnode = next;\n\t}\n}\n\nfunction diffAttributes(dom, attrs, old) {\n\tvar name;\n\n\tfor (name in old) {\n\t\tif (!(attrs && attrs[name] != null) && old[name] != null) {\n\t\t\tsetAccessor(dom, name, old[name], old[name] = undefined, isSvgMode);\n\t\t}\n\t}\n\n\tfor (name in attrs) {\n\t\tif (name !== 'children' && name !== 'innerHTML' && (!(name in old) || attrs[name] !== (name === 'value' || name === 'checked' ? dom[name] : old[name]))) {\n\t\t\tsetAccessor(dom, name, old[name], old[name] = attrs[name], isSvgMode);\n\t\t}\n\t}\n}\n\nvar recyclerComponents = [];\n\nfunction createComponent(Ctor, props, context) {\n\tvar inst,\n\t i = recyclerComponents.length;\n\n\tif (Ctor.prototype && Ctor.prototype.render) {\n\t\tinst = new Ctor(props, context);\n\t\tComponent.call(inst, props, context);\n\t} else {\n\t\tinst = new Component(props, context);\n\t\tinst.constructor = Ctor;\n\t\tinst.render = doRender;\n\t}\n\n\twhile (i--) {\n\t\tif (recyclerComponents[i].constructor === Ctor) {\n\t\t\tinst.nextBase = recyclerComponents[i].nextBase;\n\t\t\trecyclerComponents.splice(i, 1);\n\t\t\treturn inst;\n\t\t}\n\t}\n\n\treturn inst;\n}\n\nfunction doRender(props, state, context) {\n\treturn this.constructor(props, context);\n}\n\nfunction setComponentProps(component, props, renderMode, context, mountAll) {\n\tif (component._disable) return;\n\tcomponent._disable = true;\n\n\tcomponent.__ref = props.ref;\n\tcomponent.__key = props.key;\n\tdelete props.ref;\n\tdelete props.key;\n\n\tif (typeof component.constructor.getDerivedStateFromProps === 'undefined') {\n\t\tif (!component.base || mountAll) {\n\t\t\tif (component.componentWillMount) component.componentWillMount();\n\t\t} else if (component.componentWillReceiveProps) {\n\t\t\tcomponent.componentWillReceiveProps(props, context);\n\t\t}\n\t}\n\n\tif (context && context !== component.context) {\n\t\tif (!component.prevContext) component.prevContext = component.context;\n\t\tcomponent.context = context;\n\t}\n\n\tif (!component.prevProps) component.prevProps = component.props;\n\tcomponent.props = props;\n\n\tcomponent._disable = false;\n\n\tif (renderMode !== 0) {\n\t\tif (renderMode === 1 || options.syncComponentUpdates !== false || !component.base) {\n\t\t\trenderComponent(component, 1, mountAll);\n\t\t} else {\n\t\t\tenqueueRender(component);\n\t\t}\n\t}\n\n\tif (component.__ref) component.__ref(component);\n}\n\nfunction renderComponent(component, renderMode, mountAll, isChild) {\n\tif (component._disable) return;\n\n\tvar props = component.props,\n\t state = component.state,\n\t context = component.context,\n\t previousProps = component.prevProps || props,\n\t previousState = component.prevState || state,\n\t previousContext = component.prevContext || context,\n\t isUpdate = component.base,\n\t nextBase = component.nextBase,\n\t initialBase = isUpdate || nextBase,\n\t initialChildComponent = component._component,\n\t skip = false,\n\t snapshot = previousContext,\n\t rendered,\n\t inst,\n\t cbase;\n\n\tif (component.constructor.getDerivedStateFromProps) {\n\t\tstate = extend(extend({}, state), component.constructor.getDerivedStateFromProps(props, state));\n\t\tcomponent.state = state;\n\t}\n\n\tif (isUpdate) {\n\t\tcomponent.props = previousProps;\n\t\tcomponent.state = previousState;\n\t\tcomponent.context = previousContext;\n\t\tif (renderMode !== 2 && component.shouldComponentUpdate && component.shouldComponentUpdate(props, state, context) === false) {\n\t\t\tskip = true;\n\t\t} else if (component.componentWillUpdate) {\n\t\t\tcomponent.componentWillUpdate(props, state, context);\n\t\t}\n\t\tcomponent.props = props;\n\t\tcomponent.state = state;\n\t\tcomponent.context = context;\n\t}\n\n\tcomponent.prevProps = component.prevState = component.prevContext = component.nextBase = null;\n\tcomponent._dirty = false;\n\n\tif (!skip) {\n\t\trendered = component.render(props, state, context);\n\n\t\tif (component.getChildContext) {\n\t\t\tcontext = extend(extend({}, context), component.getChildContext());\n\t\t}\n\n\t\tif (isUpdate && component.getSnapshotBeforeUpdate) {\n\t\t\tsnapshot = component.getSnapshotBeforeUpdate(previousProps, previousState);\n\t\t}\n\n\t\tvar childComponent = rendered && rendered.nodeName,\n\t\t toUnmount,\n\t\t base;\n\n\t\tif (typeof childComponent === 'function') {\n\n\t\t\tvar childProps = getNodeProps(rendered);\n\t\t\tinst = initialChildComponent;\n\n\t\t\tif (inst && inst.constructor === childComponent && childProps.key == inst.__key) {\n\t\t\t\tsetComponentProps(inst, childProps, 1, context, false);\n\t\t\t} else {\n\t\t\t\ttoUnmount = inst;\n\n\t\t\t\tcomponent._component = inst = createComponent(childComponent, childProps, context);\n\t\t\t\tinst.nextBase = inst.nextBase || nextBase;\n\t\t\t\tinst._parentComponent = component;\n\t\t\t\tsetComponentProps(inst, childProps, 0, context, false);\n\t\t\t\trenderComponent(inst, 1, mountAll, true);\n\t\t\t}\n\n\t\t\tbase = inst.base;\n\t\t} else {\n\t\t\tcbase = initialBase;\n\n\t\t\ttoUnmount = initialChildComponent;\n\t\t\tif (toUnmount) {\n\t\t\t\tcbase = component._component = null;\n\t\t\t}\n\n\t\t\tif (initialBase || renderMode === 1) {\n\t\t\t\tif (cbase) cbase._component = null;\n\t\t\t\tbase = diff(cbase, rendered, context, mountAll || !isUpdate, initialBase && initialBase.parentNode, true);\n\t\t\t}\n\t\t}\n\n\t\tif (initialBase && base !== initialBase && inst !== initialChildComponent) {\n\t\t\tvar baseParent = initialBase.parentNode;\n\t\t\tif (baseParent && base !== baseParent) {\n\t\t\t\tbaseParent.replaceChild(base, initialBase);\n\n\t\t\t\tif (!toUnmount) {\n\t\t\t\t\tinitialBase._component = null;\n\t\t\t\t\trecollectNodeTree(initialBase, false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (toUnmount) {\n\t\t\tunmountComponent(toUnmount);\n\t\t}\n\n\t\tcomponent.base = base;\n\t\tif (base && !isChild) {\n\t\t\tvar componentRef = component,\n\t\t\t t = component;\n\t\t\twhile (t = t._parentComponent) {\n\t\t\t\t(componentRef = t).base = base;\n\t\t\t}\n\t\t\tbase._component = componentRef;\n\t\t\tbase._componentConstructor = componentRef.constructor;\n\t\t}\n\t}\n\n\tif (!isUpdate || mountAll) {\n\t\tmounts.unshift(component);\n\t} else if (!skip) {\n\n\t\tif (component.componentDidUpdate) {\n\t\t\tcomponent.componentDidUpdate(previousProps, previousState, snapshot);\n\t\t}\n\t\tif (options.afterUpdate) options.afterUpdate(component);\n\t}\n\n\twhile (component._renderCallbacks.length) {\n\t\tcomponent._renderCallbacks.pop().call(component);\n\t}if (!diffLevel && !isChild) flushMounts();\n}\n\nfunction buildComponentFromVNode(dom, vnode, context, mountAll) {\n\tvar c = dom && dom._component,\n\t originalComponent = c,\n\t oldDom = dom,\n\t isDirectOwner = c && dom._componentConstructor === vnode.nodeName,\n\t isOwner = isDirectOwner,\n\t props = getNodeProps(vnode);\n\twhile (c && !isOwner && (c = c._parentComponent)) {\n\t\tisOwner = c.constructor === vnode.nodeName;\n\t}\n\n\tif (c && isOwner && (!mountAll || c._component)) {\n\t\tsetComponentProps(c, props, 3, context, mountAll);\n\t\tdom = c.base;\n\t} else {\n\t\tif (originalComponent && !isDirectOwner) {\n\t\t\tunmountComponent(originalComponent);\n\t\t\tdom = oldDom = null;\n\t\t}\n\n\t\tc = createComponent(vnode.nodeName, props, context);\n\t\tif (dom && !c.nextBase) {\n\t\t\tc.nextBase = dom;\n\n\t\t\toldDom = null;\n\t\t}\n\t\tsetComponentProps(c, props, 1, context, mountAll);\n\t\tdom = c.base;\n\n\t\tif (oldDom && dom !== oldDom) {\n\t\t\toldDom._component = null;\n\t\t\trecollectNodeTree(oldDom, false);\n\t\t}\n\t}\n\n\treturn dom;\n}\n\nfunction unmountComponent(component) {\n\tif (options.beforeUnmount) options.beforeUnmount(component);\n\n\tvar base = component.base;\n\n\tcomponent._disable = true;\n\n\tif (component.componentWillUnmount) component.componentWillUnmount();\n\n\tcomponent.base = null;\n\n\tvar inner = component._component;\n\tif (inner) {\n\t\tunmountComponent(inner);\n\t} else if (base) {\n\t\tif (base['__preactattr_'] && base['__preactattr_'].ref) base['__preactattr_'].ref(null);\n\n\t\tcomponent.nextBase = base;\n\n\t\tremoveNode(base);\n\t\trecyclerComponents.push(component);\n\n\t\tremoveChildren(base);\n\t}\n\n\tif (component.__ref) component.__ref(null);\n}\n\nfunction Component(props, context) {\n\tthis._dirty = true;\n\n\tthis.context = context;\n\n\tthis.props = props;\n\n\tthis.state = this.state || {};\n\n\tthis._renderCallbacks = [];\n}\n\nextend(Component.prototype, {\n\tsetState: function setState(state, callback) {\n\t\tif (!this.prevState) this.prevState = this.state;\n\t\tthis.state = extend(extend({}, this.state), typeof state === 'function' ? state(this.state, this.props) : state);\n\t\tif (callback) this._renderCallbacks.push(callback);\n\t\tenqueueRender(this);\n\t},\n\tforceUpdate: function forceUpdate(callback) {\n\t\tif (callback) this._renderCallbacks.push(callback);\n\t\trenderComponent(this, 2);\n\t},\n\trender: function render() {}\n});\n\nfunction render(vnode, parent, merge) {\n return diff(merge, vnode, {}, false, parent, false);\n}\n\nvar preact = {\n\th: h,\n\tcreateElement: h,\n\tcloneElement: cloneElement,\n\tComponent: Component,\n\trender: render,\n\trerender: rerender,\n\toptions: options\n};\n\nexport default preact;\nexport { h, h as createElement, cloneElement, Component, render, rerender, options };\n//# sourceMappingURL=preact.mjs.map\n","import PropTypes from 'prop-types';\nimport preact from 'preact';\n\nclass FreeformQuestion extends preact.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n 'error': false,\n 'text': ''\n };\n\n this.handleChange = this.handleChange.bind(this);\n }\n\n handleChange(ev) {\n const {hasError, store} = this.props;\n const value = ev.target.value;\n const error = hasError(value);\n\n if (error) {\n store.set('');\n ev.target.setCustomValidity(error);\n } else {\n store.set(value);\n ev.target.setCustomValidity('');\n }\n this.setState({\n 'error': error,\n 'text': value\n });\n }\n\n render() {\n const {errorText, placeholder} = this.props;\n const {error, text} = this.state;\n return (\n
\n \n \n {errorText}\n
\n \n );\n }\n}\n\nFreeformQuestion.propTypes = {\n 'errorText': PropTypes.string,\n 'hasError': PropTypes.func,\n 'placeholder': PropTypes.string,\n 'store': PropTypes.objectOf(PropTypes.func).isRequired\n};\n\nFreeformQuestion.defaultProps = {\n 'hasError': () => false\n};\n\nexport default FreeformQuestion;\n","import PropTypes from 'prop-types';\nimport preact from 'preact';\n\nclass InputField extends preact.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n 'error': false,\n 'text': ''\n };\n\n this.handleChange = this.handleChange.bind(this);\n }\n\n handleChange(ev) {\n const {hasError, store} = this.props;\n const value = ev.target.value;\n const error = hasError(value);\n\n if (error) {\n store.set('');\n ev.target.setCustomValidity(error);\n } else {\n store.set(value);\n ev.target.setCustomValidity('');\n }\n this.setState({\n 'error': error,\n 'text': value\n });\n }\n\n render() {\n const {errorText, inputType, placeholder} = this.props;\n const {error, text} = this.state;\n return (\n
\n \n
\n {errorText}\n
\n
\n );\n }\n}\n\nInputField.propTypes = {\n 'errorText': PropTypes.string,\n 'hasError': PropTypes.func,\n 'inputType': PropTypes.string,\n 'placeholder': PropTypes.string,\n 'store': PropTypes.objectOf(PropTypes.func).isRequired\n};\n\nInputField.defaultProps = {\n 'hasError': () => false,\n 'inputType': 'text'\n};\n\nexport default InputField;\n","import PropTypes from 'prop-types';\nimport preact from 'preact';\n\n// State enum\nconst STATE_INITIAL = 'Initial';\nconst STATE_VOTED = 'Voted';\n\nclass MainWidget extends preact.Component {\n constructor(props) {\n super(props);\n this.state = {\n 'closed': false,\n 'state': STATE_INITIAL\n };\n\n this.onSubmitFeedback = this.onSubmitFeedback.bind(this);\n this.onInitialVote = this.onInitialVote.bind(this);\n this.toggleVisibility = this.toggleVisibility.bind(this);\n }\n\n componentDidMount() {\n const savedFeedbackState = JSON.parse(window.sessionStorage.getItem('feedbackHidden'));\n if (savedFeedbackState) {\n this.setState({'closed': savedFeedbackState});\n }\n }\n\n onSubmitFeedback() {\n this.props.onSubmitFeedback(this.state.state);\n this.setState({'state': STATE_VOTED});\n }\n\n onInitialVote(e, state) {\n window.open('https://discord.gg/yn3fm8bjWU', '_blank');\n }\n\n toggleVisibility(event) {\n const {closed, state} = this.state;\n event.stopPropagation();\n if ((typeof state === 'boolean' || state === STATE_VOTED) && closed === false) {\n this.setState({'state': STATE_INITIAL});\n }\n this.setState(\n (prevState) => ({'closed': !prevState.closed}),\n () => window.sessionStorage.setItem('feedbackHidden', JSON.stringify(this.state.closed))\n );\n }\n\n render({children, canShowSuggestions, voteAcknowledgement}, {closed, state}) {\n const delugeBodyClass = (state === STATE_INITIAL)\n ? 'deluge-body'\n : 'deluge-body deluge-body-expanded';\n const delugeHeaderClass = 'deluge-header';\n const delugeClass = (state !== STATE_INITIAL && closed === false)\n ? 'deluge deluge-expanded'\n : 'deluge';\n\n return (\n
\n {closed ? (\n
\n \n
\n ) : (\n
\n
\n \n Need more info?\n \n
\n\n \n\n
\n
\n
\n )}\n
\n );\n }\n}\n\nMainWidget.propTypes = {\n 'error': PropTypes.bool.isRequired,\n 'onSubmitFeedback': PropTypes.func.isRequired,\n 'onSubmitVote': PropTypes.func.isRequired,\n 'onClear': PropTypes.func.isRequired,\n 'children': PropTypes.arrayOf(PropTypes.node),\n 'voteAcknowledgement': PropTypes.string,\n 'handleOpenDrawer': PropTypes.func.isRequired,\n 'canShowSuggestions': PropTypes.bool.isRequired\n};\n\nexport default MainWidget;\n","import FreeformQuestion from './FreeformQuestion';\nimport InputField from './InputField';\nimport MainWidget from './MainWidget';\nimport PropTypes from 'prop-types';\nimport preact from 'preact';\n\nconst MIN_CHAR_COUNT = 15;\nconst MIN_CHAR_ERROR_TEXT = `Please respond with at least ${MIN_CHAR_COUNT} characters.`;\nconst EMAIL_ERROR_TEXT = 'Please enter a valid email address.';\nconst EMAIL_PROMPT_TEXT = 'May we contact you about your feedback?';\n\nclass Deluge extends preact.Component {\n constructor(props) {\n super(props);\n\n const crypto = window.crypto || window.msCrypto;\n const buf = new Uint8Array(16);\n crypto.getRandomValues(buf);\n\n this.state = {\n answers: {},\n emailError: false,\n interactionId: btoa(\n Array.prototype.map.call(buf, ch => String.fromCharCode(ch)).join('')\n ).slice(0, -2),\n voteAcknowledgement: null,\n };\n this.onSubmitFeedback = this.onSubmitFeedback.bind(this);\n this.onSubmitVote = this.onSubmitVote.bind(this);\n }\n\n sendAnalytics(eventName, eventObj) {\n try {\n const user = window.analytics.user();\n const segmentUID = user.id();\n if (segmentUID) {\n eventObj.segmentUID = segmentUID.toString();\n } else {\n eventObj.segmentAnonymousID = user.anonymousId().toString();\n }\n window.analytics.track(eventName, eventObj);\n } catch (err) {\n console.error(err);\n }\n return eventObj;\n }\n\n onSubmitVote(vote) {\n this.sendVote(vote)\n .then(result => {\n this.setState({\n voteAcknowledgement: vote ? 'up' : 'down',\n });\n })\n .catch(err => {\n console.error(err);\n });\n }\n\n sendVote(vote) {}\n\n onSubmitFeedback(vote) {\n const fields = {};\n\n const answers = this.state.answers;\n const keys = Object.keys(answers);\n for (let i = 0; i < keys.length; i += 1) {\n const key = keys[i];\n\n // Report booleans and non-empty strings\n if (answers[key] || answers[key] === false) {\n fields[key] = answers[key];\n }\n }\n\n this.sendFeedback(vote, fields).catch(err => {\n console.error(err);\n });\n }\n\n sendFeedback(vote, fields) {}\n\n makeStore(key) {\n return {\n get: () => this.state.answers[key],\n set: val =>\n this.setState(prevState => ({\n answers: {\n ...prevState.answers,\n [key]: val,\n },\n })),\n };\n }\n\n validateEmail(input) {\n const hasError = !(\n input === '' || /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(input)\n );\n this.setState({emailError: hasError});\n return hasError;\n }\n\n render(props, {voteAcknowledgement}) {\n const noAnswersSubmitted =\n Object.keys(this.state.answers).length === 0 ||\n Object.values(this.state.answers).every(val => val === '');\n const hasError = noAnswersSubmitted || this.state.emailError;\n return (\n this.setState({answers: {}})}\n canShowSuggestions={props.canShowSuggestions}\n i\n handleOpenDrawer={props.handleOpenDrawer}\n error={hasError}\n >\n \n
{EMAIL_PROMPT_TEXT}
\n this.validateEmail(input)}\n inputType={'email'}\n store={this.makeStore('email')}\n placeholder=\"Email address\"\n />\n \n );\n }\n}\n\nDeluge.propTypes = {\n project: PropTypes.string.isRequired,\n path: PropTypes.string.isRequired,\n canShowSuggestions: PropTypes.bool.isRequired,\n handleOpenDrawer: PropTypes.func.isRequired,\n};\n\nexport default Deluge;\n","import PropTypes from 'prop-types';\nimport preact from 'preact';\n\nfunction addQueryParameters(url, pageName) {\n return `${url}?suggestor=${encodeURIComponent(pageName)}`;\n}\n\nfunction SuggestionCard({suggestion}) {\n const urlWithParams = addQueryParameters(suggestion.url, this.props.pageName);\n return (\n
\n \n
\n

{suggestion.title}

\n {suggestion.description &&

{suggestion.description}

}\n
\n
\n
\n );\n}\n\nfunction EmptyCard({handleDismissCard}) {\n return (\n
handleDismissCard()}>\n

This isn't what I was looking for

\n
\n );\n}\n\nclass SuggestionCardList extends preact.Component {\n render() {\n const suggestions = this.props.suggestions;\n const suggestionCards = suggestions.map((suggestion) =>\n \n );\n return (\n
\n {suggestionCards}\n \n
\n );\n }\n}\n\nSuggestionCard.propTypes = {\n 'pageName': PropTypes.string.isRequired,\n 'suggestion': PropTypes.object.isRequired\n};\n\nEmptyCard.propTypes = {\n 'handleDismissCard': PropTypes.func.isRequired\n};\n\nSuggestionCardList.propTypes = {\n 'suggestions': PropTypes.array.isRequired,\n 'handleDismissCard': PropTypes.func.isRequired,\n 'pageName': PropTypes.string.isRequired\n};\n\nexport default SuggestionCardList;\n","import PropTypes from 'prop-types';\nimport SuggestionCardList from './SuggestionCardList';\nimport preact from 'preact';\nimport {reportAnalytics} from '../../js/util';\n\nfunction getPageName() {\n const bodyElements = document.getElementsByClassName('body');\n if (!bodyElements.length) {\n return null;\n }\n\n const pagename = bodyElements[0].getAttribute('data-pagename');\n\n return pagename;\n}\n\nclass Suggestion extends preact.Component {\n constructor(props) {\n super(props);\n\n this.handleCloseDrawer = this.handleCloseDrawer.bind(this);\n this.handleDismissCard = this.handleDismissCard.bind(this);\n this.pageName = getPageName();\n\n this.state = {\n isLoaded: false,\n showThankYouMessage: false,\n suggestions: [],\n };\n }\n\n handleCloseDrawer() {\n this.props.handleCloseDrawer();\n reportAnalytics('Suggestion Drawer Closed', {\n userDismissedSuggestions: this.state.showThankYouMessage,\n });\n }\n\n handleDismissCard() {\n this.setState({showThankYouMessage: true});\n reportAnalytics('Suggestions Dismissed');\n }\n\n render() {\n const drawerIsOpen = this.props.drawerIsOpen ? 'is-open' : '';\n const showThankYouMessage = this.state.showThankYouMessage;\n let bodyDisplay; // eslint-disable-line init-declarations\n\n if (showThankYouMessage) {\n bodyDisplay = (\n
\n this.handleCloseDrawer()}\n class=\"fa fa-times suggestion-close suggestion-close-button\"\n />\n

Thanks for your feedback.

\n

\n We'll use it to make more helpful suggestions in the future.\n

\n
\n );\n } else {\n bodyDisplay = (\n
\n this.handleCloseDrawer()}\n class=\"fa fa-times suggestion-close suggestion-close-button\"\n />\n

Need help?

\n

Other MongoDB users have found these resources useful.

\n \n
\n );\n }\n return
{bodyDisplay}
;\n }\n}\n\nSuggestion.propTypes = {\n drawerIsOpen: PropTypes.bool.isRequired,\n handleCloseDrawer: PropTypes.func.isRequired,\n};\n\nexport default Suggestion;\n","import Deluge from './deluge/deluge';\nimport PropTypes from 'prop-types';\nimport Suggestion from './suggestion/suggestion';\nimport preact from 'preact';\n\nconst whitelist = [\n];\n\nclass Widgets extends preact.Component {\n constructor(props) {\n super(props);\n this.isSuggestionPage = this.isSuggestionPage(this.props.path);\n this.handleOpenDrawer = this.handleOpenDrawer.bind(this);\n this.handleCloseDrawer = this.handleCloseDrawer.bind(this);\n\n this.state = {\n 'drawerIsOpen': false,\n 'drawerHasOpened': false\n };\n }\n\n isSuggestionPage(path) {\n return whitelist.indexOf(path) >= 0;\n }\n\n handleOpenDrawer() {\n // Don't display suggestions again after closing\n if (this.state.drawerHasOpened) {\n return;\n }\n\n this.setState((prevState) => ({\n 'drawerIsOpen': true,\n 'drawerHasOpened': true\n }));\n }\n\n handleCloseDrawer() {\n this.setState((prevState) => ({\n 'drawerIsOpen': false\n }));\n }\n\n render() {\n // return null;\n return (\n
\n \n {this.isSuggestionPage &&\n \n }\n
\n );\n }\n}\n\nWidgets.propTypes = {\n 'project': PropTypes.string.isRequired,\n 'path': PropTypes.string.isRequired\n};\n\nexport default function widgets(project, path, rootElement) {\n preact.render('', rootElement, rootElement._widgetsRendered);\n\n if (path) {\n rootElement._widgetsRendered = preact.render(\n ,\n rootElement);\n }\n}\n","import widgets from '../widgets/widgets';\n\nlet project = null;\nlet ratingPanelElement = null;\n\n// Files on which we should not have feedback widgets\nconst blacklist = ['meta/404', 'search'];\n\nfunction getPageName() {\n const bodyElements = document.getElementsByClassName('body');\n if (!bodyElements.length) { return null; }\n\n const pagename = bodyElements[0].getAttribute('data-pagename');\n if (blacklist.indexOf(pagename) >= 0) {\n return null;\n }\n\n const isEol = bodyElements[0].getAttribute('data-eol');\n if (isEol) {\n return null;\n }\n\n return pagename;\n}\nexport function init() {\n project = document.body.getAttribute('data-project');\n ratingPanelElement = document.getElementById('rating-panel');\n}\n\nexport function setup() {\n // We require DOM storage. Don't show anything if support is not present.\n if (window.localStorage === undefined) { return; }\n\n const pageName = getPageName();\n if (ratingPanelElement) {\n widgets(project, pageName, ratingPanelElement);\n }\n}\n","import {Dispatcher, reportAnalytics, toArray} from './util';\n\nexport const tabsEventDispatcher = new Dispatcher();\n\n/**\n * Show only the first set of tabs at the top of the page.\n * @returns {void}\n */\nfunction hideTabBars() {\n const isTop = document.querySelector('.tabs-top');\n if (isTop) {\n const tabBars = $('.tab-strip--singleton');\n const mainTabBar = tabBars.first();\n // Remove any additional tab bars\n tabBars.slice(1).\n detach();\n // Position the main tab bar after the page title\n mainTabBar.\n detach().\n insertAfter('h1').\n first();\n }\n}\n\n/**\n * Return the tabPref object containing preferences for tab sets\n * and page specific prefs. Returns an empty object if it doesn't\n * exist.\n * @returns {object} Tab preference object.\n */\nexport function getTabPref() {\n return JSON.parse(window.localStorage.getItem('tabPref')) || {};\n}\n\n/**\n * Sets the tabPref object depending on whether the tab belongs\n * to set (e.g., \"drivers\") or if it's a one-off page.\n\n * @param {object} pref The \"tabId\" and \"type\" (tab set)\n * @param {boolean} anonymous Whether or not the tab being configured is anonymous.\n * @returns {void}\n */\nexport function setTabPref(pref, anonymous) {\n const tabPref = getTabPref();\n\n if (anonymous) {\n if (!tabPref.pages) {\n tabPref.pages = {};\n }\n\n tabPref.pages[window.location.pathname] = pref.tabId;\n } else {\n // Set top-level fields for tab set preferences\n tabPref[pref.type] = pref.tabId;\n }\n\n // Write pref object back to localStorage\n window.localStorage.setItem('tabPref', JSON.stringify(tabPref));\n}\n\nlet tabSets = {};\nclass TabSet {\n constructor(tabType, anonymous, tabStripElements, tabContents) {\n this.type = tabType;\n this.tabStrips = tabStripElements;\n this.tabContents = tabContents;\n this.anonymous = anonymous;\n\n // A set of all tabIds contained within this TabSet.\n this.tabIds = {};\n }\n\n /**\n * Return the first singleton tab ID on the page.\n * @returns {string} The first singleton tab ID found.\n */\n getFirstTabId() {\n const tabsElement = this.tabStrips[0].\n querySelector('.tab-strip__element[aria-selected=true]');\n if (!tabsElement) { return null; }\n\n return tabsElement.getAttribute('data-tabid');\n }\n\n setup() {\n if (this.tabStrips.length === 0) { return; }\n\n hideTabBars();\n\n for (const tabStrip of this.tabStrips) {\n for (const element of tabStrip.querySelectorAll('[data-tabid]')) {\n this.tabIds[element.getAttribute('data-tabid')] = true;\n\n element.onclick = (e) => {\n // Get the initial position of the tab clicked\n // to avoid page jumping after new tab is selected\n const initRect = element.getBoundingClientRect();\n\n // Get the position where the user scrolled to\n const initScrollY = window.scrollY;\n\n // Calc the distance from the tab strip to the top\n // of whatever the user has scrolled to\n const offset = initScrollY - initRect.y;\n\n // Get the tab ID of the clicked tab\n const tabId = e.target.getAttribute('data-tabid');\n\n // Build the pref object to set\n const pref = {};\n pref.tabId = tabId;\n pref.type = this.type;\n\n // Check to make sure value is not null, i.e., don't do anything on \"other\"\n if (tabId) {\n // Save the users preference and re-render\n this.update(tabId, true);\n\n // Get the position of tab strip after re-render\n const rects = element.getBoundingClientRect();\n\n // Reset the scroll position of the browser\n window.scrollTo(rects.x, rects.y + offset);\n\n reportAnalytics('Tab Selected', {\n 'tabId': tabId,\n 'title': e.target.innerText,\n 'tabSet': this.type\n });\n\n e.preventDefault();\n }\n };\n }\n }\n\n this.update(null, false);\n }\n\n update(tabId, isUserAction) {\n if (this.tabStrips.length === 0) { return; }\n\n if (!tabId) {\n const tabPref = getTabPref();\n if (this.anonymous && tabPref.pages && tabPref.pages[window.location.pathname]) {\n // Check if current page has a one-off page specific pref\n tabId = tabPref.pages[window.location.pathname];\n } else if (tabPref[this.type]) {\n tabId = tabPref[this.type];\n }\n }\n\n if (!tabId || !this.tabIds[tabId]) {\n tabId = this.getFirstTabId();\n\n if (!tabId) { return; }\n }\n\n // Show the appropriate tab content and mark the tab as active\n tabsEventDispatcher.dispatch({\n 'isUserAction': isUserAction,\n 'tabId': tabId,\n 'type': this.type\n });\n }\n\n /**\n * Marks the selected tab as active, handles special cases for the dropdown\n * @param {string} currentAttrValue The currently selected tab ID.\n * @returns {void}\n */\n showHideSelectedTab(currentAttrValue) {\n for (const tabStrip of this.tabStrips) {\n // Get the ,
  • and