sfgov-design-system
Version:
This is the design system for [SF.gov](https://sf.gov) and the City & County of San Francisco.
1 lines • 79.3 kB
Source Map (JSON)
{"version":3,"file":"docs.js","sources":["../../node_modules/@github/clipboard-copy-element/dist/index.esm.js","../../node_modules/@github/details-dialog-element/dist/index.esm.js","../../node_modules/@github/hotkey/dist/index.js","../../node_modules/selector-set/selector-set.next.js","../../node_modules/selector-observer/dist/index.esm.js","../../node_modules/delegated-events/dist/index.js","../../src/js/docs.js"],"sourcesContent":["function createNode(text) {\n const node = document.createElement('pre');\n node.style.width = '1px';\n node.style.height = '1px';\n node.style.position = 'fixed';\n node.style.top = '5px';\n node.textContent = text;\n return node;\n}\n\nfunction copyNode(node) {\n if ('clipboard' in navigator) {\n // eslint-disable-next-line flowtype/no-flow-fix-me-comments\n // $FlowFixMe Clipboard is not defined in Flow yet.\n return navigator.clipboard.writeText(node.textContent);\n }\n\n const selection = getSelection();\n\n if (selection == null) {\n return Promise.reject(new Error());\n }\n\n selection.removeAllRanges();\n const range = document.createRange();\n range.selectNodeContents(node);\n selection.addRange(range);\n document.execCommand('copy');\n selection.removeAllRanges();\n return Promise.resolve();\n}\nfunction copyText(text) {\n if ('clipboard' in navigator) {\n // eslint-disable-next-line flowtype/no-flow-fix-me-comments\n // $FlowFixMe Clipboard is not defined in Flow yet.\n return navigator.clipboard.writeText(text);\n }\n\n const body = document.body;\n\n if (!body) {\n return Promise.reject(new Error());\n }\n\n const node = createNode(text);\n body.appendChild(node);\n copyNode(node);\n body.removeChild(node);\n return Promise.resolve();\n}\n\nfunction copy(button) {\n const id = button.getAttribute('for');\n const text = button.getAttribute('value');\n\n function trigger() {\n button.dispatchEvent(new CustomEvent('clipboard-copy', {\n bubbles: true\n }));\n }\n\n if (text) {\n copyText(text).then(trigger);\n } else if (id) {\n const root = 'getRootNode' in Element.prototype ? button.getRootNode() : button.ownerDocument;\n if (!(root instanceof Document || 'ShadowRoot' in window && root instanceof ShadowRoot)) return;\n const node = root.getElementById(id);\n if (node) copyTarget(node).then(trigger);\n }\n}\n\nfunction copyTarget(content) {\n if (content instanceof HTMLInputElement || content instanceof HTMLTextAreaElement) {\n return copyText(content.value);\n } else if (content instanceof HTMLAnchorElement && content.hasAttribute('href')) {\n return copyText(content.href);\n } else {\n return copyNode(content);\n }\n}\n\nfunction clicked(event) {\n const button = event.currentTarget;\n\n if (button instanceof HTMLElement) {\n copy(button);\n }\n}\n\nfunction keydown(event) {\n if (event.key === ' ' || event.key === 'Enter') {\n const button = event.currentTarget;\n\n if (button instanceof HTMLElement) {\n event.preventDefault();\n copy(button);\n }\n }\n}\n\nfunction focused(event) {\n event.currentTarget.addEventListener('keydown', keydown);\n}\n\nfunction blurred(event) {\n event.currentTarget.removeEventListener('keydown', keydown);\n}\n\nclass ClipboardCopyElement extends HTMLElement {\n constructor() {\n super();\n this.addEventListener('click', clicked);\n this.addEventListener('focus', focused);\n this.addEventListener('blur', blurred);\n }\n\n connectedCallback() {\n if (!this.hasAttribute('tabindex')) {\n this.setAttribute('tabindex', '0');\n }\n\n if (!this.hasAttribute('role')) {\n this.setAttribute('role', 'button');\n }\n }\n\n get value() {\n return this.getAttribute('value') || '';\n }\n\n set value(text) {\n this.setAttribute('value', text);\n }\n\n}\n\nif (!window.customElements.get('clipboard-copy')) {\n window.ClipboardCopyElement = ClipboardCopyElement;\n window.customElements.define('clipboard-copy', ClipboardCopyElement);\n}\n\nexport default ClipboardCopyElement;\n","const CLOSE_ATTR = 'data-close-dialog';\nconst CLOSE_SELECTOR = `[${CLOSE_ATTR}]`;\n\nfunction autofocus(el) {\n let autofocus = el.querySelector('[autofocus]');\n\n if (!autofocus) {\n autofocus = el;\n el.setAttribute('tabindex', '-1');\n }\n\n autofocus.focus();\n}\n\nfunction keydown(event) {\n const details = event.currentTarget;\n if (!(details instanceof Element)) return;\n\n if (event.key === 'Escape' || event.key === 'Esc') {\n toggleDetails(details, false);\n event.stopPropagation();\n } else if (event.key === 'Tab') {\n restrictTabBehavior(event);\n }\n}\n\nfunction focusable(el) {\n return el.tabIndex >= 0 && !el.disabled && !el.hidden && (!el.type || el.type !== 'hidden') && !el.closest('[hidden]');\n}\n\nfunction restrictTabBehavior(event) {\n if (!(event.currentTarget instanceof Element)) return;\n const dialog = event.currentTarget.querySelector('details-dialog');\n if (!dialog) return;\n event.preventDefault();\n const elements = Array.from(dialog.querySelectorAll('*')).filter(focusable);\n if (elements.length === 0) return;\n const movement = event.shiftKey ? -1 : 1;\n const currentFocus = elements.filter(el => el.matches(':focus'))[0];\n let targetIndex = 0;\n\n if (currentFocus) {\n const currentIndex = elements.indexOf(currentFocus);\n\n if (currentIndex !== -1) {\n const newIndex = currentIndex + movement;\n if (newIndex >= 0) targetIndex = newIndex % elements.length;\n }\n }\n\n elements[targetIndex].focus();\n}\n\nfunction allowClosingDialog(details) {\n const dialog = details.querySelector('details-dialog');\n if (!(dialog instanceof DetailsDialogElement)) return true;\n return dialog.dispatchEvent(new CustomEvent('details-dialog-close', {\n bubbles: true,\n cancelable: true\n }));\n}\n\nfunction onSummaryClick(event) {\n if (!(event.currentTarget instanceof Element)) return;\n const details = event.currentTarget.closest('details[open]');\n if (!details) return; // Prevent summary click events if details-dialog-close was cancelled\n\n if (!allowClosingDialog(details)) {\n event.preventDefault();\n event.stopPropagation();\n }\n}\n\nfunction toggle(event) {\n const details = event.currentTarget;\n if (!(details instanceof Element)) return;\n const dialog = details.querySelector('details-dialog');\n if (!(dialog instanceof DetailsDialogElement)) return;\n\n if (details.hasAttribute('open')) {\n if (document.activeElement) {\n initialized.set(dialog, {\n details,\n activeElement: document.activeElement\n });\n }\n\n autofocus(dialog);\n details.addEventListener('keydown', keydown);\n } else {\n for (const form of dialog.querySelectorAll('form')) {\n if (form instanceof HTMLFormElement) form.reset();\n }\n\n const focusElement = findFocusElement(details, dialog);\n if (focusElement) focusElement.focus();\n details.removeEventListener('keydown', keydown);\n }\n}\n\nfunction findFocusElement(details, dialog) {\n const state = initialized.get(dialog);\n\n if (state && state.activeElement instanceof HTMLElement) {\n return state.activeElement;\n } else {\n return details.querySelector('summary');\n }\n}\n\nfunction toggleDetails(details, open) {\n // Don't update unless state is changing\n if (open === details.hasAttribute('open')) return;\n\n if (open) {\n details.setAttribute('open', '');\n } else if (allowClosingDialog(details)) {\n details.removeAttribute('open');\n }\n}\n\nfunction loadIncludeFragment(event) {\n const details = event.currentTarget;\n if (!(details instanceof Element)) return;\n const dialog = details.querySelector('details-dialog');\n if (!(dialog instanceof DetailsDialogElement)) return;\n const loader = dialog.querySelector('include-fragment:not([src])');\n if (!loader) return;\n const src = dialog.src;\n if (src === null) return;\n loader.addEventListener('loadend', () => {\n if (details.hasAttribute('open')) autofocus(dialog);\n });\n loader.setAttribute('src', src);\n}\n\nconst initialized = new WeakMap();\n\nclass DetailsDialogElement extends HTMLElement {\n static get CLOSE_ATTR() {\n return CLOSE_ATTR;\n }\n\n static get CLOSE_SELECTOR() {\n return CLOSE_SELECTOR;\n }\n\n constructor() {\n super();\n initialized.set(this, {\n details: null,\n activeElement: null\n });\n this.addEventListener('click', function (_ref) {\n let target = _ref.target;\n if (!(target instanceof Element)) return;\n const details = target.closest('details');\n\n if (details && target.closest(CLOSE_SELECTOR)) {\n toggleDetails(details, false);\n }\n });\n }\n\n get src() {\n return this.getAttribute('src');\n }\n\n set src(value) {\n this.setAttribute('src', value);\n }\n\n get preload() {\n return this.hasAttribute('preload');\n }\n\n set preload(value) {\n value ? this.setAttribute('preload', '') : this.removeAttribute('preload');\n }\n\n connectedCallback() {\n this.setAttribute('role', 'dialog');\n this.setAttribute('aria-modal', 'true');\n const state = initialized.get(this);\n if (!state) return;\n const details = this.parentElement;\n if (!details) return;\n const summary = details.querySelector('summary');\n\n if (summary) {\n summary.setAttribute('role', 'button');\n summary.addEventListener('click', onSummaryClick, {\n capture: true\n });\n }\n\n details.addEventListener('toggle', toggle);\n state.details = details;\n }\n\n disconnectedCallback() {\n const state = initialized.get(this);\n if (!state) return;\n const details = state.details;\n if (!details) return;\n details.removeEventListener('toggle', toggle);\n const summary = details.querySelector('summary');\n\n if (summary) {\n summary.removeEventListener('click', onSummaryClick, {\n capture: true\n });\n }\n\n state.details = null;\n }\n\n toggle(open) {\n const state = initialized.get(this);\n if (!state) return;\n const details = state.details;\n if (!details) return;\n toggleDetails(details, open);\n }\n\n static get observedAttributes() {\n return ['src', 'preload'];\n }\n\n attributeChangedCallback() {\n const details = this.parentElement;\n if (!details) return;\n const state = initialized.get(this);\n if (!state) return;\n\n if (this.src) {\n details.addEventListener('toggle', loadIncludeFragment, {\n once: true\n });\n } else {\n details.removeEventListener('toggle', loadIncludeFragment);\n }\n\n if (this.src && this.preload) {\n details.addEventListener('mouseover', loadIncludeFragment, {\n once: true\n });\n } else {\n details.removeEventListener('mouseover', loadIncludeFragment);\n }\n }\n\n}\n\nexport default DetailsDialogElement;\n\nif (!window.customElements.get('details-dialog')) {\n window.DetailsDialogElement = DetailsDialogElement;\n window.customElements.define('details-dialog', DetailsDialogElement);\n}\n","class Leaf {\n constructor(trie) {\n this.children = [];\n this.parent = trie;\n }\n delete(value) {\n const index = this.children.indexOf(value);\n if (index === -1)\n return false;\n this.children = this.children.slice(0, index).concat(this.children.slice(index + 1));\n if (this.children.length === 0) {\n this.parent.delete(this);\n }\n return true;\n }\n add(value) {\n this.children.push(value);\n return this;\n }\n}\nclass RadixTrie {\n constructor(trie) {\n this.parent = null;\n this.children = {};\n this.parent = trie || null;\n }\n get(edge) {\n return this.children[edge];\n }\n insert(edges) {\n let currentNode = this;\n for (let i = 0; i < edges.length; i += 1) {\n const edge = edges[i];\n let nextNode = currentNode.get(edge);\n if (i === edges.length - 1) {\n if (nextNode instanceof RadixTrie) {\n currentNode.delete(nextNode);\n nextNode = null;\n }\n if (!nextNode) {\n nextNode = new Leaf(currentNode);\n currentNode.children[edge] = nextNode;\n }\n return nextNode;\n }\n else {\n if (nextNode instanceof Leaf)\n nextNode = null;\n if (!nextNode) {\n nextNode = new RadixTrie(currentNode);\n currentNode.children[edge] = nextNode;\n }\n }\n currentNode = nextNode;\n }\n return currentNode;\n }\n delete(node) {\n for (const edge in this.children) {\n const currentNode = this.children[edge];\n if (currentNode === node) {\n const success = delete this.children[edge];\n if (Object.keys(this.children).length === 0 && this.parent) {\n this.parent.delete(this);\n }\n return success;\n }\n }\n return false;\n }\n}\n\nfunction isFormField(element) {\n if (!(element instanceof HTMLElement)) {\n return false;\n }\n const name = element.nodeName.toLowerCase();\n const type = (element.getAttribute('type') || '').toLowerCase();\n return (name === 'select' ||\n name === 'textarea' ||\n (name === 'input' && type !== 'submit' && type !== 'reset' && type !== 'checkbox' && type !== 'radio') ||\n element.isContentEditable);\n}\nfunction fireDeterminedAction(el, path) {\n const delegateEvent = new CustomEvent('hotkey-fire', { cancelable: true, detail: { path } });\n const cancelled = !el.dispatchEvent(delegateEvent);\n if (cancelled)\n return;\n if (isFormField(el)) {\n el.focus();\n }\n else {\n el.click();\n }\n}\nfunction expandHotkeyToEdges(hotkey) {\n return hotkey.split(',').map(edge => edge.split(' '));\n}\n\nfunction hotkey(event) {\n const elideShift = event.code.startsWith('Key') && event.shiftKey && event.key.toUpperCase() === event.key;\n return `${event.ctrlKey ? 'Control+' : ''}${event.altKey ? 'Alt+' : ''}${event.metaKey ? 'Meta+' : ''}${event.shiftKey && !elideShift ? 'Shift+' : ''}${event.key}`;\n}\n\nconst hotkeyRadixTrie = new RadixTrie();\nconst elementsLeaves = new WeakMap();\nlet currentTriePosition = hotkeyRadixTrie;\nlet resetTriePositionTimer = null;\nlet path = [];\nfunction resetTriePosition() {\n path = [];\n resetTriePositionTimer = null;\n currentTriePosition = hotkeyRadixTrie;\n}\nfunction keyDownHandler(event) {\n if (event.defaultPrevented)\n return;\n if (!(event.target instanceof Node))\n return;\n if (isFormField(event.target)) {\n const target = event.target;\n if (!target.id)\n return;\n if (!target.ownerDocument.querySelector(`[data-hotkey-scope=${target.id}]`))\n return;\n }\n if (resetTriePositionTimer != null) {\n window.clearTimeout(resetTriePositionTimer);\n }\n resetTriePositionTimer = window.setTimeout(resetTriePosition, 1500);\n const newTriePosition = currentTriePosition.get(hotkey(event));\n if (!newTriePosition) {\n resetTriePosition();\n return;\n }\n path.push(hotkey(event));\n currentTriePosition = newTriePosition;\n if (newTriePosition instanceof Leaf) {\n const target = event.target;\n let shouldFire = false;\n let elementToFire;\n const formField = isFormField(target);\n for (let i = newTriePosition.children.length - 1; i >= 0; i -= 1) {\n elementToFire = newTriePosition.children[i];\n const scope = elementToFire.getAttribute('data-hotkey-scope');\n if ((!formField && !scope) || (formField && target.id === scope)) {\n shouldFire = true;\n break;\n }\n }\n if (elementToFire && shouldFire) {\n fireDeterminedAction(elementToFire, path);\n event.preventDefault();\n }\n resetTriePosition();\n }\n}\nfunction install(element, hotkey) {\n if (Object.keys(hotkeyRadixTrie.children).length === 0) {\n document.addEventListener('keydown', keyDownHandler);\n }\n const hotkeys = expandHotkeyToEdges(hotkey || element.getAttribute('data-hotkey') || '');\n const leaves = hotkeys.map(h => hotkeyRadixTrie.insert(h).add(element));\n elementsLeaves.set(element, leaves);\n}\nfunction uninstall(element) {\n const leaves = elementsLeaves.get(element);\n if (leaves && leaves.length) {\n for (const leaf of leaves) {\n leaf && leaf.delete(element);\n }\n }\n if (Object.keys(hotkeyRadixTrie.children).length === 0) {\n document.removeEventListener('keydown', keyDownHandler);\n }\n}\n\nexport { Leaf, RadixTrie, hotkey as eventToHotkeyString, install, uninstall };\n","// Public: Create a new SelectorSet.\nexport default function SelectorSet() {\n // Construct new SelectorSet if called as a function.\n if (!(this instanceof SelectorSet)) {\n return new SelectorSet();\n }\n\n // Public: Number of selectors added to the set\n this.size = 0;\n\n // Internal: Incrementing ID counter\n this.uid = 0;\n\n // Internal: Array of String selectors in the set\n this.selectors = [];\n\n // Internal: Map of selector ids to objects\n this.selectorObjects = {};\n\n // Internal: All Object index String names mapping to Index objects.\n this.indexes = Object.create(this.indexes);\n\n // Internal: Used Object index String names mapping to Index objects.\n this.activeIndexes = [];\n}\n\n// Detect prefixed Element#matches function.\nvar docElem = window.document.documentElement;\nvar matches =\n docElem.matches ||\n docElem.webkitMatchesSelector ||\n docElem.mozMatchesSelector ||\n docElem.oMatchesSelector ||\n docElem.msMatchesSelector;\n\n// Public: Check if element matches selector.\n//\n// Maybe overridden with custom Element.matches function.\n//\n// el - An Element\n// selector - String CSS selector\n//\n// Returns true or false.\nSelectorSet.prototype.matchesSelector = function(el, selector) {\n return matches.call(el, selector);\n};\n\n// Public: Find all elements in the context that match the selector.\n//\n// Maybe overridden with custom querySelectorAll function.\n//\n// selectors - String CSS selectors.\n// context - Element context\n//\n// Returns non-live list of Elements.\nSelectorSet.prototype.querySelectorAll = function(selectors, context) {\n return context.querySelectorAll(selectors);\n};\n\n// Public: Array of indexes.\n//\n// name - Unique String name\n// selector - Function that takes a String selector and returns a String key\n// or undefined if it can't be used by the index.\n// element - Function that takes an Element and returns an Array of String\n// keys that point to indexed values.\n//\nSelectorSet.prototype.indexes = [];\n\n// Index by element id\nvar idRe = /^#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/g;\nSelectorSet.prototype.indexes.push({\n name: 'ID',\n selector: function matchIdSelector(sel) {\n var m;\n if ((m = sel.match(idRe))) {\n return m[0].slice(1);\n }\n },\n element: function getElementId(el) {\n if (el.id) {\n return [el.id];\n }\n }\n});\n\n// Index by all of its class names\nvar classRe = /^\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/g;\nSelectorSet.prototype.indexes.push({\n name: 'CLASS',\n selector: function matchClassSelector(sel) {\n var m;\n if ((m = sel.match(classRe))) {\n return m[0].slice(1);\n }\n },\n element: function getElementClassNames(el) {\n var className = el.className;\n if (className) {\n if (typeof className === 'string') {\n return className.split(/\\s/);\n } else if (typeof className === 'object' && 'baseVal' in className) {\n // className is a SVGAnimatedString\n // global SVGAnimatedString is not an exposed global in Opera 12\n return className.baseVal.split(/\\s/);\n }\n }\n }\n});\n\n// Index by tag/node name: `DIV`, `FORM`, `A`\nvar tagRe = /^((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/g;\nSelectorSet.prototype.indexes.push({\n name: 'TAG',\n selector: function matchTagSelector(sel) {\n var m;\n if ((m = sel.match(tagRe))) {\n return m[0].toUpperCase();\n }\n },\n element: function getElementTagName(el) {\n return [el.nodeName.toUpperCase()];\n }\n});\n\n// Default index just contains a single array of elements.\nSelectorSet.prototype.indexes['default'] = {\n name: 'UNIVERSAL',\n selector: function() {\n return true;\n },\n element: function() {\n return [true];\n }\n};\n\n// Use ES Maps when supported\nvar Map;\nif (typeof window.Map === 'function') {\n Map = window.Map;\n} else {\n Map = (function() {\n function Map() {\n this.map = {};\n }\n Map.prototype.get = function(key) {\n return this.map[key + ' '];\n };\n Map.prototype.set = function(key, value) {\n this.map[key + ' '] = value;\n };\n return Map;\n })();\n}\n\n// Regexps adopted from Sizzle\n// https://github.com/jquery/sizzle/blob/1.7/sizzle.js\n//\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g;\n\n// Internal: Get indexes for selector.\n//\n// selector - String CSS selector\n//\n// Returns Array of {index, key}.\nfunction parseSelectorIndexes(allIndexes, selector) {\n allIndexes = allIndexes.slice(0).concat(allIndexes['default']);\n\n var allIndexesLen = allIndexes.length,\n i,\n j,\n m,\n dup,\n rest = selector,\n key,\n index,\n indexes = [];\n\n do {\n chunker.exec('');\n if ((m = chunker.exec(rest))) {\n rest = m[3];\n if (m[2] || !rest) {\n for (i = 0; i < allIndexesLen; i++) {\n index = allIndexes[i];\n if ((key = index.selector(m[1]))) {\n j = indexes.length;\n dup = false;\n while (j--) {\n if (indexes[j].index === index && indexes[j].key === key) {\n dup = true;\n break;\n }\n }\n if (!dup) {\n indexes.push({ index: index, key: key });\n }\n break;\n }\n }\n }\n }\n } while (m);\n\n return indexes;\n}\n\n// Internal: Find first item in Array that is a prototype of `proto`.\n//\n// ary - Array of objects\n// proto - Prototype of expected item in `ary`\n//\n// Returns object from `ary` if found. Otherwise returns undefined.\nfunction findByPrototype(ary, proto) {\n var i, len, item;\n for (i = 0, len = ary.length; i < len; i++) {\n item = ary[i];\n if (proto.isPrototypeOf(item)) {\n return item;\n }\n }\n}\n\n// Public: Log when added selector falls under the default index.\n//\n// This API should not be considered stable. May change between\n// minor versions.\n//\n// obj - {selector, data} Object\n//\n// SelectorSet.prototype.logDefaultIndexUsed = function(obj) {\n// console.warn(obj.selector, \"could not be indexed\");\n// };\n//\n// Returns nothing.\nSelectorSet.prototype.logDefaultIndexUsed = function() {};\n\n// Public: Add selector to set.\n//\n// selector - String CSS selector\n// data - Optional data Object (default: undefined)\n//\n// Returns nothing.\nSelectorSet.prototype.add = function(selector, data) {\n var obj,\n i,\n indexProto,\n key,\n index,\n objs,\n selectorIndexes,\n selectorIndex,\n indexes = this.activeIndexes,\n selectors = this.selectors,\n selectorObjects = this.selectorObjects;\n\n if (typeof selector !== 'string') {\n return;\n }\n\n obj = {\n id: this.uid++,\n selector: selector,\n data: data\n };\n selectorObjects[obj.id] = obj;\n\n selectorIndexes = parseSelectorIndexes(this.indexes, selector);\n for (i = 0; i < selectorIndexes.length; i++) {\n selectorIndex = selectorIndexes[i];\n key = selectorIndex.key;\n indexProto = selectorIndex.index;\n\n index = findByPrototype(indexes, indexProto);\n if (!index) {\n index = Object.create(indexProto);\n index.map = new Map();\n indexes.push(index);\n }\n\n if (indexProto === this.indexes['default']) {\n this.logDefaultIndexUsed(obj);\n }\n objs = index.map.get(key);\n if (!objs) {\n objs = [];\n index.map.set(key, objs);\n }\n objs.push(obj);\n }\n\n this.size++;\n selectors.push(selector);\n};\n\n// Public: Remove selector from set.\n//\n// selector - String CSS selector\n// data - Optional data Object (default: undefined)\n//\n// Returns nothing.\nSelectorSet.prototype.remove = function(selector, data) {\n if (typeof selector !== 'string') {\n return;\n }\n\n var selectorIndexes,\n selectorIndex,\n i,\n j,\n k,\n selIndex,\n objs,\n obj,\n indexes = this.activeIndexes,\n selectors = (this.selectors = []),\n selectorObjects = this.selectorObjects,\n removedIds = {},\n removeAll = arguments.length === 1;\n\n selectorIndexes = parseSelectorIndexes(this.indexes, selector);\n for (i = 0; i < selectorIndexes.length; i++) {\n selectorIndex = selectorIndexes[i];\n\n j = indexes.length;\n while (j--) {\n selIndex = indexes[j];\n if (selectorIndex.index.isPrototypeOf(selIndex)) {\n objs = selIndex.map.get(selectorIndex.key);\n if (objs) {\n k = objs.length;\n while (k--) {\n obj = objs[k];\n if (obj.selector === selector && (removeAll || obj.data === data)) {\n objs.splice(k, 1);\n removedIds[obj.id] = true;\n }\n }\n }\n break;\n }\n }\n }\n\n for (i in removedIds) {\n delete selectorObjects[i];\n this.size--;\n }\n\n for (i in selectorObjects) {\n selectors.push(selectorObjects[i].selector);\n }\n};\n\n// Sort by id property handler.\n//\n// a - Selector obj.\n// b - Selector obj.\n//\n// Returns Number.\nfunction sortById(a, b) {\n return a.id - b.id;\n}\n\n// Public: Find all matching decendants of the context element.\n//\n// context - An Element\n//\n// Returns Array of {selector, data, elements} matches.\nSelectorSet.prototype.queryAll = function(context) {\n if (!this.selectors.length) {\n return [];\n }\n\n var matches = {},\n results = [];\n var els = this.querySelectorAll(this.selectors.join(', '), context);\n\n var i, j, len, len2, el, m, match, obj;\n for (i = 0, len = els.length; i < len; i++) {\n el = els[i];\n m = this.matches(el);\n for (j = 0, len2 = m.length; j < len2; j++) {\n obj = m[j];\n if (!matches[obj.id]) {\n match = {\n id: obj.id,\n selector: obj.selector,\n data: obj.data,\n elements: []\n };\n matches[obj.id] = match;\n results.push(match);\n } else {\n match = matches[obj.id];\n }\n match.elements.push(el);\n }\n }\n\n return results.sort(sortById);\n};\n\n// Public: Match element against all selectors in set.\n//\n// el - An Element\n//\n// Returns Array of {selector, data} matches.\nSelectorSet.prototype.matches = function(el) {\n if (!el) {\n return [];\n }\n\n var i, j, k, len, len2, len3, index, keys, objs, obj, id;\n var indexes = this.activeIndexes,\n matchedIds = {},\n matches = [];\n\n for (i = 0, len = indexes.length; i < len; i++) {\n index = indexes[i];\n keys = index.element(el);\n if (keys) {\n for (j = 0, len2 = keys.length; j < len2; j++) {\n if ((objs = index.map.get(keys[j]))) {\n for (k = 0, len3 = objs.length; k < len3; k++) {\n obj = objs[k];\n id = obj.id;\n if (!matchedIds[id] && this.matchesSelector(el, obj.selector)) {\n matchedIds[id] = true;\n matches.push(obj);\n }\n }\n }\n }\n }\n }\n\n return matches.sort(sortById);\n};\n","import SelectorSet from 'selector-set';\n\nvar el = null;\nvar observer = null;\nvar queue = [];\n\nfunction scheduleBatch(document, callback) {\n var calls = [];\n\n function processBatchQueue() {\n var callsCopy = calls;\n calls = [];\n callback(callsCopy);\n }\n\n function scheduleBatchQueue() {\n for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n calls.push(args);\n if (calls.length === 1) scheduleMacroTask(document, processBatchQueue);\n }\n\n return scheduleBatchQueue;\n}\n\nfunction scheduleMacroTask(document, callback) {\n if (!observer) {\n observer = new MutationObserver(handleMutations);\n }\n\n if (!el) {\n el = document.createElement('div');\n observer.observe(el, { attributes: true });\n }\n\n queue.push(callback);\n el.setAttribute('data-twiddle', '' + Date.now());\n}\n\nfunction handleMutations() {\n var callbacks = queue;\n queue = [];\n for (var i = 0; i < callbacks.length; i++) {\n try {\n callbacks[i]();\n } catch (error) {\n setTimeout(function () {\n throw error;\n }, 0);\n }\n }\n}\n\n// selector-observer processes dom mutations in two phases. This module applies\n// the Change set from the first phase and invokes the any registered hooks.\n\nvar initMap = new WeakMap();\nvar initializerMap = new WeakMap();\nvar subscriptionMap = new WeakMap();\nvar addMap = new WeakMap();\n\nfunction applyChanges(selectorObserver, changes) {\n for (var i = 0; i < changes.length; i++) {\n var change = changes[i];\n var type = change[0];\n var el = change[1];\n var observer = change[2];\n if (type === ADD) {\n runInit(observer, el);\n runAdd(observer, el);\n } else if (type === REMOVE) {\n runRemove(observer, el);\n } else if (type === REMOVE_ALL) {\n runRemoveAll(selectorObserver.observers, el);\n }\n }\n}\n\n// Run observer node \"initialize\" callback once.\n// Call when observer selector matches node.\n//\n// observer - An observer Object.\n// el - An Element\n//\n// Returns nothing.\nfunction runInit(observer, el) {\n if (!(el instanceof observer.elementConstructor)) {\n return;\n }\n\n var initIds = initMap.get(el);\n if (!initIds) {\n initIds = [];\n initMap.set(el, initIds);\n }\n\n if (initIds.indexOf(observer.id) === -1) {\n var initializer = void 0;\n if (observer.initialize) {\n initializer = observer.initialize.call(undefined, el);\n }\n if (initializer) {\n var initializers = initializerMap.get(el);\n if (!initializers) {\n initializers = {};\n initializerMap.set(el, initializers);\n }\n initializers['' + observer.id] = initializer;\n }\n initIds.push(observer.id);\n }\n}\n\n// Run observer node \"add\" callback.\n// Call when observer selector matches node.\n//\n// observer - An observer Object.\n// el - An Element\n//\n// Returns nothing.\nfunction runAdd(observer, el) {\n if (!(el instanceof observer.elementConstructor)) {\n return;\n }\n\n var addIds = addMap.get(el);\n if (!addIds) {\n addIds = [];\n addMap.set(el, addIds);\n }\n\n if (addIds.indexOf(observer.id) === -1) {\n observer.elements.push(el);\n\n var initializers = initializerMap.get(el);\n var initializer = initializers ? initializers['' + observer.id] : null;\n if (initializer && initializer.add) {\n initializer.add.call(undefined, el);\n }\n\n if (observer.subscribe) {\n var subscription = observer.subscribe.call(undefined, el);\n if (subscription) {\n var subscriptions = subscriptionMap.get(el);\n if (!subscriptions) {\n subscriptions = {};\n subscriptionMap.set(el, subscriptions);\n }\n subscriptions['' + observer.id] = subscription;\n }\n }\n\n if (observer.add) {\n observer.add.call(undefined, el);\n }\n\n addIds.push(observer.id);\n }\n}\n\n// Runs all observer element \"remove\" callbacks.\n// Call when element is completely removed from the DOM.\n//\n// observer - An observer Object.\n// el - An Element\n//\n// Returns nothing.\nfunction runRemove(observer, el) {\n if (!(el instanceof observer.elementConstructor)) {\n return;\n }\n\n var addIds = addMap.get(el);\n if (!addIds) {\n return;\n }\n\n var index = observer.elements.indexOf(el);\n if (index !== -1) {\n observer.elements.splice(index, 1);\n }\n\n index = addIds.indexOf(observer.id);\n if (index !== -1) {\n var initializers = initializerMap.get(el);\n var initializer = initializers ? initializers['' + observer.id] : null;\n if (initializer) {\n if (initializer.remove) {\n initializer.remove.call(undefined, el);\n }\n }\n\n if (observer.subscribe) {\n var subscriptions = subscriptionMap.get(el);\n var subscription = subscriptions ? subscriptions['' + observer.id] : null;\n if (subscription && subscription.unsubscribe) {\n subscription.unsubscribe();\n }\n }\n\n if (observer.remove) {\n observer.remove.call(undefined, el);\n }\n\n addIds.splice(index, 1);\n }\n\n if (addIds.length === 0) {\n addMap.delete(el);\n }\n}\n\n// Runs all observer element \"remove\" callbacks.\n// Call when element is completely removed from the DOM.\n//\n// observes - Array of observers\n// el - An Element\n//\n// Returns nothing.\nfunction runRemoveAll(observers, el) {\n var addIds = addMap.get(el);\n if (!addIds) {\n return;\n }\n\n var ids = addIds.slice(0);\n for (var i = 0; i < ids.length; i++) {\n var observer = observers[ids[i]];\n if (!observer) {\n continue;\n }\n\n var index = observer.elements.indexOf(el);\n if (index !== -1) {\n observer.elements.splice(index, 1);\n }\n\n var initializers = initializerMap.get(el);\n var initializer = initializers ? initializers['' + observer.id] : null;\n if (initializer && initializer.remove) {\n initializer.remove.call(undefined, el);\n }\n\n var subscriptions = subscriptionMap.get(el);\n var subscription = subscriptions ? subscriptions['' + observer.id] : null;\n if (subscription && subscription.unsubscribe) {\n subscription.unsubscribe();\n }\n\n if (observer.remove) {\n observer.remove.call(undefined, el);\n }\n }\n addMap.delete(el);\n}\n\nvar innerHTMLReplacementIsBuggy = null;\n\n// In IE 9/10/11 replacing child via innerHTML will orphan all of the child\n// elements. This prevents walking the descendants of removedNodes.\n// https://connect.microsoft.com/IE/feedback/details/797844/ie9-10-11-dom-child-kill-bug\nfunction detectInnerHTMLReplacementBuggy(document) {\n if (innerHTMLReplacementIsBuggy === null) {\n var a = document.createElement('div');\n var b = document.createElement('div');\n var c = document.createElement('div');\n a.appendChild(b);\n b.appendChild(c);\n a.innerHTML = '';\n innerHTMLReplacementIsBuggy = c.parentNode !== b;\n }\n return innerHTMLReplacementIsBuggy;\n}\n\nfunction supportsSelectorMatching(node) {\n return 'matches' in node || 'webkitMatchesSelector' in node || 'mozMatchesSelector' in node || 'oMatchesSelector' in node || 'msMatchesSelector' in node;\n}\n\n// selector-observer processes dom mutations in two phases. This module\n// processes DOM mutations, revalidates selectors against the target element and\n// enqueues a Change for an observers hooks to be ran.\n\n// A set of Changes is structured as an Array of tuples:\n//\n// [ADD, element, observer]: Indicates that an observer starting matching\n// the element.\nvar ADD = 1;\n\n// [REMOVE, element, observer]: Indicates that an observer stopped matching\n// the element.\nvar REMOVE = 2;\n\n// [REMOVE_ALL, element]: Indicates that an element was removed from the\n// document and all related observers stopped matching the element.\nvar REMOVE_ALL = 3;\n\n// A handler for processing MutationObserver mutations.\n//\n// selectorObserver - The SelectorObserver\n// changes - Array of changes to append to\n// mutations - An array of MutationEvents\n//\n// Return nothing.\nfunction handleMutations$1(selectorObserver, changes, mutations) {\n for (var i = 0; i < mutations.length; i++) {\n var mutation = mutations[i];\n if (mutation.type === 'childList') {\n addNodes(selectorObserver, changes, mutation.addedNodes);\n removeNodes(selectorObserver, changes, mutation.removedNodes);\n } else if (mutation.type === 'attributes') {\n revalidateObservers(selectorObserver, changes, mutation.target);\n }\n }\n if (detectInnerHTMLReplacementBuggy(selectorObserver.ownerDocument)) {\n revalidateOrphanedElements(selectorObserver, changes);\n }\n}\n\n// Run observer node \"add\" callback once on the any matching\n// node and its subtree.\n//\n// selectorObserver - The SelectorObserver\n// changes - Array of changes to append to\n// nodes - A NodeList of Nodes\n//\n// Returns nothing.\nfunction addNodes(selectorObserver, changes, nodes) {\n for (var i = 0; i < nodes.length; i++) {\n var node = nodes[i];\n\n if (supportsSelectorMatching(node)) {\n var matches = selectorObserver.selectorSet.matches(node);\n for (var j = 0; j < matches.length; j++) {\n var data = matches[j].data;\n\n changes.push([ADD, node, data]);\n }\n }\n\n if ('querySelectorAll' in node) {\n var matches2 = selectorObserver.selectorSet.queryAll(node);\n for (var _j = 0; _j < matches2.length; _j++) {\n var _matches2$_j = matches2[_j],\n _data = _matches2$_j.data,\n elements = _matches2$_j.elements;\n\n for (var k = 0; k < elements.length; k++) {\n changes.push([ADD, elements[k], _data]);\n }\n }\n }\n }\n}\n\n// Run all observer node \"remove\" callbacks on the node\n// and its entire subtree.\n//\n// selectorObserver - The SelectorObserver\n// changes - Array of changes to append to\n// nodes - A NodeList of Nodes\n//\n// Returns nothing.\nfunction removeNodes(selectorObserver, changes, nodes) {\n for (var i = 0; i < nodes.length; i++) {\n var node = nodes[i];\n if ('querySelectorAll' in node) {\n changes.push([REMOVE_ALL, node]);\n var descendants = node.querySelectorAll('*');\n for (var j = 0; j < descendants.length; j++) {\n changes.push([REMOVE_ALL, descendants[j]]);\n }\n }\n }\n}\n\n// Recheck all \"add\" observers to see if the selector still matches.\n// If not, run the \"remove\" callback.\n//\n// selectorObserver - The SelectorObserver\n// changes - Array of changes to append to\n// node - A Node\n//\n// Returns nothing.\nfunction revalidateObservers(selectorObserver, changes, node) {\n if (supportsSelectorMatching(node)) {\n var matches = selectorObserver.selectorSet.matches(node);\n for (var i = 0; i < matches.length; i++) {\n var data = matches[i].data;\n\n changes.push([ADD, node, data]);\n }\n }\n\n if ('querySelectorAll' in node) {\n var ids = addMap.get(node);\n if (ids) {\n for (var _i = 0; _i < ids.length; _i++) {\n var observer = selectorObserver.observers[ids[_i]];\n if (observer) {\n if (!selectorObserver.selectorSet.matchesSelector(node, observer.selector)) {\n changes.push([REMOVE, node, observer]);\n }\n }\n }\n }\n }\n}\n\n// Recheck all \"add\" observers to see if the selector still matches.\n// If not, run the \"remove\" callback. Runs on node and all its descendants.\n//\n// selectorObserver - The SelectorObserver\n// changes - Array of changes to append to\n// node - The root Node\n//\n// Returns nothing.\nfunction revalidateDescendantObservers(selectorObserver, changes, node) {\n if ('querySelectorAll' in node) {\n revalidateObservers(selectorObserver, changes, node);\n var descendants = node.querySelectorAll('*');\n for (var i = 0; i < descendants.length; i++) {\n revalidateObservers(selectorObserver, changes, descendants[i]);\n }\n }\n}\n\n// Recheck input after \"change\" event and possible related form elements.\n//\n// selectorObserver - The SelectorObserver\n// changes - Array of changes to append to\n// input - The HTMLInputElement\n//\n// Returns nothing.\nfunction revalidateInputObservers(selectorObserver, changes, inputs) {\n for (var i = 0; i < inputs.length; i++) {\n var input = inputs[i];\n var els = input.form ? input.form.elements : selectorObserver.rootNode.querySelectorAll('input');\n for (var j = 0; j < els.length; j++) {\n revalidateObservers(selectorObserver, changes, els[j]);\n }\n }\n}\n\n// Check all observed elements to see if they are still in the DOM.\n// Only intended to run on IE where innerHTML replacement is buggy.\n//\n// selectorObserver - The SelectorObserver\n// changes - Array of changes to append to\n//\n// Returns nothing.\nfunction revalidateOrphanedElements(selectorObserver, changes) {\n for (var i = 0; i < selectorObserver.observers.length; i++) {\n var observer = selectorObserver.observers[i];\n if (observer) {\n var elements = observer.elements;\n\n for (var j = 0; j < elements.length; j++) {\n var el = elements[j];\n if (!el.parentNode) {\n changes.push([REMOVE_ALL, el]);\n }\n }\n }\n }\n}\n\nfunction whenReady(document, callback) {\n var readyState = document.readyState;\n if (readyState === 'interactive' || readyState === 'complete') {\n scheduleMacroTask(document, callback);\n } else {\n document.addEventListener('DOMContentLoaded', scheduleMacroTask(document, callback));\n }\n}\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) {\n return typeof obj;\n} : function (obj) {\n return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n};\n\n// Observer uid counter\nvar uid = 0;\n\nfunction SelectorObserver(rootNode) {\n this.rootNode = rootNode.nodeType === 9 ? rootNode.documentElement : rootNode;\n this.ownerDocument = rootNode.nodeType === 9 ? rootNode : rootNode.ownerDocument;\n\n // Map of observer id to object\n this.observers = [];\n\n // Index of selectors to observer objects\n this.selectorSet = new SelectorSet();\n\n // Process all mutations from root element\n this.mutationObserver = new MutationObserver(handleRootMutations.bind(this, this));\n\n this._scheduleAddRootNodes = scheduleBatch(this.ownerDocument, addRootNodes.bind(this, this));\n\n this._handleThrottledChangedTargets = scheduleBatch(this.ownerDocument, handleChangedTargets.bind(this, this));\n this.rootNode.addEventListener('change', handleChangeEvents.bind(this, this), false);\n\n whenReady(this.ownerDocument, onReady.bind(this, this));\n}\n\nSelectorObserver.prototype.disconnect = function () {\n this.mutationObserver.disconnect();\n};\n\n// Register a new observer.\n//\n// selector - String CSS selector.\n// handlers - Initialize Function or Object with keys:\n// initialize - Function to invoke once when Node is first matched\n// add - Function to invoke when Node matches selector\n// remove - Function to invoke when Node no longer matches selector\n// subscribe - Function to invoke when Node matches selector and returns Subscription.\n//\n// Returns Observer object.\nSelectorObserver.prototype.observe = function (a, b) {\n var handlers = void 0;\n\n if (typeof b === 'function') {\n handlers = {\n selector: a,\n initialize: b\n };\n } else if ((typeof b === 'undefined' ? 'undefined' : _typeof(b)) === 'object') {\n handlers = b;\n handlers.selector = a;\n } else {\n handlers = a;\n }\n\n var self = this;\n\n var observer = {\n id: uid++,\n selector: handlers.selector,\n initialize: handlers.initialize,\n add: handlers.add,\n remove: handlers.remove,\n subscribe: handlers.subscribe,\n elements: [],\n elementConstructor: handlers.hasOwnProperty('constructor') ? handlers.constructor : this.ownerDocument.defaultView.Element,\n abort: function abort() {\n self._abortObserving(observer);\n }\n };\n this.selectorSet.add(observer.selector, observer);\n this.observers[observer.id] = observer;\n this._scheduleAddRootNodes();\n\n return observer;\n};\n\n// Removes observer and calls any remaining remove hooks.\n//\n// observer - Observer object\n//\n// Returns nothing.\nSelectorObserver.prototype._abortObserving = function (observer) {\n var elements = observer.elements;\n for (var i = 0; i < elements.length; i++) {\n runRemove(observer, elements[i]);\n }\n this.selectorSet.remove(observer.selector, observer);\n delete this.observers[observer.id];\n};\n\n// Internal: For hacking in dirty changes that aren't getting picked up\nSelectorObserver.prototype.triggerObservers = function (container) {\n var changes = [];\n revalidateDescendantObservers(this, changes, container);\n applyChanges(this, changes);\n};\n\nfunction onReady(selectorObserver) {\n selectorObserver.mutationObserver.observe(selectorObserver.rootNode, {\n childList: true,\n attributes: true,\n subtree: true\n });\n selectorObserver._scheduleAddRootNodes();\n}\n\nfunction addRootNodes(selectorObserver) {\n var changes = [];\n addNodes(selectorObserver, changes, [selectorObserver.rootNode]);\n applyChanges(selectorObserver, changes);\n}\n\nfunction handleRootMutations(selectorObserver, mutations) {\n var changes = [];\n handleMutations$1(selectorObserver, changes, mutations);\n applyChanges(selectorObserver, changes);\n}\n\nfunction handleChangeEvents(selectorObserver, event) {\n selectorObserver._handleThrottledChangedTargets(event.target);\n}\n\nfunction handleChangedTargets(selectorObserver, inputs) {\n var changes = [];\n revalidateInputObservers(selectorObserver, changes, inputs);\n applyChanges(selectorObserver, changes);\n}\n\n// observe\n//\n// Observe provides a declarative hook thats informed when an element becomes\n// matched by a selector, and then when it stops matching the selector.\n//\n// Examples\n//\n// observe('.js-foo', (el) => {\n// console.log(el, 'was added to the DOM')\n// })\n//\n// observe('.js-bar', {\n// add(el) { console.log('js-bar was added to', el) },\n// remove(el) { console.log 'js-bar was removed from', el) }\n// })\n//\n\nvar documentObserver = void 0;\n\nfunction getDocumentObserver() {\n if (!documentObserver) {\n documentObserver = new SelectorObserver(window.document);\n }\n return documentObserver;\n}\n\nfunction observe() {\n var _getDocumentObserver;\n\n return (_getDocumentObserver = getDocumentObserver()).observe.apply(_getDocumentObserver, arguments);\n}\n\nfunction triggerObservers() {\n var _getDocumentObserver2;\n\n return (_getDocumentObserver2 = getDocumentObserver()).triggerObservers.apply(_getDocumentObserver2, arguments);\n}\n\nexport default SelectorObserver;\nexport { getDocumentObserver, observe, triggerObservers };\n","import SelectorSet from 'selector-set';\n\nvar bubbleEvents = {};\nvar captureEvents = {};\nvar propagationStopped = new WeakMap();\nvar immediatePropagationStopped = new WeakMap();\nvar currentTargets = new WeakMap();\nvar currentTargetDesc = Object.getOwnPropertyDescriptor(Event.prototype, 'currentTarget');\n\nfunction before(subject, verb, fn) {\n var source = subject[verb];\n\n subject[verb] = function () {\n fn.apply(subject, arguments);\n return source.apply(subject, arguments);\n };\n\n return subject;\n}\n\nfunction matches(selectors, target, reverse) {\n var queue = [];\n var node = target;\n\n do {\n if (node.nodeType !== 1) break;\n\n var _matches = selectors.matches(node);\n\n if (_matches.length) {\n var matched = {\n node: node,\n observers: _matches\n };\n\n if (reverse) {\n queue.unshift(matched);\n } else {\n queue.push(matched);\n }\n }\n } while (node = node.parentElement);\n\n return queue;\n}\n\nfunction trackPropagation() {\n propagationStopped.set(this, true);\n}\n\nfunction trackImmediate() {\n propagationStopped.set(this, true);\n immediatePropagationStopped.set(this, true);\n}\n\nfunction getCurrentTarget() {\n return currentTargets.get(this) || null;\n}\n\nfunction defineCurrentTarget(event, getter) {\n if (!currentTargetDesc) return;\n Object.defineProperty(event, 'currentTarget', {\n configurable: true,\n enumerable: true,\n get: getter || currentTargetDesc.get\n });\n}\n\nfunction canDispatch(event) {\n try {\n event.eventPhase;\n return true;\n } catch (_) {\n return false;\n }\n}\n\nfunction dispatch(event) {\n if (!canDispatch(event)) return;\n var events = event.eventPhase === 1 ? captureEvents : bubbleEvents;\n var selectors = events[event.type];\n if (!selectors) return;\n var queue = matches(selectors, event.target, event.eventPhase === 1);\n if (!queue.length) return;\n before(event, 'stopPropagation', trackPropagation);\n before(event, 'stopImmediatePropagation', trackImmediate);\n defineCurrentTarget(event, getCurrentTarget);\n\n for (var i = 0, len1 = queue.length; i < len1; i++) {\n if (propagationStopped.get(event)) break;\n var matched = queue[i];\n currentTargets.set(event, matched.node);\n\n for (var j = 0, len2 = matched.observers.length; j < len2; j++) {\n if (immediatePropagat