{"version":3,"file":"index-CXUUnIYo.js","sources":["../../../node_modules/.pnpm/@hotwired+stimulus@3.2.2/node_modules/@hotwired/stimulus/dist/stimulus.js","../../../node_modules/.pnpm/@hotwired+strada@1.0.0-beta1_@hotwired+stimulus@3.2.2/node_modules/@hotwired/strada/dist/strada.js","../../../app/frontend/controllers/bridge/form_controller.js","../../../app/frontend/controllers/places_controller.ts","../../../app/frontend/controllers/remove_controller.js","../../../app/frontend/controllers/task_form_controller.js","../../../node_modules/.pnpm/@rails+request.js@0.0.9/node_modules/@rails/request.js/src/fetch_response.js","../../../node_modules/.pnpm/@rails+request.js@0.0.9/node_modules/@rails/request.js/src/request_interceptor.js","../../../node_modules/.pnpm/@rails+request.js@0.0.9/node_modules/@rails/request.js/src/lib/utils.js","../../../node_modules/.pnpm/@rails+request.js@0.0.9/node_modules/@rails/request.js/src/fetch_request.js","../../../node_modules/.pnpm/@rails+request.js@0.0.9/node_modules/@rails/request.js/src/verbs.js","../../../node_modules/.pnpm/tom-select@2.3.1/node_modules/tom-select/dist/esm/tom-select.complete.js","../../../app/frontend/controllers/tom_select_controller.js","../../../node_modules/.pnpm/stimulus-vite-helpers@3.1.0/node_modules/stimulus-vite-helpers/dist/index.js"],"sourcesContent":["/*\nStimulus 3.2.1\nCopyright © 2023 Basecamp, LLC\n */\nclass EventListener {\n constructor(eventTarget, eventName, eventOptions) {\n this.eventTarget = eventTarget;\n this.eventName = eventName;\n this.eventOptions = eventOptions;\n this.unorderedBindings = new Set();\n }\n connect() {\n this.eventTarget.addEventListener(this.eventName, this, this.eventOptions);\n }\n disconnect() {\n this.eventTarget.removeEventListener(this.eventName, this, this.eventOptions);\n }\n bindingConnected(binding) {\n this.unorderedBindings.add(binding);\n }\n bindingDisconnected(binding) {\n this.unorderedBindings.delete(binding);\n }\n handleEvent(event) {\n const extendedEvent = extendEvent(event);\n for (const binding of this.bindings) {\n if (extendedEvent.immediatePropagationStopped) {\n break;\n }\n else {\n binding.handleEvent(extendedEvent);\n }\n }\n }\n hasBindings() {\n return this.unorderedBindings.size > 0;\n }\n get bindings() {\n return Array.from(this.unorderedBindings).sort((left, right) => {\n const leftIndex = left.index, rightIndex = right.index;\n return leftIndex < rightIndex ? -1 : leftIndex > rightIndex ? 1 : 0;\n });\n }\n}\nfunction extendEvent(event) {\n if (\"immediatePropagationStopped\" in event) {\n return event;\n }\n else {\n const { stopImmediatePropagation } = event;\n return Object.assign(event, {\n immediatePropagationStopped: false,\n stopImmediatePropagation() {\n this.immediatePropagationStopped = true;\n stopImmediatePropagation.call(this);\n },\n });\n }\n}\n\nclass Dispatcher {\n constructor(application) {\n this.application = application;\n this.eventListenerMaps = new Map();\n this.started = false;\n }\n start() {\n if (!this.started) {\n this.started = true;\n this.eventListeners.forEach((eventListener) => eventListener.connect());\n }\n }\n stop() {\n if (this.started) {\n this.started = false;\n this.eventListeners.forEach((eventListener) => eventListener.disconnect());\n }\n }\n get eventListeners() {\n return Array.from(this.eventListenerMaps.values()).reduce((listeners, map) => listeners.concat(Array.from(map.values())), []);\n }\n bindingConnected(binding) {\n this.fetchEventListenerForBinding(binding).bindingConnected(binding);\n }\n bindingDisconnected(binding, clearEventListeners = false) {\n this.fetchEventListenerForBinding(binding).bindingDisconnected(binding);\n if (clearEventListeners)\n this.clearEventListenersForBinding(binding);\n }\n handleError(error, message, detail = {}) {\n this.application.handleError(error, `Error ${message}`, detail);\n }\n clearEventListenersForBinding(binding) {\n const eventListener = this.fetchEventListenerForBinding(binding);\n if (!eventListener.hasBindings()) {\n eventListener.disconnect();\n this.removeMappedEventListenerFor(binding);\n }\n }\n removeMappedEventListenerFor(binding) {\n const { eventTarget, eventName, eventOptions } = binding;\n const eventListenerMap = this.fetchEventListenerMapForEventTarget(eventTarget);\n const cacheKey = this.cacheKey(eventName, eventOptions);\n eventListenerMap.delete(cacheKey);\n if (eventListenerMap.size == 0)\n this.eventListenerMaps.delete(eventTarget);\n }\n fetchEventListenerForBinding(binding) {\n const { eventTarget, eventName, eventOptions } = binding;\n return this.fetchEventListener(eventTarget, eventName, eventOptions);\n }\n fetchEventListener(eventTarget, eventName, eventOptions) {\n const eventListenerMap = this.fetchEventListenerMapForEventTarget(eventTarget);\n const cacheKey = this.cacheKey(eventName, eventOptions);\n let eventListener = eventListenerMap.get(cacheKey);\n if (!eventListener) {\n eventListener = this.createEventListener(eventTarget, eventName, eventOptions);\n eventListenerMap.set(cacheKey, eventListener);\n }\n return eventListener;\n }\n createEventListener(eventTarget, eventName, eventOptions) {\n const eventListener = new EventListener(eventTarget, eventName, eventOptions);\n if (this.started) {\n eventListener.connect();\n }\n return eventListener;\n }\n fetchEventListenerMapForEventTarget(eventTarget) {\n let eventListenerMap = this.eventListenerMaps.get(eventTarget);\n if (!eventListenerMap) {\n eventListenerMap = new Map();\n this.eventListenerMaps.set(eventTarget, eventListenerMap);\n }\n return eventListenerMap;\n }\n cacheKey(eventName, eventOptions) {\n const parts = [eventName];\n Object.keys(eventOptions)\n .sort()\n .forEach((key) => {\n parts.push(`${eventOptions[key] ? \"\" : \"!\"}${key}`);\n });\n return parts.join(\":\");\n }\n}\n\nconst defaultActionDescriptorFilters = {\n stop({ event, value }) {\n if (value)\n event.stopPropagation();\n return true;\n },\n prevent({ event, value }) {\n if (value)\n event.preventDefault();\n return true;\n },\n self({ event, value, element }) {\n if (value) {\n return element === event.target;\n }\n else {\n return true;\n }\n },\n};\nconst descriptorPattern = /^(?:(?:([^.]+?)\\+)?(.+?)(?:\\.(.+?))?(?:@(window|document))?->)?(.+?)(?:#([^:]+?))(?::(.+))?$/;\nfunction parseActionDescriptorString(descriptorString) {\n const source = descriptorString.trim();\n const matches = source.match(descriptorPattern) || [];\n let eventName = matches[2];\n let keyFilter = matches[3];\n if (keyFilter && ![\"keydown\", \"keyup\", \"keypress\"].includes(eventName)) {\n eventName += `.${keyFilter}`;\n keyFilter = \"\";\n }\n return {\n eventTarget: parseEventTarget(matches[4]),\n eventName,\n eventOptions: matches[7] ? parseEventOptions(matches[7]) : {},\n identifier: matches[5],\n methodName: matches[6],\n keyFilter: matches[1] || keyFilter,\n };\n}\nfunction parseEventTarget(eventTargetName) {\n if (eventTargetName == \"window\") {\n return window;\n }\n else if (eventTargetName == \"document\") {\n return document;\n }\n}\nfunction parseEventOptions(eventOptions) {\n return eventOptions\n .split(\":\")\n .reduce((options, token) => Object.assign(options, { [token.replace(/^!/, \"\")]: !/^!/.test(token) }), {});\n}\nfunction stringifyEventTarget(eventTarget) {\n if (eventTarget == window) {\n return \"window\";\n }\n else if (eventTarget == document) {\n return \"document\";\n }\n}\n\nfunction camelize(value) {\n return value.replace(/(?:[_-])([a-z0-9])/g, (_, char) => char.toUpperCase());\n}\nfunction namespaceCamelize(value) {\n return camelize(value.replace(/--/g, \"-\").replace(/__/g, \"_\"));\n}\nfunction capitalize(value) {\n return value.charAt(0).toUpperCase() + value.slice(1);\n}\nfunction dasherize(value) {\n return value.replace(/([A-Z])/g, (_, char) => `-${char.toLowerCase()}`);\n}\nfunction tokenize(value) {\n return value.match(/[^\\s]+/g) || [];\n}\n\nfunction isSomething(object) {\n return object !== null && object !== undefined;\n}\nfunction hasProperty(object, property) {\n return Object.prototype.hasOwnProperty.call(object, property);\n}\n\nconst allModifiers = [\"meta\", \"ctrl\", \"alt\", \"shift\"];\nclass Action {\n constructor(element, index, descriptor, schema) {\n this.element = element;\n this.index = index;\n this.eventTarget = descriptor.eventTarget || element;\n this.eventName = descriptor.eventName || getDefaultEventNameForElement(element) || error(\"missing event name\");\n this.eventOptions = descriptor.eventOptions || {};\n this.identifier = descriptor.identifier || error(\"missing identifier\");\n this.methodName = descriptor.methodName || error(\"missing method name\");\n this.keyFilter = descriptor.keyFilter || \"\";\n this.schema = schema;\n }\n static forToken(token, schema) {\n return new this(token.element, token.index, parseActionDescriptorString(token.content), schema);\n }\n toString() {\n const eventFilter = this.keyFilter ? `.${this.keyFilter}` : \"\";\n const eventTarget = this.eventTargetName ? `@${this.eventTargetName}` : \"\";\n return `${this.eventName}${eventFilter}${eventTarget}->${this.identifier}#${this.methodName}`;\n }\n shouldIgnoreKeyboardEvent(event) {\n if (!this.keyFilter) {\n return false;\n }\n const filters = this.keyFilter.split(\"+\");\n if (this.keyFilterDissatisfied(event, filters)) {\n return true;\n }\n const standardFilter = filters.filter((key) => !allModifiers.includes(key))[0];\n if (!standardFilter) {\n return false;\n }\n if (!hasProperty(this.keyMappings, standardFilter)) {\n error(`contains unknown key filter: ${this.keyFilter}`);\n }\n return this.keyMappings[standardFilter].toLowerCase() !== event.key.toLowerCase();\n }\n shouldIgnoreMouseEvent(event) {\n if (!this.keyFilter) {\n return false;\n }\n const filters = [this.keyFilter];\n if (this.keyFilterDissatisfied(event, filters)) {\n return true;\n }\n return false;\n }\n get params() {\n const params = {};\n const pattern = new RegExp(`^data-${this.identifier}-(.+)-param$`, \"i\");\n for (const { name, value } of Array.from(this.element.attributes)) {\n const match = name.match(pattern);\n const key = match && match[1];\n if (key) {\n params[camelize(key)] = typecast(value);\n }\n }\n return params;\n }\n get eventTargetName() {\n return stringifyEventTarget(this.eventTarget);\n }\n get keyMappings() {\n return this.schema.keyMappings;\n }\n keyFilterDissatisfied(event, filters) {\n const [meta, ctrl, alt, shift] = allModifiers.map((modifier) => filters.includes(modifier));\n return event.metaKey !== meta || event.ctrlKey !== ctrl || event.altKey !== alt || event.shiftKey !== shift;\n }\n}\nconst defaultEventNames = {\n a: () => \"click\",\n button: () => \"click\",\n form: () => \"submit\",\n details: () => \"toggle\",\n input: (e) => (e.getAttribute(\"type\") == \"submit\" ? \"click\" : \"input\"),\n select: () => \"change\",\n textarea: () => \"input\",\n};\nfunction getDefaultEventNameForElement(element) {\n const tagName = element.tagName.toLowerCase();\n if (tagName in defaultEventNames) {\n return defaultEventNames[tagName](element);\n }\n}\nfunction error(message) {\n throw new Error(message);\n}\nfunction typecast(value) {\n try {\n return JSON.parse(value);\n }\n catch (o_O) {\n return value;\n }\n}\n\nclass Binding {\n constructor(context, action) {\n this.context = context;\n this.action = action;\n }\n get index() {\n return this.action.index;\n }\n get eventTarget() {\n return this.action.eventTarget;\n }\n get eventOptions() {\n return this.action.eventOptions;\n }\n get identifier() {\n return this.context.identifier;\n }\n handleEvent(event) {\n const actionEvent = this.prepareActionEvent(event);\n if (this.willBeInvokedByEvent(event) && this.applyEventModifiers(actionEvent)) {\n this.invokeWithEvent(actionEvent);\n }\n }\n get eventName() {\n return this.action.eventName;\n }\n get method() {\n const method = this.controller[this.methodName];\n if (typeof method == \"function\") {\n return method;\n }\n throw new Error(`Action \"${this.action}\" references undefined method \"${this.methodName}\"`);\n }\n applyEventModifiers(event) {\n const { element } = this.action;\n const { actionDescriptorFilters } = this.context.application;\n const { controller } = this.context;\n let passes = true;\n for (const [name, value] of Object.entries(this.eventOptions)) {\n if (name in actionDescriptorFilters) {\n const filter = actionDescriptorFilters[name];\n passes = passes && filter({ name, value, event, element, controller });\n }\n else {\n continue;\n }\n }\n return passes;\n }\n prepareActionEvent(event) {\n return Object.assign(event, { params: this.action.params });\n }\n invokeWithEvent(event) {\n const { target, currentTarget } = event;\n try {\n this.method.call(this.controller, event);\n this.context.logDebugActivity(this.methodName, { event, target, currentTarget, action: this.methodName });\n }\n catch (error) {\n const { identifier, controller, element, index } = this;\n const detail = { identifier, controller, element, index, event };\n this.context.handleError(error, `invoking action \"${this.action}\"`, detail);\n }\n }\n willBeInvokedByEvent(event) {\n const eventTarget = event.target;\n if (event instanceof KeyboardEvent && this.action.shouldIgnoreKeyboardEvent(event)) {\n return false;\n }\n if (event instanceof MouseEvent && this.action.shouldIgnoreMouseEvent(event)) {\n return false;\n }\n if (this.element === eventTarget) {\n return true;\n }\n else if (eventTarget instanceof Element && this.element.contains(eventTarget)) {\n return this.scope.containsElement(eventTarget);\n }\n else {\n return this.scope.containsElement(this.action.element);\n }\n }\n get controller() {\n return this.context.controller;\n }\n get methodName() {\n return this.action.methodName;\n }\n get element() {\n return this.scope.element;\n }\n get scope() {\n return this.context.scope;\n }\n}\n\nclass ElementObserver {\n constructor(element, delegate) {\n this.mutationObserverInit = { attributes: true, childList: true, subtree: true };\n this.element = element;\n this.started = false;\n this.delegate = delegate;\n this.elements = new Set();\n this.mutationObserver = new MutationObserver((mutations) => this.processMutations(mutations));\n }\n start() {\n if (!this.started) {\n this.started = true;\n this.mutationObserver.observe(this.element, this.mutationObserverInit);\n this.refresh();\n }\n }\n pause(callback) {\n if (this.started) {\n this.mutationObserver.disconnect();\n this.started = false;\n }\n callback();\n if (!this.started) {\n this.mutationObserver.observe(this.element, this.mutationObserverInit);\n this.started = true;\n }\n }\n stop() {\n if (this.started) {\n this.mutationObserver.takeRecords();\n this.mutationObserver.disconnect();\n this.started = false;\n }\n }\n refresh() {\n if (this.started) {\n const matches = new Set(this.matchElementsInTree());\n for (const element of Array.from(this.elements)) {\n if (!matches.has(element)) {\n this.removeElement(element);\n }\n }\n for (const element of Array.from(matches)) {\n this.addElement(element);\n }\n }\n }\n processMutations(mutations) {\n if (this.started) {\n for (const mutation of mutations) {\n this.processMutation(mutation);\n }\n }\n }\n processMutation(mutation) {\n if (mutation.type == \"attributes\") {\n this.processAttributeChange(mutation.target, mutation.attributeName);\n }\n else if (mutation.type == \"childList\") {\n this.processRemovedNodes(mutation.removedNodes);\n this.processAddedNodes(mutation.addedNodes);\n }\n }\n processAttributeChange(element, attributeName) {\n if (this.elements.has(element)) {\n if (this.delegate.elementAttributeChanged && this.matchElement(element)) {\n this.delegate.elementAttributeChanged(element, attributeName);\n }\n else {\n this.removeElement(element);\n }\n }\n else if (this.matchElement(element)) {\n this.addElement(element);\n }\n }\n processRemovedNodes(nodes) {\n for (const node of Array.from(nodes)) {\n const element = this.elementFromNode(node);\n if (element) {\n this.processTree(element, this.removeElement);\n }\n }\n }\n processAddedNodes(nodes) {\n for (const node of Array.from(nodes)) {\n const element = this.elementFromNode(node);\n if (element && this.elementIsActive(element)) {\n this.processTree(element, this.addElement);\n }\n }\n }\n matchElement(element) {\n return this.delegate.matchElement(element);\n }\n matchElementsInTree(tree = this.element) {\n return this.delegate.matchElementsInTree(tree);\n }\n processTree(tree, processor) {\n for (const element of this.matchElementsInTree(tree)) {\n processor.call(this, element);\n }\n }\n elementFromNode(node) {\n if (node.nodeType == Node.ELEMENT_NODE) {\n return node;\n }\n }\n elementIsActive(element) {\n if (element.isConnected != this.element.isConnected) {\n return false;\n }\n else {\n return this.element.contains(element);\n }\n }\n addElement(element) {\n if (!this.elements.has(element)) {\n if (this.elementIsActive(element)) {\n this.elements.add(element);\n if (this.delegate.elementMatched) {\n this.delegate.elementMatched(element);\n }\n }\n }\n }\n removeElement(element) {\n if (this.elements.has(element)) {\n this.elements.delete(element);\n if (this.delegate.elementUnmatched) {\n this.delegate.elementUnmatched(element);\n }\n }\n }\n}\n\nclass AttributeObserver {\n constructor(element, attributeName, delegate) {\n this.attributeName = attributeName;\n this.delegate = delegate;\n this.elementObserver = new ElementObserver(element, this);\n }\n get element() {\n return this.elementObserver.element;\n }\n get selector() {\n return `[${this.attributeName}]`;\n }\n start() {\n this.elementObserver.start();\n }\n pause(callback) {\n this.elementObserver.pause(callback);\n }\n stop() {\n this.elementObserver.stop();\n }\n refresh() {\n this.elementObserver.refresh();\n }\n get started() {\n return this.elementObserver.started;\n }\n matchElement(element) {\n return element.hasAttribute(this.attributeName);\n }\n matchElementsInTree(tree) {\n const match = this.matchElement(tree) ? [tree] : [];\n const matches = Array.from(tree.querySelectorAll(this.selector));\n return match.concat(matches);\n }\n elementMatched(element) {\n if (this.delegate.elementMatchedAttribute) {\n this.delegate.elementMatchedAttribute(element, this.attributeName);\n }\n }\n elementUnmatched(element) {\n if (this.delegate.elementUnmatchedAttribute) {\n this.delegate.elementUnmatchedAttribute(element, this.attributeName);\n }\n }\n elementAttributeChanged(element, attributeName) {\n if (this.delegate.elementAttributeValueChanged && this.attributeName == attributeName) {\n this.delegate.elementAttributeValueChanged(element, attributeName);\n }\n }\n}\n\nfunction add(map, key, value) {\n fetch(map, key).add(value);\n}\nfunction del(map, key, value) {\n fetch(map, key).delete(value);\n prune(map, key);\n}\nfunction fetch(map, key) {\n let values = map.get(key);\n if (!values) {\n values = new Set();\n map.set(key, values);\n }\n return values;\n}\nfunction prune(map, key) {\n const values = map.get(key);\n if (values != null && values.size == 0) {\n map.delete(key);\n }\n}\n\nclass Multimap {\n constructor() {\n this.valuesByKey = new Map();\n }\n get keys() {\n return Array.from(this.valuesByKey.keys());\n }\n get values() {\n const sets = Array.from(this.valuesByKey.values());\n return sets.reduce((values, set) => values.concat(Array.from(set)), []);\n }\n get size() {\n const sets = Array.from(this.valuesByKey.values());\n return sets.reduce((size, set) => size + set.size, 0);\n }\n add(key, value) {\n add(this.valuesByKey, key, value);\n }\n delete(key, value) {\n del(this.valuesByKey, key, value);\n }\n has(key, value) {\n const values = this.valuesByKey.get(key);\n return values != null && values.has(value);\n }\n hasKey(key) {\n return this.valuesByKey.has(key);\n }\n hasValue(value) {\n const sets = Array.from(this.valuesByKey.values());\n return sets.some((set) => set.has(value));\n }\n getValuesForKey(key) {\n const values = this.valuesByKey.get(key);\n return values ? Array.from(values) : [];\n }\n getKeysForValue(value) {\n return Array.from(this.valuesByKey)\n .filter(([_key, values]) => values.has(value))\n .map(([key, _values]) => key);\n }\n}\n\nclass IndexedMultimap extends Multimap {\n constructor() {\n super();\n this.keysByValue = new Map();\n }\n get values() {\n return Array.from(this.keysByValue.keys());\n }\n add(key, value) {\n super.add(key, value);\n add(this.keysByValue, value, key);\n }\n delete(key, value) {\n super.delete(key, value);\n del(this.keysByValue, value, key);\n }\n hasValue(value) {\n return this.keysByValue.has(value);\n }\n getKeysForValue(value) {\n const set = this.keysByValue.get(value);\n return set ? Array.from(set) : [];\n }\n}\n\nclass SelectorObserver {\n constructor(element, selector, delegate, details) {\n this._selector = selector;\n this.details = details;\n this.elementObserver = new ElementObserver(element, this);\n this.delegate = delegate;\n this.matchesByElement = new Multimap();\n }\n get started() {\n return this.elementObserver.started;\n }\n get selector() {\n return this._selector;\n }\n set selector(selector) {\n this._selector = selector;\n this.refresh();\n }\n start() {\n this.elementObserver.start();\n }\n pause(callback) {\n this.elementObserver.pause(callback);\n }\n stop() {\n this.elementObserver.stop();\n }\n refresh() {\n this.elementObserver.refresh();\n }\n get element() {\n return this.elementObserver.element;\n }\n matchElement(element) {\n const { selector } = this;\n if (selector) {\n const matches = element.matches(selector);\n if (this.delegate.selectorMatchElement) {\n return matches && this.delegate.selectorMatchElement(element, this.details);\n }\n return matches;\n }\n else {\n return false;\n }\n }\n matchElementsInTree(tree) {\n const { selector } = this;\n if (selector) {\n const match = this.matchElement(tree) ? [tree] : [];\n const matches = Array.from(tree.querySelectorAll(selector)).filter((match) => this.matchElement(match));\n return match.concat(matches);\n }\n else {\n return [];\n }\n }\n elementMatched(element) {\n const { selector } = this;\n if (selector) {\n this.selectorMatched(element, selector);\n }\n }\n elementUnmatched(element) {\n const selectors = this.matchesByElement.getKeysForValue(element);\n for (const selector of selectors) {\n this.selectorUnmatched(element, selector);\n }\n }\n elementAttributeChanged(element, _attributeName) {\n const { selector } = this;\n if (selector) {\n const matches = this.matchElement(element);\n const matchedBefore = this.matchesByElement.has(selector, element);\n if (matches && !matchedBefore) {\n this.selectorMatched(element, selector);\n }\n else if (!matches && matchedBefore) {\n this.selectorUnmatched(element, selector);\n }\n }\n }\n selectorMatched(element, selector) {\n this.delegate.selectorMatched(element, selector, this.details);\n this.matchesByElement.add(selector, element);\n }\n selectorUnmatched(element, selector) {\n this.delegate.selectorUnmatched(element, selector, this.details);\n this.matchesByElement.delete(selector, element);\n }\n}\n\nclass StringMapObserver {\n constructor(element, delegate) {\n this.element = element;\n this.delegate = delegate;\n this.started = false;\n this.stringMap = new Map();\n this.mutationObserver = new MutationObserver((mutations) => this.processMutations(mutations));\n }\n start() {\n if (!this.started) {\n this.started = true;\n this.mutationObserver.observe(this.element, { attributes: true, attributeOldValue: true });\n this.refresh();\n }\n }\n stop() {\n if (this.started) {\n this.mutationObserver.takeRecords();\n this.mutationObserver.disconnect();\n this.started = false;\n }\n }\n refresh() {\n if (this.started) {\n for (const attributeName of this.knownAttributeNames) {\n this.refreshAttribute(attributeName, null);\n }\n }\n }\n processMutations(mutations) {\n if (this.started) {\n for (const mutation of mutations) {\n this.processMutation(mutation);\n }\n }\n }\n processMutation(mutation) {\n const attributeName = mutation.attributeName;\n if (attributeName) {\n this.refreshAttribute(attributeName, mutation.oldValue);\n }\n }\n refreshAttribute(attributeName, oldValue) {\n const key = this.delegate.getStringMapKeyForAttribute(attributeName);\n if (key != null) {\n if (!this.stringMap.has(attributeName)) {\n this.stringMapKeyAdded(key, attributeName);\n }\n const value = this.element.getAttribute(attributeName);\n if (this.stringMap.get(attributeName) != value) {\n this.stringMapValueChanged(value, key, oldValue);\n }\n if (value == null) {\n const oldValue = this.stringMap.get(attributeName);\n this.stringMap.delete(attributeName);\n if (oldValue)\n this.stringMapKeyRemoved(key, attributeName, oldValue);\n }\n else {\n this.stringMap.set(attributeName, value);\n }\n }\n }\n stringMapKeyAdded(key, attributeName) {\n if (this.delegate.stringMapKeyAdded) {\n this.delegate.stringMapKeyAdded(key, attributeName);\n }\n }\n stringMapValueChanged(value, key, oldValue) {\n if (this.delegate.stringMapValueChanged) {\n this.delegate.stringMapValueChanged(value, key, oldValue);\n }\n }\n stringMapKeyRemoved(key, attributeName, oldValue) {\n if (this.delegate.stringMapKeyRemoved) {\n this.delegate.stringMapKeyRemoved(key, attributeName, oldValue);\n }\n }\n get knownAttributeNames() {\n return Array.from(new Set(this.currentAttributeNames.concat(this.recordedAttributeNames)));\n }\n get currentAttributeNames() {\n return Array.from(this.element.attributes).map((attribute) => attribute.name);\n }\n get recordedAttributeNames() {\n return Array.from(this.stringMap.keys());\n }\n}\n\nclass TokenListObserver {\n constructor(element, attributeName, delegate) {\n this.attributeObserver = new AttributeObserver(element, attributeName, this);\n this.delegate = delegate;\n this.tokensByElement = new Multimap();\n }\n get started() {\n return this.attributeObserver.started;\n }\n start() {\n this.attributeObserver.start();\n }\n pause(callback) {\n this.attributeObserver.pause(callback);\n }\n stop() {\n this.attributeObserver.stop();\n }\n refresh() {\n this.attributeObserver.refresh();\n }\n get element() {\n return this.attributeObserver.element;\n }\n get attributeName() {\n return this.attributeObserver.attributeName;\n }\n elementMatchedAttribute(element) {\n this.tokensMatched(this.readTokensForElement(element));\n }\n elementAttributeValueChanged(element) {\n const [unmatchedTokens, matchedTokens] = this.refreshTokensForElement(element);\n this.tokensUnmatched(unmatchedTokens);\n this.tokensMatched(matchedTokens);\n }\n elementUnmatchedAttribute(element) {\n this.tokensUnmatched(this.tokensByElement.getValuesForKey(element));\n }\n tokensMatched(tokens) {\n tokens.forEach((token) => this.tokenMatched(token));\n }\n tokensUnmatched(tokens) {\n tokens.forEach((token) => this.tokenUnmatched(token));\n }\n tokenMatched(token) {\n this.delegate.tokenMatched(token);\n this.tokensByElement.add(token.element, token);\n }\n tokenUnmatched(token) {\n this.delegate.tokenUnmatched(token);\n this.tokensByElement.delete(token.element, token);\n }\n refreshTokensForElement(element) {\n const previousTokens = this.tokensByElement.getValuesForKey(element);\n const currentTokens = this.readTokensForElement(element);\n const firstDifferingIndex = zip(previousTokens, currentTokens).findIndex(([previousToken, currentToken]) => !tokensAreEqual(previousToken, currentToken));\n if (firstDifferingIndex == -1) {\n return [[], []];\n }\n else {\n return [previousTokens.slice(firstDifferingIndex), currentTokens.slice(firstDifferingIndex)];\n }\n }\n readTokensForElement(element) {\n const attributeName = this.attributeName;\n const tokenString = element.getAttribute(attributeName) || \"\";\n return parseTokenString(tokenString, element, attributeName);\n }\n}\nfunction parseTokenString(tokenString, element, attributeName) {\n return tokenString\n .trim()\n .split(/\\s+/)\n .filter((content) => content.length)\n .map((content, index) => ({ element, attributeName, content, index }));\n}\nfunction zip(left, right) {\n const length = Math.max(left.length, right.length);\n return Array.from({ length }, (_, index) => [left[index], right[index]]);\n}\nfunction tokensAreEqual(left, right) {\n return left && right && left.index == right.index && left.content == right.content;\n}\n\nclass ValueListObserver {\n constructor(element, attributeName, delegate) {\n this.tokenListObserver = new TokenListObserver(element, attributeName, this);\n this.delegate = delegate;\n this.parseResultsByToken = new WeakMap();\n this.valuesByTokenByElement = new WeakMap();\n }\n get started() {\n return this.tokenListObserver.started;\n }\n start() {\n this.tokenListObserver.start();\n }\n stop() {\n this.tokenListObserver.stop();\n }\n refresh() {\n this.tokenListObserver.refresh();\n }\n get element() {\n return this.tokenListObserver.element;\n }\n get attributeName() {\n return this.tokenListObserver.attributeName;\n }\n tokenMatched(token) {\n const { element } = token;\n const { value } = this.fetchParseResultForToken(token);\n if (value) {\n this.fetchValuesByTokenForElement(element).set(token, value);\n this.delegate.elementMatchedValue(element, value);\n }\n }\n tokenUnmatched(token) {\n const { element } = token;\n const { value } = this.fetchParseResultForToken(token);\n if (value) {\n this.fetchValuesByTokenForElement(element).delete(token);\n this.delegate.elementUnmatchedValue(element, value);\n }\n }\n fetchParseResultForToken(token) {\n let parseResult = this.parseResultsByToken.get(token);\n if (!parseResult) {\n parseResult = this.parseToken(token);\n this.parseResultsByToken.set(token, parseResult);\n }\n return parseResult;\n }\n fetchValuesByTokenForElement(element) {\n let valuesByToken = this.valuesByTokenByElement.get(element);\n if (!valuesByToken) {\n valuesByToken = new Map();\n this.valuesByTokenByElement.set(element, valuesByToken);\n }\n return valuesByToken;\n }\n parseToken(token) {\n try {\n const value = this.delegate.parseValueForToken(token);\n return { value };\n }\n catch (error) {\n return { error };\n }\n }\n}\n\nclass BindingObserver {\n constructor(context, delegate) {\n this.context = context;\n this.delegate = delegate;\n this.bindingsByAction = new Map();\n }\n start() {\n if (!this.valueListObserver) {\n this.valueListObserver = new ValueListObserver(this.element, this.actionAttribute, this);\n this.valueListObserver.start();\n }\n }\n stop() {\n if (this.valueListObserver) {\n this.valueListObserver.stop();\n delete this.valueListObserver;\n this.disconnectAllActions();\n }\n }\n get element() {\n return this.context.element;\n }\n get identifier() {\n return this.context.identifier;\n }\n get actionAttribute() {\n return this.schema.actionAttribute;\n }\n get schema() {\n return this.context.schema;\n }\n get bindings() {\n return Array.from(this.bindingsByAction.values());\n }\n connectAction(action) {\n const binding = new Binding(this.context, action);\n this.bindingsByAction.set(action, binding);\n this.delegate.bindingConnected(binding);\n }\n disconnectAction(action) {\n const binding = this.bindingsByAction.get(action);\n if (binding) {\n this.bindingsByAction.delete(action);\n this.delegate.bindingDisconnected(binding);\n }\n }\n disconnectAllActions() {\n this.bindings.forEach((binding) => this.delegate.bindingDisconnected(binding, true));\n this.bindingsByAction.clear();\n }\n parseValueForToken(token) {\n const action = Action.forToken(token, this.schema);\n if (action.identifier == this.identifier) {\n return action;\n }\n }\n elementMatchedValue(element, action) {\n this.connectAction(action);\n }\n elementUnmatchedValue(element, action) {\n this.disconnectAction(action);\n }\n}\n\nclass ValueObserver {\n constructor(context, receiver) {\n this.context = context;\n this.receiver = receiver;\n this.stringMapObserver = new StringMapObserver(this.element, this);\n this.valueDescriptorMap = this.controller.valueDescriptorMap;\n }\n start() {\n this.stringMapObserver.start();\n this.invokeChangedCallbacksForDefaultValues();\n }\n stop() {\n this.stringMapObserver.stop();\n }\n get element() {\n return this.context.element;\n }\n get controller() {\n return this.context.controller;\n }\n getStringMapKeyForAttribute(attributeName) {\n if (attributeName in this.valueDescriptorMap) {\n return this.valueDescriptorMap[attributeName].name;\n }\n }\n stringMapKeyAdded(key, attributeName) {\n const descriptor = this.valueDescriptorMap[attributeName];\n if (!this.hasValue(key)) {\n this.invokeChangedCallback(key, descriptor.writer(this.receiver[key]), descriptor.writer(descriptor.defaultValue));\n }\n }\n stringMapValueChanged(value, name, oldValue) {\n const descriptor = this.valueDescriptorNameMap[name];\n if (value === null)\n return;\n if (oldValue === null) {\n oldValue = descriptor.writer(descriptor.defaultValue);\n }\n this.invokeChangedCallback(name, value, oldValue);\n }\n stringMapKeyRemoved(key, attributeName, oldValue) {\n const descriptor = this.valueDescriptorNameMap[key];\n if (this.hasValue(key)) {\n this.invokeChangedCallback(key, descriptor.writer(this.receiver[key]), oldValue);\n }\n else {\n this.invokeChangedCallback(key, descriptor.writer(descriptor.defaultValue), oldValue);\n }\n }\n invokeChangedCallbacksForDefaultValues() {\n for (const { key, name, defaultValue, writer } of this.valueDescriptors) {\n if (defaultValue != undefined && !this.controller.data.has(key)) {\n this.invokeChangedCallback(name, writer(defaultValue), undefined);\n }\n }\n }\n invokeChangedCallback(name, rawValue, rawOldValue) {\n const changedMethodName = `${name}Changed`;\n const changedMethod = this.receiver[changedMethodName];\n if (typeof changedMethod == \"function\") {\n const descriptor = this.valueDescriptorNameMap[name];\n try {\n const value = descriptor.reader(rawValue);\n let oldValue = rawOldValue;\n if (rawOldValue) {\n oldValue = descriptor.reader(rawOldValue);\n }\n changedMethod.call(this.receiver, value, oldValue);\n }\n catch (error) {\n if (error instanceof TypeError) {\n error.message = `Stimulus Value \"${this.context.identifier}.${descriptor.name}\" - ${error.message}`;\n }\n throw error;\n }\n }\n }\n get valueDescriptors() {\n const { valueDescriptorMap } = this;\n return Object.keys(valueDescriptorMap).map((key) => valueDescriptorMap[key]);\n }\n get valueDescriptorNameMap() {\n const descriptors = {};\n Object.keys(this.valueDescriptorMap).forEach((key) => {\n const descriptor = this.valueDescriptorMap[key];\n descriptors[descriptor.name] = descriptor;\n });\n return descriptors;\n }\n hasValue(attributeName) {\n const descriptor = this.valueDescriptorNameMap[attributeName];\n const hasMethodName = `has${capitalize(descriptor.name)}`;\n return this.receiver[hasMethodName];\n }\n}\n\nclass TargetObserver {\n constructor(context, delegate) {\n this.context = context;\n this.delegate = delegate;\n this.targetsByName = new Multimap();\n }\n start() {\n if (!this.tokenListObserver) {\n this.tokenListObserver = new TokenListObserver(this.element, this.attributeName, this);\n this.tokenListObserver.start();\n }\n }\n stop() {\n if (this.tokenListObserver) {\n this.disconnectAllTargets();\n this.tokenListObserver.stop();\n delete this.tokenListObserver;\n }\n }\n tokenMatched({ element, content: name }) {\n if (this.scope.containsElement(element)) {\n this.connectTarget(element, name);\n }\n }\n tokenUnmatched({ element, content: name }) {\n this.disconnectTarget(element, name);\n }\n connectTarget(element, name) {\n var _a;\n if (!this.targetsByName.has(name, element)) {\n this.targetsByName.add(name, element);\n (_a = this.tokenListObserver) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.targetConnected(element, name));\n }\n }\n disconnectTarget(element, name) {\n var _a;\n if (this.targetsByName.has(name, element)) {\n this.targetsByName.delete(name, element);\n (_a = this.tokenListObserver) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.targetDisconnected(element, name));\n }\n }\n disconnectAllTargets() {\n for (const name of this.targetsByName.keys) {\n for (const element of this.targetsByName.getValuesForKey(name)) {\n this.disconnectTarget(element, name);\n }\n }\n }\n get attributeName() {\n return `data-${this.context.identifier}-target`;\n }\n get element() {\n return this.context.element;\n }\n get scope() {\n return this.context.scope;\n }\n}\n\nfunction readInheritableStaticArrayValues(constructor, propertyName) {\n const ancestors = getAncestorsForConstructor(constructor);\n return Array.from(ancestors.reduce((values, constructor) => {\n getOwnStaticArrayValues(constructor, propertyName).forEach((name) => values.add(name));\n return values;\n }, new Set()));\n}\nfunction readInheritableStaticObjectPairs(constructor, propertyName) {\n const ancestors = getAncestorsForConstructor(constructor);\n return ancestors.reduce((pairs, constructor) => {\n pairs.push(...getOwnStaticObjectPairs(constructor, propertyName));\n return pairs;\n }, []);\n}\nfunction getAncestorsForConstructor(constructor) {\n const ancestors = [];\n while (constructor) {\n ancestors.push(constructor);\n constructor = Object.getPrototypeOf(constructor);\n }\n return ancestors.reverse();\n}\nfunction getOwnStaticArrayValues(constructor, propertyName) {\n const definition = constructor[propertyName];\n return Array.isArray(definition) ? definition : [];\n}\nfunction getOwnStaticObjectPairs(constructor, propertyName) {\n const definition = constructor[propertyName];\n return definition ? Object.keys(definition).map((key) => [key, definition[key]]) : [];\n}\n\nclass OutletObserver {\n constructor(context, delegate) {\n this.started = false;\n this.context = context;\n this.delegate = delegate;\n this.outletsByName = new Multimap();\n this.outletElementsByName = new Multimap();\n this.selectorObserverMap = new Map();\n this.attributeObserverMap = new Map();\n }\n start() {\n if (!this.started) {\n this.outletDefinitions.forEach((outletName) => {\n this.setupSelectorObserverForOutlet(outletName);\n this.setupAttributeObserverForOutlet(outletName);\n });\n this.started = true;\n this.dependentContexts.forEach((context) => context.refresh());\n }\n }\n refresh() {\n this.selectorObserverMap.forEach((observer) => observer.refresh());\n this.attributeObserverMap.forEach((observer) => observer.refresh());\n }\n stop() {\n if (this.started) {\n this.started = false;\n this.disconnectAllOutlets();\n this.stopSelectorObservers();\n this.stopAttributeObservers();\n }\n }\n stopSelectorObservers() {\n if (this.selectorObserverMap.size > 0) {\n this.selectorObserverMap.forEach((observer) => observer.stop());\n this.selectorObserverMap.clear();\n }\n }\n stopAttributeObservers() {\n if (this.attributeObserverMap.size > 0) {\n this.attributeObserverMap.forEach((observer) => observer.stop());\n this.attributeObserverMap.clear();\n }\n }\n selectorMatched(element, _selector, { outletName }) {\n const outlet = this.getOutlet(element, outletName);\n if (outlet) {\n this.connectOutlet(outlet, element, outletName);\n }\n }\n selectorUnmatched(element, _selector, { outletName }) {\n const outlet = this.getOutletFromMap(element, outletName);\n if (outlet) {\n this.disconnectOutlet(outlet, element, outletName);\n }\n }\n selectorMatchElement(element, { outletName }) {\n const selector = this.selector(outletName);\n const hasOutlet = this.hasOutlet(element, outletName);\n const hasOutletController = element.matches(`[${this.schema.controllerAttribute}~=${outletName}]`);\n if (selector) {\n return hasOutlet && hasOutletController && element.matches(selector);\n }\n else {\n return false;\n }\n }\n elementMatchedAttribute(_element, attributeName) {\n const outletName = this.getOutletNameFromOutletAttributeName(attributeName);\n if (outletName) {\n this.updateSelectorObserverForOutlet(outletName);\n }\n }\n elementAttributeValueChanged(_element, attributeName) {\n const outletName = this.getOutletNameFromOutletAttributeName(attributeName);\n if (outletName) {\n this.updateSelectorObserverForOutlet(outletName);\n }\n }\n elementUnmatchedAttribute(_element, attributeName) {\n const outletName = this.getOutletNameFromOutletAttributeName(attributeName);\n if (outletName) {\n this.updateSelectorObserverForOutlet(outletName);\n }\n }\n connectOutlet(outlet, element, outletName) {\n var _a;\n if (!this.outletElementsByName.has(outletName, element)) {\n this.outletsByName.add(outletName, outlet);\n this.outletElementsByName.add(outletName, element);\n (_a = this.selectorObserverMap.get(outletName)) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.outletConnected(outlet, element, outletName));\n }\n }\n disconnectOutlet(outlet, element, outletName) {\n var _a;\n if (this.outletElementsByName.has(outletName, element)) {\n this.outletsByName.delete(outletName, outlet);\n this.outletElementsByName.delete(outletName, element);\n (_a = this.selectorObserverMap\n .get(outletName)) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.outletDisconnected(outlet, element, outletName));\n }\n }\n disconnectAllOutlets() {\n for (const outletName of this.outletElementsByName.keys) {\n for (const element of this.outletElementsByName.getValuesForKey(outletName)) {\n for (const outlet of this.outletsByName.getValuesForKey(outletName)) {\n this.disconnectOutlet(outlet, element, outletName);\n }\n }\n }\n }\n updateSelectorObserverForOutlet(outletName) {\n const observer = this.selectorObserverMap.get(outletName);\n if (observer) {\n observer.selector = this.selector(outletName);\n }\n }\n setupSelectorObserverForOutlet(outletName) {\n const selector = this.selector(outletName);\n const selectorObserver = new SelectorObserver(document.body, selector, this, { outletName });\n this.selectorObserverMap.set(outletName, selectorObserver);\n selectorObserver.start();\n }\n setupAttributeObserverForOutlet(outletName) {\n const attributeName = this.attributeNameForOutletName(outletName);\n const attributeObserver = new AttributeObserver(this.scope.element, attributeName, this);\n this.attributeObserverMap.set(outletName, attributeObserver);\n attributeObserver.start();\n }\n selector(outletName) {\n return this.scope.outlets.getSelectorForOutletName(outletName);\n }\n attributeNameForOutletName(outletName) {\n return this.scope.schema.outletAttributeForScope(this.identifier, outletName);\n }\n getOutletNameFromOutletAttributeName(attributeName) {\n return this.outletDefinitions.find((outletName) => this.attributeNameForOutletName(outletName) === attributeName);\n }\n get outletDependencies() {\n const dependencies = new Multimap();\n this.router.modules.forEach((module) => {\n const constructor = module.definition.controllerConstructor;\n const outlets = readInheritableStaticArrayValues(constructor, \"outlets\");\n outlets.forEach((outlet) => dependencies.add(outlet, module.identifier));\n });\n return dependencies;\n }\n get outletDefinitions() {\n return this.outletDependencies.getKeysForValue(this.identifier);\n }\n get dependentControllerIdentifiers() {\n return this.outletDependencies.getValuesForKey(this.identifier);\n }\n get dependentContexts() {\n const identifiers = this.dependentControllerIdentifiers;\n return this.router.contexts.filter((context) => identifiers.includes(context.identifier));\n }\n hasOutlet(element, outletName) {\n return !!this.getOutlet(element, outletName) || !!this.getOutletFromMap(element, outletName);\n }\n getOutlet(element, outletName) {\n return this.application.getControllerForElementAndIdentifier(element, outletName);\n }\n getOutletFromMap(element, outletName) {\n return this.outletsByName.getValuesForKey(outletName).find((outlet) => outlet.element === element);\n }\n get scope() {\n return this.context.scope;\n }\n get schema() {\n return this.context.schema;\n }\n get identifier() {\n return this.context.identifier;\n }\n get application() {\n return this.context.application;\n }\n get router() {\n return this.application.router;\n }\n}\n\nclass Context {\n constructor(module, scope) {\n this.logDebugActivity = (functionName, detail = {}) => {\n const { identifier, controller, element } = this;\n detail = Object.assign({ identifier, controller, element }, detail);\n this.application.logDebugActivity(this.identifier, functionName, detail);\n };\n this.module = module;\n this.scope = scope;\n this.controller = new module.controllerConstructor(this);\n this.bindingObserver = new BindingObserver(this, this.dispatcher);\n this.valueObserver = new ValueObserver(this, this.controller);\n this.targetObserver = new TargetObserver(this, this);\n this.outletObserver = new OutletObserver(this, this);\n try {\n this.controller.initialize();\n this.logDebugActivity(\"initialize\");\n }\n catch (error) {\n this.handleError(error, \"initializing controller\");\n }\n }\n connect() {\n this.bindingObserver.start();\n this.valueObserver.start();\n this.targetObserver.start();\n this.outletObserver.start();\n try {\n this.controller.connect();\n this.logDebugActivity(\"connect\");\n }\n catch (error) {\n this.handleError(error, \"connecting controller\");\n }\n }\n refresh() {\n this.outletObserver.refresh();\n }\n disconnect() {\n try {\n this.controller.disconnect();\n this.logDebugActivity(\"disconnect\");\n }\n catch (error) {\n this.handleError(error, \"disconnecting controller\");\n }\n this.outletObserver.stop();\n this.targetObserver.stop();\n this.valueObserver.stop();\n this.bindingObserver.stop();\n }\n get application() {\n return this.module.application;\n }\n get identifier() {\n return this.module.identifier;\n }\n get schema() {\n return this.application.schema;\n }\n get dispatcher() {\n return this.application.dispatcher;\n }\n get element() {\n return this.scope.element;\n }\n get parentElement() {\n return this.element.parentElement;\n }\n handleError(error, message, detail = {}) {\n const { identifier, controller, element } = this;\n detail = Object.assign({ identifier, controller, element }, detail);\n this.application.handleError(error, `Error ${message}`, detail);\n }\n targetConnected(element, name) {\n this.invokeControllerMethod(`${name}TargetConnected`, element);\n }\n targetDisconnected(element, name) {\n this.invokeControllerMethod(`${name}TargetDisconnected`, element);\n }\n outletConnected(outlet, element, name) {\n this.invokeControllerMethod(`${namespaceCamelize(name)}OutletConnected`, outlet, element);\n }\n outletDisconnected(outlet, element, name) {\n this.invokeControllerMethod(`${namespaceCamelize(name)}OutletDisconnected`, outlet, element);\n }\n invokeControllerMethod(methodName, ...args) {\n const controller = this.controller;\n if (typeof controller[methodName] == \"function\") {\n controller[methodName](...args);\n }\n }\n}\n\nfunction bless(constructor) {\n return shadow(constructor, getBlessedProperties(constructor));\n}\nfunction shadow(constructor, properties) {\n const shadowConstructor = extend(constructor);\n const shadowProperties = getShadowProperties(constructor.prototype, properties);\n Object.defineProperties(shadowConstructor.prototype, shadowProperties);\n return shadowConstructor;\n}\nfunction getBlessedProperties(constructor) {\n const blessings = readInheritableStaticArrayValues(constructor, \"blessings\");\n return blessings.reduce((blessedProperties, blessing) => {\n const properties = blessing(constructor);\n for (const key in properties) {\n const descriptor = blessedProperties[key] || {};\n blessedProperties[key] = Object.assign(descriptor, properties[key]);\n }\n return blessedProperties;\n }, {});\n}\nfunction getShadowProperties(prototype, properties) {\n return getOwnKeys(properties).reduce((shadowProperties, key) => {\n const descriptor = getShadowedDescriptor(prototype, properties, key);\n if (descriptor) {\n Object.assign(shadowProperties, { [key]: descriptor });\n }\n return shadowProperties;\n }, {});\n}\nfunction getShadowedDescriptor(prototype, properties, key) {\n const shadowingDescriptor = Object.getOwnPropertyDescriptor(prototype, key);\n const shadowedByValue = shadowingDescriptor && \"value\" in shadowingDescriptor;\n if (!shadowedByValue) {\n const descriptor = Object.getOwnPropertyDescriptor(properties, key).value;\n if (shadowingDescriptor) {\n descriptor.get = shadowingDescriptor.get || descriptor.get;\n descriptor.set = shadowingDescriptor.set || descriptor.set;\n }\n return descriptor;\n }\n}\nconst getOwnKeys = (() => {\n if (typeof Object.getOwnPropertySymbols == \"function\") {\n return (object) => [...Object.getOwnPropertyNames(object), ...Object.getOwnPropertySymbols(object)];\n }\n else {\n return Object.getOwnPropertyNames;\n }\n})();\nconst extend = (() => {\n function extendWithReflect(constructor) {\n function extended() {\n return Reflect.construct(constructor, arguments, new.target);\n }\n extended.prototype = Object.create(constructor.prototype, {\n constructor: { value: extended },\n });\n Reflect.setPrototypeOf(extended, constructor);\n return extended;\n }\n function testReflectExtension() {\n const a = function () {\n this.a.call(this);\n };\n const b = extendWithReflect(a);\n b.prototype.a = function () { };\n return new b();\n }\n try {\n testReflectExtension();\n return extendWithReflect;\n }\n catch (error) {\n return (constructor) => class extended extends constructor {\n };\n }\n})();\n\nfunction blessDefinition(definition) {\n return {\n identifier: definition.identifier,\n controllerConstructor: bless(definition.controllerConstructor),\n };\n}\n\nclass Module {\n constructor(application, definition) {\n this.application = application;\n this.definition = blessDefinition(definition);\n this.contextsByScope = new WeakMap();\n this.connectedContexts = new Set();\n }\n get identifier() {\n return this.definition.identifier;\n }\n get controllerConstructor() {\n return this.definition.controllerConstructor;\n }\n get contexts() {\n return Array.from(this.connectedContexts);\n }\n connectContextForScope(scope) {\n const context = this.fetchContextForScope(scope);\n this.connectedContexts.add(context);\n context.connect();\n }\n disconnectContextForScope(scope) {\n const context = this.contextsByScope.get(scope);\n if (context) {\n this.connectedContexts.delete(context);\n context.disconnect();\n }\n }\n fetchContextForScope(scope) {\n let context = this.contextsByScope.get(scope);\n if (!context) {\n context = new Context(this, scope);\n this.contextsByScope.set(scope, context);\n }\n return context;\n }\n}\n\nclass ClassMap {\n constructor(scope) {\n this.scope = scope;\n }\n has(name) {\n return this.data.has(this.getDataKey(name));\n }\n get(name) {\n return this.getAll(name)[0];\n }\n getAll(name) {\n const tokenString = this.data.get(this.getDataKey(name)) || \"\";\n return tokenize(tokenString);\n }\n getAttributeName(name) {\n return this.data.getAttributeNameForKey(this.getDataKey(name));\n }\n getDataKey(name) {\n return `${name}-class`;\n }\n get data() {\n return this.scope.data;\n }\n}\n\nclass DataMap {\n constructor(scope) {\n this.scope = scope;\n }\n get element() {\n return this.scope.element;\n }\n get identifier() {\n return this.scope.identifier;\n }\n get(key) {\n const name = this.getAttributeNameForKey(key);\n return this.element.getAttribute(name);\n }\n set(key, value) {\n const name = this.getAttributeNameForKey(key);\n this.element.setAttribute(name, value);\n return this.get(key);\n }\n has(key) {\n const name = this.getAttributeNameForKey(key);\n return this.element.hasAttribute(name);\n }\n delete(key) {\n if (this.has(key)) {\n const name = this.getAttributeNameForKey(key);\n this.element.removeAttribute(name);\n return true;\n }\n else {\n return false;\n }\n }\n getAttributeNameForKey(key) {\n return `data-${this.identifier}-${dasherize(key)}`;\n }\n}\n\nclass Guide {\n constructor(logger) {\n this.warnedKeysByObject = new WeakMap();\n this.logger = logger;\n }\n warn(object, key, message) {\n let warnedKeys = this.warnedKeysByObject.get(object);\n if (!warnedKeys) {\n warnedKeys = new Set();\n this.warnedKeysByObject.set(object, warnedKeys);\n }\n if (!warnedKeys.has(key)) {\n warnedKeys.add(key);\n this.logger.warn(message, object);\n }\n }\n}\n\nfunction attributeValueContainsToken(attributeName, token) {\n return `[${attributeName}~=\"${token}\"]`;\n}\n\nclass TargetSet {\n constructor(scope) {\n this.scope = scope;\n }\n get element() {\n return this.scope.element;\n }\n get identifier() {\n return this.scope.identifier;\n }\n get schema() {\n return this.scope.schema;\n }\n has(targetName) {\n return this.find(targetName) != null;\n }\n find(...targetNames) {\n return targetNames.reduce((target, targetName) => target || this.findTarget(targetName) || this.findLegacyTarget(targetName), undefined);\n }\n findAll(...targetNames) {\n return targetNames.reduce((targets, targetName) => [\n ...targets,\n ...this.findAllTargets(targetName),\n ...this.findAllLegacyTargets(targetName),\n ], []);\n }\n findTarget(targetName) {\n const selector = this.getSelectorForTargetName(targetName);\n return this.scope.findElement(selector);\n }\n findAllTargets(targetName) {\n const selector = this.getSelectorForTargetName(targetName);\n return this.scope.findAllElements(selector);\n }\n getSelectorForTargetName(targetName) {\n const attributeName = this.schema.targetAttributeForScope(this.identifier);\n return attributeValueContainsToken(attributeName, targetName);\n }\n findLegacyTarget(targetName) {\n const selector = this.getLegacySelectorForTargetName(targetName);\n return this.deprecate(this.scope.findElement(selector), targetName);\n }\n findAllLegacyTargets(targetName) {\n const selector = this.getLegacySelectorForTargetName(targetName);\n return this.scope.findAllElements(selector).map((element) => this.deprecate(element, targetName));\n }\n getLegacySelectorForTargetName(targetName) {\n const targetDescriptor = `${this.identifier}.${targetName}`;\n return attributeValueContainsToken(this.schema.targetAttribute, targetDescriptor);\n }\n deprecate(element, targetName) {\n if (element) {\n const { identifier } = this;\n const attributeName = this.schema.targetAttribute;\n const revisedAttributeName = this.schema.targetAttributeForScope(identifier);\n this.guide.warn(element, `target:${targetName}`, `Please replace ${attributeName}=\"${identifier}.${targetName}\" with ${revisedAttributeName}=\"${targetName}\". ` +\n `The ${attributeName} attribute is deprecated and will be removed in a future version of Stimulus.`);\n }\n return element;\n }\n get guide() {\n return this.scope.guide;\n }\n}\n\nclass OutletSet {\n constructor(scope, controllerElement) {\n this.scope = scope;\n this.controllerElement = controllerElement;\n }\n get element() {\n return this.scope.element;\n }\n get identifier() {\n return this.scope.identifier;\n }\n get schema() {\n return this.scope.schema;\n }\n has(outletName) {\n return this.find(outletName) != null;\n }\n find(...outletNames) {\n return outletNames.reduce((outlet, outletName) => outlet || this.findOutlet(outletName), undefined);\n }\n findAll(...outletNames) {\n return outletNames.reduce((outlets, outletName) => [...outlets, ...this.findAllOutlets(outletName)], []);\n }\n getSelectorForOutletName(outletName) {\n const attributeName = this.schema.outletAttributeForScope(this.identifier, outletName);\n return this.controllerElement.getAttribute(attributeName);\n }\n findOutlet(outletName) {\n const selector = this.getSelectorForOutletName(outletName);\n if (selector)\n return this.findElement(selector, outletName);\n }\n findAllOutlets(outletName) {\n const selector = this.getSelectorForOutletName(outletName);\n return selector ? this.findAllElements(selector, outletName) : [];\n }\n findElement(selector, outletName) {\n const elements = this.scope.queryElements(selector);\n return elements.filter((element) => this.matchesElement(element, selector, outletName))[0];\n }\n findAllElements(selector, outletName) {\n const elements = this.scope.queryElements(selector);\n return elements.filter((element) => this.matchesElement(element, selector, outletName));\n }\n matchesElement(element, selector, outletName) {\n const controllerAttribute = element.getAttribute(this.scope.schema.controllerAttribute) || \"\";\n return element.matches(selector) && controllerAttribute.split(\" \").includes(outletName);\n }\n}\n\nclass Scope {\n constructor(schema, element, identifier, logger) {\n this.targets = new TargetSet(this);\n this.classes = new ClassMap(this);\n this.data = new DataMap(this);\n this.containsElement = (element) => {\n return element.closest(this.controllerSelector) === this.element;\n };\n this.schema = schema;\n this.element = element;\n this.identifier = identifier;\n this.guide = new Guide(logger);\n this.outlets = new OutletSet(this.documentScope, element);\n }\n findElement(selector) {\n return this.element.matches(selector) ? this.element : this.queryElements(selector).find(this.containsElement);\n }\n findAllElements(selector) {\n return [\n ...(this.element.matches(selector) ? [this.element] : []),\n ...this.queryElements(selector).filter(this.containsElement),\n ];\n }\n queryElements(selector) {\n return Array.from(this.element.querySelectorAll(selector));\n }\n get controllerSelector() {\n return attributeValueContainsToken(this.schema.controllerAttribute, this.identifier);\n }\n get isDocumentScope() {\n return this.element === document.documentElement;\n }\n get documentScope() {\n return this.isDocumentScope\n ? this\n : new Scope(this.schema, document.documentElement, this.identifier, this.guide.logger);\n }\n}\n\nclass ScopeObserver {\n constructor(element, schema, delegate) {\n this.element = element;\n this.schema = schema;\n this.delegate = delegate;\n this.valueListObserver = new ValueListObserver(this.element, this.controllerAttribute, this);\n this.scopesByIdentifierByElement = new WeakMap();\n this.scopeReferenceCounts = new WeakMap();\n }\n start() {\n this.valueListObserver.start();\n }\n stop() {\n this.valueListObserver.stop();\n }\n get controllerAttribute() {\n return this.schema.controllerAttribute;\n }\n parseValueForToken(token) {\n const { element, content: identifier } = token;\n return this.parseValueForElementAndIdentifier(element, identifier);\n }\n parseValueForElementAndIdentifier(element, identifier) {\n const scopesByIdentifier = this.fetchScopesByIdentifierForElement(element);\n let scope = scopesByIdentifier.get(identifier);\n if (!scope) {\n scope = this.delegate.createScopeForElementAndIdentifier(element, identifier);\n scopesByIdentifier.set(identifier, scope);\n }\n return scope;\n }\n elementMatchedValue(element, value) {\n const referenceCount = (this.scopeReferenceCounts.get(value) || 0) + 1;\n this.scopeReferenceCounts.set(value, referenceCount);\n if (referenceCount == 1) {\n this.delegate.scopeConnected(value);\n }\n }\n elementUnmatchedValue(element, value) {\n const referenceCount = this.scopeReferenceCounts.get(value);\n if (referenceCount) {\n this.scopeReferenceCounts.set(value, referenceCount - 1);\n if (referenceCount == 1) {\n this.delegate.scopeDisconnected(value);\n }\n }\n }\n fetchScopesByIdentifierForElement(element) {\n let scopesByIdentifier = this.scopesByIdentifierByElement.get(element);\n if (!scopesByIdentifier) {\n scopesByIdentifier = new Map();\n this.scopesByIdentifierByElement.set(element, scopesByIdentifier);\n }\n return scopesByIdentifier;\n }\n}\n\nclass Router {\n constructor(application) {\n this.application = application;\n this.scopeObserver = new ScopeObserver(this.element, this.schema, this);\n this.scopesByIdentifier = new Multimap();\n this.modulesByIdentifier = new Map();\n }\n get element() {\n return this.application.element;\n }\n get schema() {\n return this.application.schema;\n }\n get logger() {\n return this.application.logger;\n }\n get controllerAttribute() {\n return this.schema.controllerAttribute;\n }\n get modules() {\n return Array.from(this.modulesByIdentifier.values());\n }\n get contexts() {\n return this.modules.reduce((contexts, module) => contexts.concat(module.contexts), []);\n }\n start() {\n this.scopeObserver.start();\n }\n stop() {\n this.scopeObserver.stop();\n }\n loadDefinition(definition) {\n this.unloadIdentifier(definition.identifier);\n const module = new Module(this.application, definition);\n this.connectModule(module);\n const afterLoad = definition.controllerConstructor.afterLoad;\n if (afterLoad) {\n afterLoad.call(definition.controllerConstructor, definition.identifier, this.application);\n }\n }\n unloadIdentifier(identifier) {\n const module = this.modulesByIdentifier.get(identifier);\n if (module) {\n this.disconnectModule(module);\n }\n }\n getContextForElementAndIdentifier(element, identifier) {\n const module = this.modulesByIdentifier.get(identifier);\n if (module) {\n return module.contexts.find((context) => context.element == element);\n }\n }\n proposeToConnectScopeForElementAndIdentifier(element, identifier) {\n const scope = this.scopeObserver.parseValueForElementAndIdentifier(element, identifier);\n if (scope) {\n this.scopeObserver.elementMatchedValue(scope.element, scope);\n }\n else {\n console.error(`Couldn't find or create scope for identifier: \"${identifier}\" and element:`, element);\n }\n }\n handleError(error, message, detail) {\n this.application.handleError(error, message, detail);\n }\n createScopeForElementAndIdentifier(element, identifier) {\n return new Scope(this.schema, element, identifier, this.logger);\n }\n scopeConnected(scope) {\n this.scopesByIdentifier.add(scope.identifier, scope);\n const module = this.modulesByIdentifier.get(scope.identifier);\n if (module) {\n module.connectContextForScope(scope);\n }\n }\n scopeDisconnected(scope) {\n this.scopesByIdentifier.delete(scope.identifier, scope);\n const module = this.modulesByIdentifier.get(scope.identifier);\n if (module) {\n module.disconnectContextForScope(scope);\n }\n }\n connectModule(module) {\n this.modulesByIdentifier.set(module.identifier, module);\n const scopes = this.scopesByIdentifier.getValuesForKey(module.identifier);\n scopes.forEach((scope) => module.connectContextForScope(scope));\n }\n disconnectModule(module) {\n this.modulesByIdentifier.delete(module.identifier);\n const scopes = this.scopesByIdentifier.getValuesForKey(module.identifier);\n scopes.forEach((scope) => module.disconnectContextForScope(scope));\n }\n}\n\nconst defaultSchema = {\n controllerAttribute: \"data-controller\",\n actionAttribute: \"data-action\",\n targetAttribute: \"data-target\",\n targetAttributeForScope: (identifier) => `data-${identifier}-target`,\n outletAttributeForScope: (identifier, outlet) => `data-${identifier}-${outlet}-outlet`,\n keyMappings: Object.assign(Object.assign({ enter: \"Enter\", tab: \"Tab\", esc: \"Escape\", space: \" \", up: \"ArrowUp\", down: \"ArrowDown\", left: \"ArrowLeft\", right: \"ArrowRight\", home: \"Home\", end: \"End\", page_up: \"PageUp\", page_down: \"PageDown\" }, objectFromEntries(\"abcdefghijklmnopqrstuvwxyz\".split(\"\").map((c) => [c, c]))), objectFromEntries(\"0123456789\".split(\"\").map((n) => [n, n]))),\n};\nfunction objectFromEntries(array) {\n return array.reduce((memo, [k, v]) => (Object.assign(Object.assign({}, memo), { [k]: v })), {});\n}\n\nclass Application {\n constructor(element = document.documentElement, schema = defaultSchema) {\n this.logger = console;\n this.debug = false;\n this.logDebugActivity = (identifier, functionName, detail = {}) => {\n if (this.debug) {\n this.logFormattedMessage(identifier, functionName, detail);\n }\n };\n this.element = element;\n this.schema = schema;\n this.dispatcher = new Dispatcher(this);\n this.router = new Router(this);\n this.actionDescriptorFilters = Object.assign({}, defaultActionDescriptorFilters);\n }\n static start(element, schema) {\n const application = new this(element, schema);\n application.start();\n return application;\n }\n async start() {\n await domReady();\n this.logDebugActivity(\"application\", \"starting\");\n this.dispatcher.start();\n this.router.start();\n this.logDebugActivity(\"application\", \"start\");\n }\n stop() {\n this.logDebugActivity(\"application\", \"stopping\");\n this.dispatcher.stop();\n this.router.stop();\n this.logDebugActivity(\"application\", \"stop\");\n }\n register(identifier, controllerConstructor) {\n this.load({ identifier, controllerConstructor });\n }\n registerActionOption(name, filter) {\n this.actionDescriptorFilters[name] = filter;\n }\n load(head, ...rest) {\n const definitions = Array.isArray(head) ? head : [head, ...rest];\n definitions.forEach((definition) => {\n if (definition.controllerConstructor.shouldLoad) {\n this.router.loadDefinition(definition);\n }\n });\n }\n unload(head, ...rest) {\n const identifiers = Array.isArray(head) ? head : [head, ...rest];\n identifiers.forEach((identifier) => this.router.unloadIdentifier(identifier));\n }\n get controllers() {\n return this.router.contexts.map((context) => context.controller);\n }\n getControllerForElementAndIdentifier(element, identifier) {\n const context = this.router.getContextForElementAndIdentifier(element, identifier);\n return context ? context.controller : null;\n }\n handleError(error, message, detail) {\n var _a;\n this.logger.error(`%s\\n\\n%o\\n\\n%o`, message, error, detail);\n (_a = window.onerror) === null || _a === void 0 ? void 0 : _a.call(window, message, \"\", 0, 0, error);\n }\n logFormattedMessage(identifier, functionName, detail = {}) {\n detail = Object.assign({ application: this }, detail);\n this.logger.groupCollapsed(`${identifier} #${functionName}`);\n this.logger.log(\"details:\", Object.assign({}, detail));\n this.logger.groupEnd();\n }\n}\nfunction domReady() {\n return new Promise((resolve) => {\n if (document.readyState == \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", () => resolve());\n }\n else {\n resolve();\n }\n });\n}\n\nfunction ClassPropertiesBlessing(constructor) {\n const classes = readInheritableStaticArrayValues(constructor, \"classes\");\n return classes.reduce((properties, classDefinition) => {\n return Object.assign(properties, propertiesForClassDefinition(classDefinition));\n }, {});\n}\nfunction propertiesForClassDefinition(key) {\n return {\n [`${key}Class`]: {\n get() {\n const { classes } = this;\n if (classes.has(key)) {\n return classes.get(key);\n }\n else {\n const attribute = classes.getAttributeName(key);\n throw new Error(`Missing attribute \"${attribute}\"`);\n }\n },\n },\n [`${key}Classes`]: {\n get() {\n return this.classes.getAll(key);\n },\n },\n [`has${capitalize(key)}Class`]: {\n get() {\n return this.classes.has(key);\n },\n },\n };\n}\n\nfunction OutletPropertiesBlessing(constructor) {\n const outlets = readInheritableStaticArrayValues(constructor, \"outlets\");\n return outlets.reduce((properties, outletDefinition) => {\n return Object.assign(properties, propertiesForOutletDefinition(outletDefinition));\n }, {});\n}\nfunction getOutletController(controller, element, identifier) {\n return controller.application.getControllerForElementAndIdentifier(element, identifier);\n}\nfunction getControllerAndEnsureConnectedScope(controller, element, outletName) {\n let outletController = getOutletController(controller, element, outletName);\n if (outletController)\n return outletController;\n controller.application.router.proposeToConnectScopeForElementAndIdentifier(element, outletName);\n outletController = getOutletController(controller, element, outletName);\n if (outletController)\n return outletController;\n}\nfunction propertiesForOutletDefinition(name) {\n const camelizedName = namespaceCamelize(name);\n return {\n [`${camelizedName}Outlet`]: {\n get() {\n const outletElement = this.outlets.find(name);\n const selector = this.outlets.getSelectorForOutletName(name);\n if (outletElement) {\n const outletController = getControllerAndEnsureConnectedScope(this, outletElement, name);\n if (outletController)\n return outletController;\n throw new Error(`The provided outlet element is missing an outlet controller \"${name}\" instance for host controller \"${this.identifier}\"`);\n }\n throw new Error(`Missing outlet element \"${name}\" for host controller \"${this.identifier}\". Stimulus couldn't find a matching outlet element using selector \"${selector}\".`);\n },\n },\n [`${camelizedName}Outlets`]: {\n get() {\n const outlets = this.outlets.findAll(name);\n if (outlets.length > 0) {\n return outlets\n .map((outletElement) => {\n const outletController = getControllerAndEnsureConnectedScope(this, outletElement, name);\n if (outletController)\n return outletController;\n console.warn(`The provided outlet element is missing an outlet controller \"${name}\" instance for host controller \"${this.identifier}\"`, outletElement);\n })\n .filter((controller) => controller);\n }\n return [];\n },\n },\n [`${camelizedName}OutletElement`]: {\n get() {\n const outletElement = this.outlets.find(name);\n const selector = this.outlets.getSelectorForOutletName(name);\n if (outletElement) {\n return outletElement;\n }\n else {\n throw new Error(`Missing outlet element \"${name}\" for host controller \"${this.identifier}\". Stimulus couldn't find a matching outlet element using selector \"${selector}\".`);\n }\n },\n },\n [`${camelizedName}OutletElements`]: {\n get() {\n return this.outlets.findAll(name);\n },\n },\n [`has${capitalize(camelizedName)}Outlet`]: {\n get() {\n return this.outlets.has(name);\n },\n },\n };\n}\n\nfunction TargetPropertiesBlessing(constructor) {\n const targets = readInheritableStaticArrayValues(constructor, \"targets\");\n return targets.reduce((properties, targetDefinition) => {\n return Object.assign(properties, propertiesForTargetDefinition(targetDefinition));\n }, {});\n}\nfunction propertiesForTargetDefinition(name) {\n return {\n [`${name}Target`]: {\n get() {\n const target = this.targets.find(name);\n if (target) {\n return target;\n }\n else {\n throw new Error(`Missing target element \"${name}\" for \"${this.identifier}\" controller`);\n }\n },\n },\n [`${name}Targets`]: {\n get() {\n return this.targets.findAll(name);\n },\n },\n [`has${capitalize(name)}Target`]: {\n get() {\n return this.targets.has(name);\n },\n },\n };\n}\n\nfunction ValuePropertiesBlessing(constructor) {\n const valueDefinitionPairs = readInheritableStaticObjectPairs(constructor, \"values\");\n const propertyDescriptorMap = {\n valueDescriptorMap: {\n get() {\n return valueDefinitionPairs.reduce((result, valueDefinitionPair) => {\n const valueDescriptor = parseValueDefinitionPair(valueDefinitionPair, this.identifier);\n const attributeName = this.data.getAttributeNameForKey(valueDescriptor.key);\n return Object.assign(result, { [attributeName]: valueDescriptor });\n }, {});\n },\n },\n };\n return valueDefinitionPairs.reduce((properties, valueDefinitionPair) => {\n return Object.assign(properties, propertiesForValueDefinitionPair(valueDefinitionPair));\n }, propertyDescriptorMap);\n}\nfunction propertiesForValueDefinitionPair(valueDefinitionPair, controller) {\n const definition = parseValueDefinitionPair(valueDefinitionPair, controller);\n const { key, name, reader: read, writer: write } = definition;\n return {\n [name]: {\n get() {\n const value = this.data.get(key);\n if (value !== null) {\n return read(value);\n }\n else {\n return definition.defaultValue;\n }\n },\n set(value) {\n if (value === undefined) {\n this.data.delete(key);\n }\n else {\n this.data.set(key, write(value));\n }\n },\n },\n [`has${capitalize(name)}`]: {\n get() {\n return this.data.has(key) || definition.hasCustomDefaultValue;\n },\n },\n };\n}\nfunction parseValueDefinitionPair([token, typeDefinition], controller) {\n return valueDescriptorForTokenAndTypeDefinition({\n controller,\n token,\n typeDefinition,\n });\n}\nfunction parseValueTypeConstant(constant) {\n switch (constant) {\n case Array:\n return \"array\";\n case Boolean:\n return \"boolean\";\n case Number:\n return \"number\";\n case Object:\n return \"object\";\n case String:\n return \"string\";\n }\n}\nfunction parseValueTypeDefault(defaultValue) {\n switch (typeof defaultValue) {\n case \"boolean\":\n return \"boolean\";\n case \"number\":\n return \"number\";\n case \"string\":\n return \"string\";\n }\n if (Array.isArray(defaultValue))\n return \"array\";\n if (Object.prototype.toString.call(defaultValue) === \"[object Object]\")\n return \"object\";\n}\nfunction parseValueTypeObject(payload) {\n const { controller, token, typeObject } = payload;\n const hasType = isSomething(typeObject.type);\n const hasDefault = isSomething(typeObject.default);\n const fullObject = hasType && hasDefault;\n const onlyType = hasType && !hasDefault;\n const onlyDefault = !hasType && hasDefault;\n const typeFromObject = parseValueTypeConstant(typeObject.type);\n const typeFromDefaultValue = parseValueTypeDefault(payload.typeObject.default);\n if (onlyType)\n return typeFromObject;\n if (onlyDefault)\n return typeFromDefaultValue;\n if (typeFromObject !== typeFromDefaultValue) {\n const propertyPath = controller ? `${controller}.${token}` : token;\n throw new Error(`The specified default value for the Stimulus Value \"${propertyPath}\" must match the defined type \"${typeFromObject}\". The provided default value of \"${typeObject.default}\" is of type \"${typeFromDefaultValue}\".`);\n }\n if (fullObject)\n return typeFromObject;\n}\nfunction parseValueTypeDefinition(payload) {\n const { controller, token, typeDefinition } = payload;\n const typeObject = { controller, token, typeObject: typeDefinition };\n const typeFromObject = parseValueTypeObject(typeObject);\n const typeFromDefaultValue = parseValueTypeDefault(typeDefinition);\n const typeFromConstant = parseValueTypeConstant(typeDefinition);\n const type = typeFromObject || typeFromDefaultValue || typeFromConstant;\n if (type)\n return type;\n const propertyPath = controller ? `${controller}.${typeDefinition}` : token;\n throw new Error(`Unknown value type \"${propertyPath}\" for \"${token}\" value`);\n}\nfunction defaultValueForDefinition(typeDefinition) {\n const constant = parseValueTypeConstant(typeDefinition);\n if (constant)\n return defaultValuesByType[constant];\n const hasDefault = hasProperty(typeDefinition, \"default\");\n const hasType = hasProperty(typeDefinition, \"type\");\n const typeObject = typeDefinition;\n if (hasDefault)\n return typeObject.default;\n if (hasType) {\n const { type } = typeObject;\n const constantFromType = parseValueTypeConstant(type);\n if (constantFromType)\n return defaultValuesByType[constantFromType];\n }\n return typeDefinition;\n}\nfunction valueDescriptorForTokenAndTypeDefinition(payload) {\n const { token, typeDefinition } = payload;\n const key = `${dasherize(token)}-value`;\n const type = parseValueTypeDefinition(payload);\n return {\n type,\n key,\n name: camelize(key),\n get defaultValue() {\n return defaultValueForDefinition(typeDefinition);\n },\n get hasCustomDefaultValue() {\n return parseValueTypeDefault(typeDefinition) !== undefined;\n },\n reader: readers[type],\n writer: writers[type] || writers.default,\n };\n}\nconst defaultValuesByType = {\n get array() {\n return [];\n },\n boolean: false,\n number: 0,\n get object() {\n return {};\n },\n string: \"\",\n};\nconst readers = {\n array(value) {\n const array = JSON.parse(value);\n if (!Array.isArray(array)) {\n throw new TypeError(`expected value of type \"array\" but instead got value \"${value}\" of type \"${parseValueTypeDefault(array)}\"`);\n }\n return array;\n },\n boolean(value) {\n return !(value == \"0\" || String(value).toLowerCase() == \"false\");\n },\n number(value) {\n return Number(value.replace(/_/g, \"\"));\n },\n object(value) {\n const object = JSON.parse(value);\n if (object === null || typeof object != \"object\" || Array.isArray(object)) {\n throw new TypeError(`expected value of type \"object\" but instead got value \"${value}\" of type \"${parseValueTypeDefault(object)}\"`);\n }\n return object;\n },\n string(value) {\n return value;\n },\n};\nconst writers = {\n default: writeString,\n array: writeJSON,\n object: writeJSON,\n};\nfunction writeJSON(value) {\n return JSON.stringify(value);\n}\nfunction writeString(value) {\n return `${value}`;\n}\n\nclass Controller {\n constructor(context) {\n this.context = context;\n }\n static get shouldLoad() {\n return true;\n }\n static afterLoad(_identifier, _application) {\n return;\n }\n get application() {\n return this.context.application;\n }\n get scope() {\n return this.context.scope;\n }\n get element() {\n return this.scope.element;\n }\n get identifier() {\n return this.scope.identifier;\n }\n get targets() {\n return this.scope.targets;\n }\n get outlets() {\n return this.scope.outlets;\n }\n get classes() {\n return this.scope.classes;\n }\n get data() {\n return this.scope.data;\n }\n initialize() {\n }\n connect() {\n }\n disconnect() {\n }\n dispatch(eventName, { target = this.element, detail = {}, prefix = this.identifier, bubbles = true, cancelable = true, } = {}) {\n const type = prefix ? `${prefix}:${eventName}` : eventName;\n const event = new CustomEvent(type, { detail, bubbles, cancelable });\n target.dispatchEvent(event);\n return event;\n }\n}\nController.blessings = [\n ClassPropertiesBlessing,\n TargetPropertiesBlessing,\n ValuePropertiesBlessing,\n OutletPropertiesBlessing,\n];\nController.targets = [];\nController.outlets = [];\nController.values = {};\n\nexport { Application, AttributeObserver, Context, Controller, ElementObserver, IndexedMultimap, Multimap, SelectorObserver, StringMapObserver, TokenListObserver, ValueListObserver, add, defaultSchema, del, fetch, prune };\n","/*\nStrada 1.0.0-beta1\nCopyright © 2023 37signals LLC\n*/\nvar __defProp = Object.defineProperty;\nvar __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;\nvar __publicField = (obj, key, value) => {\n __defNormalProp(obj, typeof key !== \"symbol\" ? key + \"\" : key, value);\n return value;\n};\n\n// src/bridge.js\nvar Bridge = class {\n #adapter;\n #lastMessageId;\n #pendingMessages;\n #pendingCallbacks;\n constructor() {\n this.#adapter = null;\n this.#lastMessageId = 0;\n this.#pendingMessages = [];\n this.#pendingCallbacks = /* @__PURE__ */ new Map();\n }\n start() {\n this.notifyApplicationAfterStart();\n }\n notifyApplicationAfterStart() {\n document.dispatchEvent(new Event(\"web-bridge:ready\"));\n }\n supportsComponent(component) {\n if (this.#adapter) {\n return this.#adapter.supportsComponent(component);\n } else {\n return false;\n }\n }\n send({ component, event, data, callback }) {\n if (!this.#adapter) {\n this.#savePendingMessage({ component, event, data, callback });\n return null;\n }\n if (!this.supportsComponent(component))\n return null;\n const id = this.generateMessageId();\n const message = { id, component, event, data: data || {} };\n this.#adapter.receive(message);\n if (callback) {\n this.#pendingCallbacks.set(id, callback);\n }\n return id;\n }\n receive(message) {\n this.executeCallbackFor(message);\n }\n executeCallbackFor(message) {\n const callback = this.#pendingCallbacks.get(message.id);\n if (callback) {\n callback(message);\n }\n }\n removeCallbackFor(messageId) {\n if (this.#pendingCallbacks.has(messageId)) {\n this.#pendingCallbacks.delete(messageId);\n }\n }\n removePendingMessagesFor(component) {\n this.#pendingMessages = this.#pendingMessages.filter((message) => message.component != component);\n }\n generateMessageId() {\n const id = ++this.#lastMessageId;\n return id.toString();\n }\n setAdapter(adapter) {\n this.#adapter = adapter;\n document.documentElement.dataset.bridgePlatform = this.#adapter.platform;\n this.adapterDidUpdateSupportedComponents();\n this.#sendPendingMessages();\n }\n adapterDidUpdateSupportedComponents() {\n if (this.#adapter) {\n document.documentElement.dataset.bridgeComponents = this.#adapter.supportedComponents.join(\" \");\n }\n }\n #savePendingMessage(message) {\n this.#pendingMessages.push(message);\n }\n #sendPendingMessages() {\n this.#pendingMessages.forEach((message) => this.send(message));\n this.#pendingMessages = [];\n }\n};\n\n// src/bridge_component.js\nimport { Controller } from \"@hotwired/stimulus\";\n\n// src/bridge_element.js\nvar BridgeElement = class {\n constructor(element) {\n this.element = element;\n }\n get title() {\n return (this.bridgeAttribute(\"title\") || this.attribute(\"aria-label\") || this.element.textContent || this.element.value).trim();\n }\n get enabled() {\n return !this.disabled;\n }\n get disabled() {\n const disabled = this.bridgeAttribute(\"disabled\");\n return disabled === \"true\" || disabled === this.platform;\n }\n enableForComponent(component) {\n if (component.enabled) {\n this.removeBridgeAttribute(\"disabled\");\n }\n }\n hasClass(className) {\n return this.element.classList.contains(className);\n }\n attribute(name) {\n return this.element.getAttribute(name);\n }\n bridgeAttribute(name) {\n return this.attribute(`data-bridge-${name}`);\n }\n setBridgeAttribute(name, value) {\n this.element.setAttribute(`data-bridge-${name}`, value);\n }\n removeBridgeAttribute(name) {\n this.element.removeAttribute(`data-bridge-${name}`);\n }\n click() {\n if (this.platform == \"android\") {\n this.element.removeAttribute(\"target\");\n }\n this.element.click();\n }\n get platform() {\n return document.documentElement.dataset.bridgePlatform;\n }\n};\n\n// src/helpers/user_agent.js\nvar { userAgent } = window.navigator;\nvar isStradaNativeApp = /bridge-components: \\[.+\\]/.test(userAgent);\n\n// src/bridge_component.js\nvar BridgeComponent = class extends Controller {\n static get shouldLoad() {\n return isStradaNativeApp;\n }\n pendingMessageCallbacks = [];\n initialize() {\n this.pendingMessageCallbacks = [];\n }\n connect() {\n }\n disconnect() {\n this.removePendingCallbacks();\n this.removePendingMessages();\n }\n get component() {\n return this.constructor.component;\n }\n get platformOptingOut() {\n const { bridgePlatform } = document.documentElement.dataset;\n return this.identifier == this.element.getAttribute(`data-controller-optout-${bridgePlatform}`);\n }\n get enabled() {\n return !this.platformOptingOut && this.bridge.supportsComponent(this.component);\n }\n send(event, data = {}, callback) {\n data.metadata = {\n url: window.location.href\n };\n const message = { component: this.component, event, data, callback };\n const messageId = this.bridge.send(message);\n if (callback) {\n this.pendingMessageCallbacks.push(messageId);\n }\n }\n removePendingCallbacks() {\n this.pendingMessageCallbacks.forEach((messageId) => this.bridge.removeCallbackFor(messageId));\n }\n removePendingMessages() {\n this.bridge.removePendingMessagesFor(this.component);\n }\n get bridgeElement() {\n return new BridgeElement(this.element);\n }\n get bridge() {\n return window.Strada.web;\n }\n};\n__publicField(BridgeComponent, \"component\", \"\");\n\n// src/index.js\nif (!window.Strada) {\n const webBridge = new Bridge();\n window.Strada = { web: webBridge };\n webBridge.start();\n}\nexport {\n BridgeComponent,\n BridgeElement\n};\n","import { BridgeComponent, BridgeElement } from \"@hotwired/strada\";\n\nexport default class extends BridgeComponent {\n static component = \"form\";\n static targets = [\"submit\"];\n\n submitTargetConnected(target) {\n const submitButton = new BridgeElement(target);\n const submitTitle = submitButton.title;\n\n this.send(\"connect\", { submitTitle }, () => {\n target.click();\n });\n }\n}\n","// import PlacesAutocomplete from \"stimulus-places-autocomplete\";\n\n// original source can be found here https://github.com/stimulus-components/stimulus-places-autocomplete/blob/master/src/index.ts\n// adjusted to match CRM fields of Address model\n\n// https://www.stimulus-components.com/docs/stimulus-places-autocomplete\n\nimport { Controller } from \"@hotwired/stimulus\";\n\ninterface Address {\n street_number: string;\n route: string;\n locality: string;\n administrative_area_level_2: string;\n administrative_area_level_1: string;\n country: string;\n postal_code: string;\n}\n\nexport default class extends Controller {\n autocomplete: google.maps.places.Autocomplete;\n place: google.maps.places.PlaceResult;\n\n fullAddressTarget: HTMLInputElement;\n fullAddressFormattedTarget: HTMLInputElement;\n streetNumberTarget: HTMLInputElement;\n streetTarget: HTMLInputElement;\n routeTarget: HTMLInputElement;\n cityTarget: HTMLInputElement;\n countyTarget: HTMLInputElement;\n stateTarget: HTMLInputElement;\n countryTarget: HTMLInputElement;\n zipcodeTarget: HTMLInputElement;\n longitudeTarget: HTMLInputElement;\n latitudeTarget: HTMLInputElement;\n\n hasStreetNumberTarget: boolean;\n hasRouteTarget: boolean;\n hasCityTarget: boolean;\n hasCountryTarget: boolean;\n hasCountyTarget: boolean;\n hasPostalCodeTarget: boolean;\n hasStateTarget: boolean;\n hasLongitudeTarget: boolean;\n hasLatitudeTarget: boolean;\n\n countryValue: Array;\n\n static targets = [\n \"fullAddress\",\n \"fullAddressFormatted\",\n \"city\",\n \"streetNumber\",\n \"street\",\n \"route\",\n \"zipcode\",\n \"country\",\n \"county\",\n \"state\",\n \"longitude\",\n \"latitude\",\n ];\n\n static values = {\n country: Array,\n };\n\n initialize(): void {\n this.placeChanged = this.placeChanged.bind(this);\n }\n\n connect(): void {\n if (typeof google !== \"undefined\") {\n this.initAutocomplete();\n }\n }\n\n initAutocomplete(): void {\n this.autocomplete = new google.maps.places.Autocomplete(\n this.fullAddressTarget,\n this.autocompleteOptions\n );\n\n this.autocomplete.addListener(\"place_changed\", this.placeChanged);\n }\n\n placeChanged(): void {\n this.place = this.autocomplete.getPlace();\n const addressComponents: google.maps.GeocoderAddressComponent[] =\n this.place.address_components;\n\n if (addressComponents !== undefined) {\n const formattedAddress = this.formatAddressComponents(\n addressComponents\n ) as Address;\n\n this.setAddressComponents(formattedAddress);\n }\n\n this.fullAddressFormattedTarget.value = this.place.formatted_address;\n\n if (this.place.geometry !== undefined) {\n this.setGeometry(this.place.geometry);\n }\n }\n\n setAddressComponents(address: Address): void {\n this.cityTarget.value = address.locality;\n this.countryTarget.value = address.country;\n this.countyTarget.value = address.administrative_area_level_2;\n this.stateTarget.value = address.administrative_area_level_1;\n this.streetTarget.value = address.street_number + \" \" + address.route;\n this.zipcodeTarget.value = address.postal_code;\n }\n\n setGeometry(geometry: google.maps.places.PlaceGeometry): void {\n if (this.hasLongitudeTarget)\n this.longitudeTarget.value = geometry.location.lng().toString();\n if (this.hasLatitudeTarget)\n this.latitudeTarget.value = geometry.location.lat().toString();\n }\n\n get autocompleteOptions(): google.maps.places.AutocompleteOptions {\n return {\n fields: [\"address_components\", \"geometry\", \"url\", \"formatted_address\"],\n componentRestrictions: {\n country: this.countryValue,\n },\n };\n }\n\n preventSubmit(event: KeyboardEvent): void {\n if (event.code === \"Enter\") {\n event.preventDefault();\n }\n }\n\n private formatAddressComponents(\n addressComponents: google.maps.GeocoderAddressComponent[]\n ): Address {\n const data = {};\n\n addressComponents.forEach(\n (component: google.maps.GeocoderAddressComponent) => {\n const type = component.types[0];\n\n data[type] = component.long_name;\n }\n );\n\n return data as Address;\n }\n}\n","import { Controller } from \"@hotwired/stimulus\";\n\nexport default class extends Controller {\n static targets = [\"toRemove\"];\n\n remove(evt) {\n evt.preventDefault();\n const element = evt.target;\n document.getElementById(element.dataset.toremove).remove();\n }\n}\n","import { Controller } from \"@hotwired/stimulus\";\n\nexport default class extends Controller {\n static targets = [\"datetimePicker\"];\n\n handleSpecificDatetime(ev) {\n if (ev.srcElement.value == \"due_datetime\") {\n this.datetimePickerTarget.classList.remove(\"visually-hidden\");\n } else {\n this.datetimePickerTarget.classList.add(\"visually-hidden\");\n }\n }\n}\n","export class FetchResponse {\n constructor (response) {\n this.response = response\n }\n\n get statusCode () {\n return this.response.status\n }\n\n get redirected () {\n return this.response.redirected\n }\n\n get ok () {\n return this.response.ok\n }\n\n get unauthenticated () {\n return this.statusCode === 401\n }\n\n get unprocessableEntity () {\n return this.statusCode === 422\n }\n\n get authenticationURL () {\n return this.response.headers.get('WWW-Authenticate')\n }\n\n get contentType () {\n const contentType = this.response.headers.get('Content-Type') || ''\n\n return contentType.replace(/;.*$/, '')\n }\n\n get headers () {\n return this.response.headers\n }\n\n get html () {\n if (this.contentType.match(/^(application|text)\\/(html|xhtml\\+xml)$/)) {\n return this.text\n }\n\n return Promise.reject(new Error(`Expected an HTML response but got \"${this.contentType}\" instead`))\n }\n\n get json () {\n if (this.contentType.match(/^application\\/.*json$/)) {\n return this.responseJson || (this.responseJson = this.response.json())\n }\n\n return Promise.reject(new Error(`Expected a JSON response but got \"${this.contentType}\" instead`))\n }\n\n get text () {\n return this.responseText || (this.responseText = this.response.text())\n }\n\n get isTurboStream () {\n return this.contentType.match(/^text\\/vnd\\.turbo-stream\\.html/)\n }\n\n async renderTurboStream () {\n if (this.isTurboStream) {\n if (window.Turbo) {\n await window.Turbo.renderStreamMessage(await this.text)\n } else {\n console.warn('You must set `window.Turbo = Turbo` to automatically process Turbo Stream events with request.js')\n }\n } else {\n return Promise.reject(new Error(`Expected a Turbo Stream response but got \"${this.contentType}\" instead`))\n }\n }\n}\n","export class RequestInterceptor {\n static register (interceptor) {\n this.interceptor = interceptor\n }\n\n static get () {\n return this.interceptor\n }\n\n static reset () {\n this.interceptor = undefined\n }\n}\n","export function getCookie (name) {\n const cookies = document.cookie ? document.cookie.split('; ') : []\n const prefix = `${encodeURIComponent(name)}=`\n const cookie = cookies.find(cookie => cookie.startsWith(prefix))\n\n if (cookie) {\n const value = cookie.split('=').slice(1).join('=')\n\n if (value) {\n return decodeURIComponent(value)\n }\n }\n}\n\nexport function compact (object) {\n const result = {}\n\n for (const key in object) {\n const value = object[key]\n if (value !== undefined) {\n result[key] = value\n }\n }\n\n return result\n}\n\nexport function metaContent (name) {\n const element = document.head.querySelector(`meta[name=\"${name}\"]`)\n return element && element.content\n}\n\nexport function stringEntriesFromFormData (formData) {\n return [...formData].reduce((entries, [name, value]) => {\n return entries.concat(typeof value === 'string' ? [[name, value]] : [])\n }, [])\n}\n\nexport function mergeEntries (searchParams, entries) {\n for (const [name, value] of entries) {\n if (value instanceof window.File) continue\n\n if (searchParams.has(name) && !name.includes('[]')) {\n searchParams.delete(name)\n searchParams.set(name, value)\n } else {\n searchParams.append(name, value)\n }\n }\n}\n","import { FetchResponse } from './fetch_response'\nimport { RequestInterceptor } from './request_interceptor'\nimport { getCookie, compact, metaContent, stringEntriesFromFormData, mergeEntries } from './lib/utils'\n\nexport class FetchRequest {\n constructor (method, url, options = {}) {\n this.method = method\n this.options = options\n this.originalUrl = url.toString()\n }\n\n async perform () {\n try {\n const requestInterceptor = RequestInterceptor.get()\n if (requestInterceptor) {\n await requestInterceptor(this)\n }\n } catch (error) {\n console.error(error)\n }\n\n const response = new FetchResponse(await window.fetch(this.url, this.fetchOptions))\n\n if (response.unauthenticated && response.authenticationURL) {\n return Promise.reject(window.location.href = response.authenticationURL)\n }\n\n const responseStatusIsTurboStreamable = response.ok || response.unprocessableEntity\n\n if (responseStatusIsTurboStreamable && response.isTurboStream) {\n await response.renderTurboStream()\n }\n\n return response\n }\n\n addHeader (key, value) {\n const headers = this.additionalHeaders\n headers[key] = value\n this.options.headers = headers\n }\n\n sameHostname () {\n if (!this.originalUrl.startsWith('http:')) {\n return true\n }\n\n try {\n return new URL(this.originalUrl).hostname === window.location.hostname\n } catch (_) {\n return true\n }\n }\n\n get fetchOptions () {\n return {\n method: this.method.toUpperCase(),\n headers: this.headers,\n body: this.formattedBody,\n signal: this.signal,\n credentials: this.credentials,\n redirect: this.redirect\n }\n }\n\n get headers () {\n const baseHeaders = {\n 'X-Requested-With': 'XMLHttpRequest',\n 'Content-Type': this.contentType,\n Accept: this.accept\n }\n\n if (this.sameHostname()) {\n baseHeaders['X-CSRF-Token'] = this.csrfToken\n }\n\n return compact(\n Object.assign(baseHeaders, this.additionalHeaders)\n )\n }\n\n get csrfToken () {\n return getCookie(metaContent('csrf-param')) || metaContent('csrf-token')\n }\n\n get contentType () {\n if (this.options.contentType) {\n return this.options.contentType\n } else if (this.body == null || this.body instanceof window.FormData) {\n return undefined\n } else if (this.body instanceof window.File) {\n return this.body.type\n }\n\n return 'application/json'\n }\n\n get accept () {\n switch (this.responseKind) {\n case 'html':\n return 'text/html, application/xhtml+xml'\n case 'turbo-stream':\n return 'text/vnd.turbo-stream.html, text/html, application/xhtml+xml'\n case 'json':\n return 'application/json, application/vnd.api+json'\n default:\n return '*/*'\n }\n }\n\n get body () {\n return this.options.body\n }\n\n get query () {\n const originalQuery = (this.originalUrl.split('?')[1] || '').split('#')[0]\n const params = new URLSearchParams(originalQuery)\n\n let requestQuery = this.options.query\n if (requestQuery instanceof window.FormData) {\n requestQuery = stringEntriesFromFormData(requestQuery)\n } else if (requestQuery instanceof window.URLSearchParams) {\n requestQuery = requestQuery.entries()\n } else {\n requestQuery = Object.entries(requestQuery || {})\n }\n\n mergeEntries(params, requestQuery)\n\n const query = params.toString()\n return (query.length > 0 ? `?${query}` : '')\n }\n\n get url () {\n return (this.originalUrl.split('?')[0]).split('#')[0] + this.query\n }\n\n get responseKind () {\n return this.options.responseKind || 'html'\n }\n\n get signal () {\n return this.options.signal\n }\n\n get redirect () {\n return this.options.redirect || 'follow'\n }\n\n get credentials () {\n return this.options.credentials || 'same-origin'\n }\n\n get additionalHeaders () {\n return this.options.headers || {}\n }\n\n get formattedBody () {\n const bodyIsAString = Object.prototype.toString.call(this.body) === '[object String]'\n const contentTypeIsJson = this.headers['Content-Type'] === 'application/json'\n\n if (contentTypeIsJson && !bodyIsAString) {\n return JSON.stringify(this.body)\n }\n\n return this.body\n }\n}\n","import { FetchRequest } from './fetch_request'\n\nasync function get (url, options) {\n const request = new FetchRequest('get', url, options)\n return request.perform()\n}\n\nasync function post (url, options) {\n const request = new FetchRequest('post', url, options)\n return request.perform()\n}\n\nasync function put (url, options) {\n const request = new FetchRequest('put', url, options)\n return request.perform()\n}\n\nasync function patch (url, options) {\n const request = new FetchRequest('patch', url, options)\n return request.perform()\n}\n\nasync function destroy (url, options) {\n const request = new FetchRequest('delete', url, options)\n return request.perform()\n}\n\nexport { get, post, put, patch, destroy }\n","/**\n* Tom Select v2.3.1\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n*/\n\n/**\n * MicroEvent - to make any js object an event emitter\n *\n * - pure javascript - server compatible, browser compatible\n * - dont rely on the browser doms\n * - super simple - you get it immediatly, no mistery, no magic involved\n *\n * @author Jerome Etienne (https://github.com/jeromeetienne)\n */\n\n/**\n * Execute callback for each event in space separated list of event names\n *\n */\nfunction forEvents(events, callback) {\n events.split(/\\s+/).forEach(event => {\n callback(event);\n });\n}\nclass MicroEvent {\n constructor() {\n this._events = void 0;\n this._events = {};\n }\n on(events, fct) {\n forEvents(events, event => {\n const event_array = this._events[event] || [];\n event_array.push(fct);\n this._events[event] = event_array;\n });\n }\n off(events, fct) {\n var n = arguments.length;\n if (n === 0) {\n this._events = {};\n return;\n }\n forEvents(events, event => {\n if (n === 1) {\n delete this._events[event];\n return;\n }\n const event_array = this._events[event];\n if (event_array === undefined) return;\n event_array.splice(event_array.indexOf(fct), 1);\n this._events[event] = event_array;\n });\n }\n trigger(events, ...args) {\n var self = this;\n forEvents(events, event => {\n const event_array = self._events[event];\n if (event_array === undefined) return;\n event_array.forEach(fct => {\n fct.apply(self, args);\n });\n });\n }\n}\n\n/**\n * microplugin.js\n * Copyright (c) 2013 Brian Reavis & contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n * @author Brian Reavis \n */\n\nfunction MicroPlugin(Interface) {\n Interface.plugins = {};\n return class extends Interface {\n constructor(...args) {\n super(...args);\n this.plugins = {\n names: [],\n settings: {},\n requested: {},\n loaded: {}\n };\n }\n /**\n * Registers a plugin.\n *\n * @param {function} fn\n */\n static define(name, fn) {\n Interface.plugins[name] = {\n 'name': name,\n 'fn': fn\n };\n }\n\n /**\n * Initializes the listed plugins (with options).\n * Acceptable formats:\n *\n * List (without options):\n * ['a', 'b', 'c']\n *\n * List (with options):\n * [{'name': 'a', options: {}}, {'name': 'b', options: {}}]\n *\n * Hash (with options):\n * {'a': { ... }, 'b': { ... }, 'c': { ... }}\n *\n * @param {array|object} plugins\n */\n initializePlugins(plugins) {\n var key, name;\n const self = this;\n const queue = [];\n if (Array.isArray(plugins)) {\n plugins.forEach(plugin => {\n if (typeof plugin === 'string') {\n queue.push(plugin);\n } else {\n self.plugins.settings[plugin.name] = plugin.options;\n queue.push(plugin.name);\n }\n });\n } else if (plugins) {\n for (key in plugins) {\n if (plugins.hasOwnProperty(key)) {\n self.plugins.settings[key] = plugins[key];\n queue.push(key);\n }\n }\n }\n while (name = queue.shift()) {\n self.require(name);\n }\n }\n loadPlugin(name) {\n var self = this;\n var plugins = self.plugins;\n var plugin = Interface.plugins[name];\n if (!Interface.plugins.hasOwnProperty(name)) {\n throw new Error('Unable to find \"' + name + '\" plugin');\n }\n plugins.requested[name] = true;\n plugins.loaded[name] = plugin.fn.apply(self, [self.plugins.settings[name] || {}]);\n plugins.names.push(name);\n }\n\n /**\n * Initializes a plugin.\n *\n */\n require(name) {\n var self = this;\n var plugins = self.plugins;\n if (!self.plugins.loaded.hasOwnProperty(name)) {\n if (plugins.requested[name]) {\n throw new Error('Plugin has circular dependency (\"' + name + '\")');\n }\n self.loadPlugin(name);\n }\n return plugins.loaded[name];\n }\n };\n}\n\n/*! @orchidjs/unicode-variants | https://github.com/orchidjs/unicode-variants | Apache License (v2) */\n/**\n * Convert array of strings to a regular expression\n *\tex ['ab','a'] => (?:ab|a)\n * \tex ['a','b'] => [ab]\n * @param {string[]} chars\n * @return {string}\n */\nconst arrayToPattern = chars => {\n chars = chars.filter(Boolean);\n\n if (chars.length < 2) {\n return chars[0] || '';\n }\n\n return maxValueLength(chars) == 1 ? '[' + chars.join('') + ']' : '(?:' + chars.join('|') + ')';\n};\n/**\n * @param {string[]} array\n * @return {string}\n */\n\nconst sequencePattern = array => {\n if (!hasDuplicates(array)) {\n return array.join('');\n }\n\n let pattern = '';\n let prev_char_count = 0;\n\n const prev_pattern = () => {\n if (prev_char_count > 1) {\n pattern += '{' + prev_char_count + '}';\n }\n };\n\n array.forEach((char, i) => {\n if (char === array[i - 1]) {\n prev_char_count++;\n return;\n }\n\n prev_pattern();\n pattern += char;\n prev_char_count = 1;\n });\n prev_pattern();\n return pattern;\n};\n/**\n * Convert array of strings to a regular expression\n *\tex ['ab','a'] => (?:ab|a)\n * \tex ['a','b'] => [ab]\n * @param {Set} chars\n * @return {string}\n */\n\nconst setToPattern = chars => {\n let array = toArray(chars);\n return arrayToPattern(array);\n};\n/**\n *\n * https://stackoverflow.com/questions/7376598/in-javascript-how-do-i-check-if-an-array-has-duplicate-values\n * @param {any[]} array\n */\n\nconst hasDuplicates = array => {\n return new Set(array).size !== array.length;\n};\n/**\n * https://stackoverflow.com/questions/63006601/why-does-u-throw-an-invalid-escape-error\n * @param {string} str\n * @return {string}\n */\n\nconst escape_regex = str => {\n return (str + '').replace(/([\\$\\(\\)\\*\\+\\.\\?\\[\\]\\^\\{\\|\\}\\\\])/gu, '\\\\$1');\n};\n/**\n * Return the max length of array values\n * @param {string[]} array\n *\n */\n\nconst maxValueLength = array => {\n return array.reduce((longest, value) => Math.max(longest, unicodeLength(value)), 0);\n};\n/**\n * @param {string} str\n */\n\nconst unicodeLength = str => {\n return toArray(str).length;\n};\n/**\n * @param {any} p\n * @return {any[]}\n */\n\nconst toArray = p => Array.from(p);\n\n/*! @orchidjs/unicode-variants | https://github.com/orchidjs/unicode-variants | Apache License (v2) */\n/**\n * Get all possible combinations of substrings that add up to the given string\n * https://stackoverflow.com/questions/30169587/find-all-the-combination-of-substrings-that-add-up-to-the-given-string\n * @param {string} input\n * @return {string[][]}\n */\nconst allSubstrings = input => {\n if (input.length === 1) return [[input]];\n /** @type {string[][]} */\n\n let result = [];\n const start = input.substring(1);\n const suba = allSubstrings(start);\n suba.forEach(function (subresult) {\n let tmp = subresult.slice(0);\n tmp[0] = input.charAt(0) + tmp[0];\n result.push(tmp);\n tmp = subresult.slice(0);\n tmp.unshift(input.charAt(0));\n result.push(tmp);\n });\n return result;\n};\n\n/*! @orchidjs/unicode-variants | https://github.com/orchidjs/unicode-variants | Apache License (v2) */\n\n/**\n * @typedef {{[key:string]:string}} TUnicodeMap\n * @typedef {{[key:string]:Set}} TUnicodeSets\n * @typedef {[[number,number]]} TCodePoints\n * @typedef {{folded:string,composed:string,code_point:number}} TCodePointObj\n * @typedef {{start:number,end:number,length:number,substr:string}} TSequencePart\n */\n/** @type {TCodePoints} */\n\nconst code_points = [[0, 65535]];\nconst accent_pat = '[\\u0300-\\u036F\\u{b7}\\u{2be}\\u{2bc}]';\n/** @type {TUnicodeMap} */\n\nlet unicode_map;\n/** @type {RegExp} */\n\nlet multi_char_reg;\nconst max_char_length = 3;\n/** @type {TUnicodeMap} */\n\nconst latin_convert = {};\n/** @type {TUnicodeMap} */\n\nconst latin_condensed = {\n '/': '⁄∕',\n '0': '߀',\n \"a\": \"ⱥɐɑ\",\n \"aa\": \"ꜳ\",\n \"ae\": \"æǽǣ\",\n \"ao\": \"ꜵ\",\n \"au\": \"ꜷ\",\n \"av\": \"ꜹꜻ\",\n \"ay\": \"ꜽ\",\n \"b\": \"ƀɓƃ\",\n \"c\": \"ꜿƈȼↄ\",\n \"d\": \"đɗɖᴅƌꮷԁɦ\",\n \"e\": \"ɛǝᴇɇ\",\n \"f\": \"ꝼƒ\",\n \"g\": \"ǥɠꞡᵹꝿɢ\",\n \"h\": \"ħⱨⱶɥ\",\n \"i\": \"ɨı\",\n \"j\": \"ɉȷ\",\n \"k\": \"ƙⱪꝁꝃꝅꞣ\",\n \"l\": \"łƚɫⱡꝉꝇꞁɭ\",\n \"m\": \"ɱɯϻ\",\n \"n\": \"ꞥƞɲꞑᴎлԉ\",\n \"o\": \"øǿɔɵꝋꝍᴑ\",\n \"oe\": \"œ\",\n \"oi\": \"ƣ\",\n \"oo\": \"ꝏ\",\n \"ou\": \"ȣ\",\n \"p\": \"ƥᵽꝑꝓꝕρ\",\n \"q\": \"ꝗꝙɋ\",\n \"r\": \"ɍɽꝛꞧꞃ\",\n \"s\": \"ßȿꞩꞅʂ\",\n \"t\": \"ŧƭʈⱦꞇ\",\n \"th\": \"þ\",\n \"tz\": \"ꜩ\",\n \"u\": \"ʉ\",\n \"v\": \"ʋꝟʌ\",\n \"vy\": \"ꝡ\",\n \"w\": \"ⱳ\",\n \"y\": \"ƴɏỿ\",\n \"z\": \"ƶȥɀⱬꝣ\",\n \"hv\": \"ƕ\"\n};\n\nfor (let latin in latin_condensed) {\n let unicode = latin_condensed[latin] || '';\n\n for (let i = 0; i < unicode.length; i++) {\n let char = unicode.substring(i, i + 1);\n latin_convert[char] = latin;\n }\n}\n\nconst convert_pat = new RegExp(Object.keys(latin_convert).join('|') + '|' + accent_pat, 'gu');\n/**\n * Initialize the unicode_map from the give code point ranges\n *\n * @param {TCodePoints=} _code_points\n */\n\nconst initialize = _code_points => {\n if (unicode_map !== undefined) return;\n unicode_map = generateMap(_code_points || code_points);\n};\n/**\n * Helper method for normalize a string\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize\n * @param {string} str\n * @param {string} form\n */\n\nconst normalize = (str, form = 'NFKD') => str.normalize(form);\n/**\n * Remove accents without reordering string\n * calling str.normalize('NFKD') on \\u{594}\\u{595}\\u{596} becomes \\u{596}\\u{594}\\u{595}\n * via https://github.com/krisk/Fuse/issues/133#issuecomment-318692703\n * @param {string} str\n * @return {string}\n */\n\nconst asciifold = str => {\n return toArray(str).reduce(\n /**\n * @param {string} result\n * @param {string} char\n */\n (result, char) => {\n return result + _asciifold(char);\n }, '');\n};\n/**\n * @param {string} str\n * @return {string}\n */\n\nconst _asciifold = str => {\n str = normalize(str).toLowerCase().replace(convert_pat, (\n /** @type {string} */\n char) => {\n return latin_convert[char] || '';\n }); //return str;\n\n return normalize(str, 'NFC');\n};\n/**\n * Generate a list of unicode variants from the list of code points\n * @param {TCodePoints} code_points\n * @yield {TCodePointObj}\n */\n\nfunction* generator(code_points) {\n for (const [code_point_min, code_point_max] of code_points) {\n for (let i = code_point_min; i <= code_point_max; i++) {\n let composed = String.fromCharCode(i);\n let folded = asciifold(composed);\n\n if (folded == composed.toLowerCase()) {\n continue;\n } // skip when folded is a string longer than 3 characters long\n // bc the resulting regex patterns will be long\n // eg:\n // folded صلى الله عليه وسلم length 18 code point 65018\n // folded جل جلاله length 8 code point 65019\n\n\n if (folded.length > max_char_length) {\n continue;\n }\n\n if (folded.length == 0) {\n continue;\n }\n\n yield {\n folded: folded,\n composed: composed,\n code_point: i\n };\n }\n }\n}\n/**\n * Generate a unicode map from the list of code points\n * @param {TCodePoints} code_points\n * @return {TUnicodeSets}\n */\n\nconst generateSets = code_points => {\n /** @type {{[key:string]:Set}} */\n const unicode_sets = {};\n /**\n * @param {string} folded\n * @param {string} to_add\n */\n\n const addMatching = (folded, to_add) => {\n /** @type {Set} */\n const folded_set = unicode_sets[folded] || new Set();\n const patt = new RegExp('^' + setToPattern(folded_set) + '$', 'iu');\n\n if (to_add.match(patt)) {\n return;\n }\n\n folded_set.add(escape_regex(to_add));\n unicode_sets[folded] = folded_set;\n };\n\n for (let value of generator(code_points)) {\n addMatching(value.folded, value.folded);\n addMatching(value.folded, value.composed);\n }\n\n return unicode_sets;\n};\n/**\n * Generate a unicode map from the list of code points\n * ae => (?:(?:ae|Æ|Ǽ|Ǣ)|(?:A|Ⓐ|A...)(?:E|ɛ|Ⓔ...))\n *\n * @param {TCodePoints} code_points\n * @return {TUnicodeMap}\n */\n\nconst generateMap = code_points => {\n /** @type {TUnicodeSets} */\n const unicode_sets = generateSets(code_points);\n /** @type {TUnicodeMap} */\n\n const unicode_map = {};\n /** @type {string[]} */\n\n let multi_char = [];\n\n for (let folded in unicode_sets) {\n let set = unicode_sets[folded];\n\n if (set) {\n unicode_map[folded] = setToPattern(set);\n }\n\n if (folded.length > 1) {\n multi_char.push(escape_regex(folded));\n }\n }\n\n multi_char.sort((a, b) => b.length - a.length);\n const multi_char_patt = arrayToPattern(multi_char);\n multi_char_reg = new RegExp('^' + multi_char_patt, 'u');\n return unicode_map;\n};\n/**\n * Map each element of an array from it's folded value to all possible unicode matches\n * @param {string[]} strings\n * @param {number} min_replacement\n * @return {string}\n */\n\nconst mapSequence = (strings, min_replacement = 1) => {\n let chars_replaced = 0;\n strings = strings.map(str => {\n if (unicode_map[str]) {\n chars_replaced += str.length;\n }\n\n return unicode_map[str] || str;\n });\n\n if (chars_replaced >= min_replacement) {\n return sequencePattern(strings);\n }\n\n return '';\n};\n/**\n * Convert a short string and split it into all possible patterns\n * Keep a pattern only if min_replacement is met\n *\n * 'abc'\n * \t\t=> [['abc'],['ab','c'],['a','bc'],['a','b','c']]\n *\t\t=> ['abc-pattern','ab-c-pattern'...]\n *\n *\n * @param {string} str\n * @param {number} min_replacement\n * @return {string}\n */\n\nconst substringsToPattern = (str, min_replacement = 1) => {\n min_replacement = Math.max(min_replacement, str.length - 1);\n return arrayToPattern(allSubstrings(str).map(sub_pat => {\n return mapSequence(sub_pat, min_replacement);\n }));\n};\n/**\n * Convert an array of sequences into a pattern\n * [{start:0,end:3,length:3,substr:'iii'}...] => (?:iii...)\n *\n * @param {Sequence[]} sequences\n * @param {boolean} all\n */\n\nconst sequencesToPattern = (sequences, all = true) => {\n let min_replacement = sequences.length > 1 ? 1 : 0;\n return arrayToPattern(sequences.map(sequence => {\n let seq = [];\n const len = all ? sequence.length() : sequence.length() - 1;\n\n for (let j = 0; j < len; j++) {\n seq.push(substringsToPattern(sequence.substrs[j] || '', min_replacement));\n }\n\n return sequencePattern(seq);\n }));\n};\n/**\n * Return true if the sequence is already in the sequences\n * @param {Sequence} needle_seq\n * @param {Sequence[]} sequences\n */\n\n\nconst inSequences = (needle_seq, sequences) => {\n for (const seq of sequences) {\n if (seq.start != needle_seq.start || seq.end != needle_seq.end) {\n continue;\n }\n\n if (seq.substrs.join('') !== needle_seq.substrs.join('')) {\n continue;\n }\n\n let needle_parts = needle_seq.parts;\n /**\n * @param {TSequencePart} part\n */\n\n const filter = part => {\n for (const needle_part of needle_parts) {\n if (needle_part.start === part.start && needle_part.substr === part.substr) {\n return false;\n }\n\n if (part.length == 1 || needle_part.length == 1) {\n continue;\n } // check for overlapping parts\n // a = ['::=','==']\n // b = ['::','===']\n // a = ['r','sm']\n // b = ['rs','m']\n\n\n if (part.start < needle_part.start && part.end > needle_part.start) {\n return true;\n }\n\n if (needle_part.start < part.start && needle_part.end > part.start) {\n return true;\n }\n }\n\n return false;\n };\n\n let filtered = seq.parts.filter(filter);\n\n if (filtered.length > 0) {\n continue;\n }\n\n return true;\n }\n\n return false;\n};\n\nclass Sequence {\n constructor() {\n /** @type {TSequencePart[]} */\n this.parts = [];\n /** @type {string[]} */\n\n this.substrs = [];\n this.start = 0;\n this.end = 0;\n }\n /**\n * @param {TSequencePart|undefined} part\n */\n\n\n add(part) {\n if (part) {\n this.parts.push(part);\n this.substrs.push(part.substr);\n this.start = Math.min(part.start, this.start);\n this.end = Math.max(part.end, this.end);\n }\n }\n\n last() {\n return this.parts[this.parts.length - 1];\n }\n\n length() {\n return this.parts.length;\n }\n /**\n * @param {number} position\n * @param {TSequencePart} last_piece\n */\n\n\n clone(position, last_piece) {\n let clone = new Sequence();\n let parts = JSON.parse(JSON.stringify(this.parts));\n let last_part = parts.pop();\n\n for (const part of parts) {\n clone.add(part);\n }\n\n let last_substr = last_piece.substr.substring(0, position - last_part.start);\n let clone_last_len = last_substr.length;\n clone.add({\n start: last_part.start,\n end: last_part.start + clone_last_len,\n length: clone_last_len,\n substr: last_substr\n });\n return clone;\n }\n\n}\n/**\n * Expand a regular expression pattern to include unicode variants\n * \teg /a/ becomes /aⓐaẚàáâầấẫẩãāăằắẵẳȧǡäǟảåǻǎȁȃạậặḁąⱥɐɑAⒶAÀÁÂẦẤẪẨÃĀĂẰẮẴẲȦǠÄǞẢÅǺǍȀȂẠẬẶḀĄȺⱯ/\n *\n * Issue:\n * ﺊﺋ [ 'ﺊ = \\\\u{fe8a}', 'ﺋ = \\\\u{fe8b}' ]\n *\tbecomes:\tئئ [ 'ي = \\\\u{64a}', 'ٔ = \\\\u{654}', 'ي = \\\\u{64a}', 'ٔ = \\\\u{654}' ]\n *\n *\tİIJ = IIJ = ⅡJ\n *\n * \t1/2/4\n *\n * @param {string} str\n * @return {string|undefined}\n */\n\n\nconst getPattern = str => {\n initialize();\n str = asciifold(str);\n let pattern = '';\n let sequences = [new Sequence()];\n\n for (let i = 0; i < str.length; i++) {\n let substr = str.substring(i);\n let match = substr.match(multi_char_reg);\n const char = str.substring(i, i + 1);\n const match_str = match ? match[0] : null; // loop through sequences\n // add either the char or multi_match\n\n let overlapping = [];\n let added_types = new Set();\n\n for (const sequence of sequences) {\n const last_piece = sequence.last();\n\n if (!last_piece || last_piece.length == 1 || last_piece.end <= i) {\n // if we have a multi match\n if (match_str) {\n const len = match_str.length;\n sequence.add({\n start: i,\n end: i + len,\n length: len,\n substr: match_str\n });\n added_types.add('1');\n } else {\n sequence.add({\n start: i,\n end: i + 1,\n length: 1,\n substr: char\n });\n added_types.add('2');\n }\n } else if (match_str) {\n let clone = sequence.clone(i, last_piece);\n const len = match_str.length;\n clone.add({\n start: i,\n end: i + len,\n length: len,\n substr: match_str\n });\n overlapping.push(clone);\n } else {\n // don't add char\n // adding would create invalid patterns: 234 => [2,34,4]\n added_types.add('3');\n }\n } // if we have overlapping\n\n\n if (overlapping.length > 0) {\n // ['ii','iii'] before ['i','i','iii']\n overlapping = overlapping.sort((a, b) => {\n return a.length() - b.length();\n });\n\n for (let clone of overlapping) {\n // don't add if we already have an equivalent sequence\n if (inSequences(clone, sequences)) {\n continue;\n }\n\n sequences.push(clone);\n }\n\n continue;\n } // if we haven't done anything unique\n // clean up the patterns\n // helps keep patterns smaller\n // if str = 'r₨㎧aarss', pattern will be 446 instead of 655\n\n\n if (i > 0 && added_types.size == 1 && !added_types.has('3')) {\n pattern += sequencesToPattern(sequences, false);\n let new_seq = new Sequence();\n const old_seq = sequences[0];\n\n if (old_seq) {\n new_seq.add(old_seq.last());\n }\n\n sequences = [new_seq];\n }\n }\n\n pattern += sequencesToPattern(sequences, true);\n return pattern;\n};\n\n/*! sifter.js | https://github.com/orchidjs/sifter.js | Apache License (v2) */\n\n/**\n * A property getter resolving dot-notation\n * @param {Object} obj The root object to fetch property on\n * @param {String} name The optionally dotted property name to fetch\n * @return {Object} The resolved property value\n */\nconst getAttr = (obj, name) => {\n if (!obj) return;\n return obj[name];\n};\n/**\n * A property getter resolving dot-notation\n * @param {Object} obj The root object to fetch property on\n * @param {String} name The optionally dotted property name to fetch\n * @return {Object} The resolved property value\n */\n\nconst getAttrNesting = (obj, name) => {\n if (!obj) return;\n var part,\n names = name.split(\".\");\n\n while ((part = names.shift()) && (obj = obj[part]));\n\n return obj;\n};\n/**\n * Calculates how close of a match the\n * given value is against a search token.\n *\n */\n\nconst scoreValue = (value, token, weight) => {\n var score, pos;\n if (!value) return 0;\n value = value + '';\n if (token.regex == null) return 0;\n pos = value.search(token.regex);\n if (pos === -1) return 0;\n score = token.string.length / value.length;\n if (pos === 0) score += 0.5;\n return score * weight;\n};\n/**\n * Cast object property to an array if it exists and has a value\n *\n */\n\nconst propToArray = (obj, key) => {\n var value = obj[key];\n if (typeof value == 'function') return value;\n\n if (value && !Array.isArray(value)) {\n obj[key] = [value];\n }\n};\n/**\n * Iterates over arrays and hashes.\n *\n * ```\n * iterate(this.items, function(item, id) {\n * // invoked for each item\n * });\n * ```\n *\n */\n\nconst iterate$1 = (object, callback) => {\n if (Array.isArray(object)) {\n object.forEach(callback);\n } else {\n for (var key in object) {\n if (object.hasOwnProperty(key)) {\n callback(object[key], key);\n }\n }\n }\n};\nconst cmp = (a, b) => {\n if (typeof a === 'number' && typeof b === 'number') {\n return a > b ? 1 : a < b ? -1 : 0;\n }\n\n a = asciifold(a + '').toLowerCase();\n b = asciifold(b + '').toLowerCase();\n if (a > b) return 1;\n if (b > a) return -1;\n return 0;\n};\n\n/*! sifter.js | https://github.com/orchidjs/sifter.js | Apache License (v2) */\n\n/**\n * sifter.js\n * Copyright (c) 2013–2020 Brian Reavis & contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n * @author Brian Reavis \n */\n\nclass Sifter {\n // []|{};\n\n /**\n * Textually searches arrays and hashes of objects\n * by property (or multiple properties). Designed\n * specifically for autocomplete.\n *\n */\n constructor(items, settings) {\n this.items = void 0;\n this.settings = void 0;\n this.items = items;\n this.settings = settings || {\n diacritics: true\n };\n }\n\n /**\n * Splits a search string into an array of individual\n * regexps to be used to match results.\n *\n */\n tokenize(query, respect_word_boundaries, weights) {\n if (!query || !query.length) return [];\n const tokens = [];\n const words = query.split(/\\s+/);\n var field_regex;\n\n if (weights) {\n field_regex = new RegExp('^(' + Object.keys(weights).map(escape_regex).join('|') + ')\\:(.*)$');\n }\n\n words.forEach(word => {\n let field_match;\n let field = null;\n let regex = null; // look for \"field:query\" tokens\n\n if (field_regex && (field_match = word.match(field_regex))) {\n field = field_match[1];\n word = field_match[2];\n }\n\n if (word.length > 0) {\n if (this.settings.diacritics) {\n regex = getPattern(word) || null;\n } else {\n regex = escape_regex(word);\n }\n\n if (regex && respect_word_boundaries) regex = \"\\\\b\" + regex;\n }\n\n tokens.push({\n string: word,\n regex: regex ? new RegExp(regex, 'iu') : null,\n field: field\n });\n });\n return tokens;\n }\n\n /**\n * Returns a function to be used to score individual results.\n *\n * Good matches will have a higher score than poor matches.\n * If an item is not a match, 0 will be returned by the function.\n *\n * @returns {T.ScoreFn}\n */\n getScoreFunction(query, options) {\n var search = this.prepareSearch(query, options);\n return this._getScoreFunction(search);\n }\n /**\n * @returns {T.ScoreFn}\n *\n */\n\n\n _getScoreFunction(search) {\n const tokens = search.tokens,\n token_count = tokens.length;\n\n if (!token_count) {\n return function () {\n return 0;\n };\n }\n\n const fields = search.options.fields,\n weights = search.weights,\n field_count = fields.length,\n getAttrFn = search.getAttrFn;\n\n if (!field_count) {\n return function () {\n return 1;\n };\n }\n /**\n * Calculates the score of an object\n * against the search query.\n *\n */\n\n\n const scoreObject = function () {\n if (field_count === 1) {\n return function (token, data) {\n const field = fields[0].field;\n return scoreValue(getAttrFn(data, field), token, weights[field] || 1);\n };\n }\n\n return function (token, data) {\n var sum = 0; // is the token specific to a field?\n\n if (token.field) {\n const value = getAttrFn(data, token.field);\n\n if (!token.regex && value) {\n sum += 1 / field_count;\n } else {\n sum += scoreValue(value, token, 1);\n }\n } else {\n iterate$1(weights, (weight, field) => {\n sum += scoreValue(getAttrFn(data, field), token, weight);\n });\n }\n\n return sum / field_count;\n };\n }();\n\n if (token_count === 1) {\n return function (data) {\n return scoreObject(tokens[0], data);\n };\n }\n\n if (search.options.conjunction === 'and') {\n return function (data) {\n var score,\n sum = 0;\n\n for (let token of tokens) {\n score = scoreObject(token, data);\n if (score <= 0) return 0;\n sum += score;\n }\n\n return sum / token_count;\n };\n } else {\n return function (data) {\n var sum = 0;\n iterate$1(tokens, token => {\n sum += scoreObject(token, data);\n });\n return sum / token_count;\n };\n }\n }\n\n /**\n * Returns a function that can be used to compare two\n * results, for sorting purposes. If no sorting should\n * be performed, `null` will be returned.\n *\n * @return function(a,b)\n */\n getSortFunction(query, options) {\n var search = this.prepareSearch(query, options);\n return this._getSortFunction(search);\n }\n\n _getSortFunction(search) {\n var implicit_score,\n sort_flds = [];\n const self = this,\n options = search.options,\n sort = !search.query && options.sort_empty ? options.sort_empty : options.sort;\n\n if (typeof sort == 'function') {\n return sort.bind(this);\n }\n /**\n * Fetches the specified sort field value\n * from a search result item.\n *\n */\n\n\n const get_field = function get_field(name, result) {\n if (name === '$score') return result.score;\n return search.getAttrFn(self.items[result.id], name);\n }; // parse options\n\n\n if (sort) {\n for (let s of sort) {\n if (search.query || s.field !== '$score') {\n sort_flds.push(s);\n }\n }\n } // the \"$score\" field is implied to be the primary\n // sort field, unless it's manually specified\n\n\n if (search.query) {\n implicit_score = true;\n\n for (let fld of sort_flds) {\n if (fld.field === '$score') {\n implicit_score = false;\n break;\n }\n }\n\n if (implicit_score) {\n sort_flds.unshift({\n field: '$score',\n direction: 'desc'\n });\n } // without a search.query, all items will have the same score\n\n } else {\n sort_flds = sort_flds.filter(fld => fld.field !== '$score');\n } // build function\n\n\n const sort_flds_count = sort_flds.length;\n\n if (!sort_flds_count) {\n return null;\n }\n\n return function (a, b) {\n var result, field;\n\n for (let sort_fld of sort_flds) {\n field = sort_fld.field;\n let multiplier = sort_fld.direction === 'desc' ? -1 : 1;\n result = multiplier * cmp(get_field(field, a), get_field(field, b));\n if (result) return result;\n }\n\n return 0;\n };\n }\n\n /**\n * Parses a search query and returns an object\n * with tokens and fields ready to be populated\n * with results.\n *\n */\n prepareSearch(query, optsUser) {\n const weights = {};\n var options = Object.assign({}, optsUser);\n propToArray(options, 'sort');\n propToArray(options, 'sort_empty'); // convert fields to new format\n\n if (options.fields) {\n propToArray(options, 'fields');\n const fields = [];\n options.fields.forEach(field => {\n if (typeof field == 'string') {\n field = {\n field: field,\n weight: 1\n };\n }\n\n fields.push(field);\n weights[field.field] = 'weight' in field ? field.weight : 1;\n });\n options.fields = fields;\n }\n\n return {\n options: options,\n query: query.toLowerCase().trim(),\n tokens: this.tokenize(query, options.respect_word_boundaries, weights),\n total: 0,\n items: [],\n weights: weights,\n getAttrFn: options.nesting ? getAttrNesting : getAttr\n };\n }\n\n /**\n * Searches through all items and returns a sorted array of matches.\n *\n */\n search(query, options) {\n var self = this,\n score,\n search;\n search = this.prepareSearch(query, options);\n options = search.options;\n query = search.query; // generate result scoring function\n\n const fn_score = options.score || self._getScoreFunction(search); // perform search and sort\n\n\n if (query.length) {\n iterate$1(self.items, (item, id) => {\n score = fn_score(item);\n\n if (options.filter === false || score > 0) {\n search.items.push({\n 'score': score,\n 'id': id\n });\n }\n });\n } else {\n iterate$1(self.items, (_, id) => {\n search.items.push({\n 'score': 1,\n 'id': id\n });\n });\n }\n\n const fn_sort = self._getSortFunction(search);\n\n if (fn_sort) search.items.sort(fn_sort); // apply limits\n\n search.total = search.items.length;\n\n if (typeof options.limit === 'number') {\n search.items = search.items.slice(0, options.limit);\n }\n\n return search;\n }\n\n}\n\n/**\n * Iterates over arrays and hashes.\n *\n * ```\n * iterate(this.items, function(item, id) {\n * // invoked for each item\n * });\n * ```\n *\n */\nconst iterate = (object, callback) => {\n if (Array.isArray(object)) {\n object.forEach(callback);\n } else {\n for (var key in object) {\n if (object.hasOwnProperty(key)) {\n callback(object[key], key);\n }\n }\n }\n};\n\n/**\n * Return a dom element from either a dom query string, jQuery object, a dom element or html string\n * https://stackoverflow.com/questions/494143/creating-a-new-dom-element-from-an-html-string-using-built-in-dom-methods-or-pro/35385518#35385518\n *\n * param query should be {}\n */\nconst getDom = query => {\n if (query.jquery) {\n return query[0];\n }\n if (query instanceof HTMLElement) {\n return query;\n }\n if (isHtmlString(query)) {\n var tpl = document.createElement('template');\n tpl.innerHTML = query.trim(); // Never return a text node of whitespace as the result\n return tpl.content.firstChild;\n }\n return document.querySelector(query);\n};\nconst isHtmlString = arg => {\n if (typeof arg === 'string' && arg.indexOf('<') > -1) {\n return true;\n }\n return false;\n};\nconst escapeQuery = query => {\n return query.replace(/['\"\\\\]/g, '\\\\$&');\n};\n\n/**\n * Dispatch an event\n *\n */\nconst triggerEvent = (dom_el, event_name) => {\n var event = document.createEvent('HTMLEvents');\n event.initEvent(event_name, true, false);\n dom_el.dispatchEvent(event);\n};\n\n/**\n * Apply CSS rules to a dom element\n *\n */\nconst applyCSS = (dom_el, css) => {\n Object.assign(dom_el.style, css);\n};\n\n/**\n * Add css classes\n *\n */\nconst addClasses = (elmts, ...classes) => {\n var norm_classes = classesArray(classes);\n elmts = castAsArray(elmts);\n elmts.map(el => {\n norm_classes.map(cls => {\n el.classList.add(cls);\n });\n });\n};\n\n/**\n * Remove css classes\n *\n */\nconst removeClasses = (elmts, ...classes) => {\n var norm_classes = classesArray(classes);\n elmts = castAsArray(elmts);\n elmts.map(el => {\n norm_classes.map(cls => {\n el.classList.remove(cls);\n });\n });\n};\n\n/**\n * Return arguments\n *\n */\nconst classesArray = args => {\n var classes = [];\n iterate(args, _classes => {\n if (typeof _classes === 'string') {\n _classes = _classes.trim().split(/[\\11\\12\\14\\15\\40]/);\n }\n if (Array.isArray(_classes)) {\n classes = classes.concat(_classes);\n }\n });\n return classes.filter(Boolean);\n};\n\n/**\n * Create an array from arg if it's not already an array\n *\n */\nconst castAsArray = arg => {\n if (!Array.isArray(arg)) {\n arg = [arg];\n }\n return arg;\n};\n\n/**\n * Get the closest node to the evt.target matching the selector\n * Stops at wrapper\n *\n */\nconst parentMatch = (target, selector, wrapper) => {\n if (wrapper && !wrapper.contains(target)) {\n return;\n }\n while (target && target.matches) {\n if (target.matches(selector)) {\n return target;\n }\n target = target.parentNode;\n }\n};\n\n/**\n * Get the first or last item from an array\n *\n * > 0 - right (last)\n * <= 0 - left (first)\n *\n */\nconst getTail = (list, direction = 0) => {\n if (direction > 0) {\n return list[list.length - 1];\n }\n return list[0];\n};\n\n/**\n * Return true if an object is empty\n *\n */\nconst isEmptyObject = obj => {\n return Object.keys(obj).length === 0;\n};\n\n/**\n * Get the index of an element amongst sibling nodes of the same type\n *\n */\nconst nodeIndex = (el, amongst) => {\n if (!el) return -1;\n amongst = amongst || el.nodeName;\n var i = 0;\n while (el = el.previousElementSibling) {\n if (el.matches(amongst)) {\n i++;\n }\n }\n return i;\n};\n\n/**\n * Set attributes of an element\n *\n */\nconst setAttr = (el, attrs) => {\n iterate(attrs, (val, attr) => {\n if (val == null) {\n el.removeAttribute(attr);\n } else {\n el.setAttribute(attr, '' + val);\n }\n });\n};\n\n/**\n * Replace a node\n */\nconst replaceNode = (existing, replacement) => {\n if (existing.parentNode) existing.parentNode.replaceChild(replacement, existing);\n};\n\n/**\n * highlight v3 | MIT license | Johann Burkard \n * Highlights arbitrary terms in a node.\n *\n * - Modified by Marshal 2011-6-24 (added regex)\n * - Modified by Brian Reavis 2012-8-27 (cleanup)\n */\n\nconst highlight = (element, regex) => {\n if (regex === null) return;\n\n // convet string to regex\n if (typeof regex === 'string') {\n if (!regex.length) return;\n regex = new RegExp(regex, 'i');\n }\n\n // Wrap matching part of text node with highlighting , e.g.\n // Soccer -> Soccer for regex = /soc/i\n const highlightText = node => {\n var match = node.data.match(regex);\n if (match && node.data.length > 0) {\n var spannode = document.createElement('span');\n spannode.className = 'highlight';\n var middlebit = node.splitText(match.index);\n middlebit.splitText(match[0].length);\n var middleclone = middlebit.cloneNode(true);\n spannode.appendChild(middleclone);\n replaceNode(middlebit, spannode);\n return 1;\n }\n return 0;\n };\n\n // Recurse element node, looking for child text nodes to highlight, unless element\n // is childless,