{ "version": 3, "sources": ["../../javascript/controllers/accordion-controller.js", "../../javascript/controllers/accordion2-controller.js", "../../javascript/controllers/admin-beer-controller.js", "../../javascript/controllers/admin-merge-controller.js", "../../javascript/controllers/auto-save-controller.js", "../../javascript/controllers/auto-textfield-height-controller.js", "../../javascript/controllers/autocomplete-controller.js", "../../javascript/controllers/availability-promo-controller.js", "../../javascript/controllers/beacon-controller.js", "../../javascript/controllers/product-autocomplete-controller.js", "../../javascript/controllers/beer-autocomplete-controller.js", "../../javascript/controllers/beer-info-controller.js", "../../javascript/controllers/beer-suggestions-controller.js", "../../javascript/controllers/beers-added-modal-controller.js", "../../javascript/controllers/block-modal-controller.js", "../../javascript/controllers/brewery-autocomplete-controller.js", "../../javascript/controllers/brewery-multi-select-controller.js", "../../javascript/controllers/bulk-move-controller.js", "../../javascript/controllers/calculator-controller.js", "../../javascript/controllers/calendly-controller.js", "../../javascript/controllers/charts-controller.js", "../../javascript/controllers/checkbox-counter-controller.js", "../../javascript/controllers/checkbox-submit-controller.js", "../../javascript/controllers/checkbox-toggle-controller.js", "../../javascript/controllers/checklist-accordion-controller.js", "../../javascript/controllers/checklists-controller.js", "../../javascript/controllers/choose-saved-card-controller.js", "../../javascript/controllers/clipboard_controller.js", "../../javascript/controllers/closeable-controller.js", "../../javascript/controllers/codemirror-controller.js", "../../javascript/controllers/collapsible-controller.js", "../../javascript/controllers/collapsible-simple-controller.js", "../../javascript/controllers/condition-ids-controller.js", "../../javascript/controllers/conditional-input-controller.js", "../../javascript/controllers/custom-product-autocomplete-controller.js", "../../javascript/controllers/date-input-controller.js", "../../javascript/controllers/digital-display-controller.js", "../../../node_modules/ev-emitter/ev-emitter.js", "../../../node_modules/get-size/get-size.js", "../../../node_modules/desandro-matches-selector/matches-selector.js", "../../../node_modules/fizzy-ui-utils/utils.js", "../../../node_modules/outlayer/item.js", "../../../node_modules/outlayer/outlayer.js", "../../../node_modules/masonry-layout/masonry.js", "../../../node_modules/imagesloaded/imagesloaded.js", "../../javascript/controllers/filter-templates-controller.js", "../../javascript/controllers/fonts-controller.js", "../../javascript/controllers/google-autocomplete-controller.js", "../../javascript/controllers/hamburger-menu-controller.js", "../../javascript/models/debouncer.js", "../../javascript/controllers/hiding-header-controller.js", "../../javascript/controllers/honeybadger-controller.js", "../../javascript/controllers/image-background-remover-controller.js", "../../javascript/lib/load-styles.js", "../../javascript/controllers/image-editor-controller.js", "../../javascript/controllers/location-autocomplete-controller.js", "../../javascript/controllers/masonry-grid-controller.js", "../../javascript/controllers/menu-controller.js", "../../javascript/controllers/menu-search-controller.js", "../../javascript/controllers/menu-section-controller.js", "../../javascript/controllers/menu-sections-controller.js", "../../javascript/controllers/modular-controller.js", "../../javascript/controllers/multi-select-controller.js", "../../javascript/controllers/order-search-controller.js", "../../javascript/controllers/orders-controller.js", "../../javascript/controllers/pickup-locations-controller.js", "../../javascript/controllers/place-lead-controller.js", "../../javascript/controllers/price-calculator-controller.js", "../../javascript/controllers/print-iframe-controller.js", "../../javascript/controllers/print-menu-landing-page-controller.js", "../../javascript/controllers/print-menus-controller.js", "../../javascript/controllers/print-preview-controller.js", "../../javascript/controllers/product-type-controller.js", "../../javascript/controllers/property-segments-controller.js", "../../javascript/controllers/purchase-limit-controller.js", "../../javascript/controllers/remote-file-form-controller.js", "../../javascript/controllers/scroll-to-top-controller.js", "../../javascript/controllers/segmented_field_controller.js", "../../javascript/controllers/segments-controller.js", "../../javascript/controllers/select-all-controller.js", "../../javascript/controllers/serving-controller.js", "../../javascript/controllers/servings-controller.js", "../../javascript/controllers/shoelace-controller.js", "../../javascript/controllers/show-more-controller.js", "../../javascript/controllers/simple-beer-autocomplete-controller.js", "../../javascript/controllers/simple-modular-controller.js", "../../javascript/controllers/smooth-scroller-controller.js", "../../javascript/controllers/sortable-controller.js", "../../javascript/controllers/sticky-controller.js", "../../javascript/controllers/streamlined-menu-controller.js", "../../javascript/controllers/stripe-controller.js", "../../javascript/controllers/structured-data-controller.js", "../../javascript/controllers/tabs-controller.js", "../../javascript/controllers/tabs2-controller.js", "../../javascript/controllers/textfit-controller.js", "../../javascript/controllers/tracked-clicks-controller.js", "../../javascript/controllers/trix-controller.js", "../../javascript/controllers/turnstile_controller.js", "../../javascript/controllers/tv-preview-controller.js", "../../javascript/controllers/user-preferences-controller.js", "../../javascript/controllers/video-modal-controller.js", "../../javascript/controllers/viewport-calculate-controller.js", "../../javascript/controllers/viewport-entrance-toggle-controller.js", "../../javascript/controllers/visible-anchor-controller.js", "../../javascript/controllers/visible-controller.js", "../../javascript/controllers/visible-from-radio-controller.js", "../../javascript/controllers/web-menu-preview-sizes-controller.js", "import-glob:./controllers/**/*.js", "../../../node_modules/@stimulus-components/dialog/dist/stimulus-dialog.mjs", "../../../node_modules/stimulus-use/dist/index.js", "../../../node_modules/@stimulus-components/dropdown/dist/stimulus-dropdown.mjs", "../../javascript/shared/beermenus.js", "../../javascript/shared/analytics.js"], "sourcesContent": ["import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"section\", \"expanded\", \"content\", \"collapse\"]\n\n async connect() {\n await Accordion.import()\n this.initializeAccordion()\n }\n\n collapse(event) {\n event.preventDefault()\n\n const index = this.collapseTargets.indexOf(event.currentTarget)\n this.$accordions[index].accordion(\"option\", \"active\", false)\n this.scrollTo(this.$accordions[index])\n }\n\n // private\n\n initializeAccordion() {\n this.$accordions = []\n\n this.sectionTargets.forEach((section, index) => {\n // 0 expands the first element, the only one in this case.\n const active = this.expandedTargets[index].value === \"true\" ? 0 : false\n\n const accordion = $(section).accordion({\n header: \".accordion-tab\",\n autoHeight: false,\n collapsible: true,\n heightStyle: \"content\",\n active: active,\n animate: this.animations,\n icons: this.icons,\n beforeActivate: this.beforeActivate.bind(this),\n activate: this.activate.bind(this)\n })\n this.$accordions[index] = accordion\n })\n\n this.contentTargets.forEach(el => el.classList.remove(\"hidden\"))\n }\n\n beforeActivate(event, ui) {\n BeerMenus.Checklists.closeDriver()\n\n if (ui.newHeader.length) {\n this.scrollTo(ui.newHeader)\n }\n }\n\n activate(event, ui) {\n const expandedIndex = this.contentTargets.indexOf(ui.newPanel[0])\n if (expandedIndex >= 0) {\n this.expandedTargets[expandedIndex].value = true\n }\n\n const collapsedIndex = this.contentTargets.indexOf(ui.oldPanel[0])\n if (collapsedIndex >= 0) {\n this.expandedTargets[collapsedIndex].value = false\n }\n }\n\n scrollTo(header) {\n const scrollTop = header.offset().top +\n ($(\".accordion-scroll-window\").scrollTop() || 0)\n const offset = parseInt(this.data.get(\"offset\")) || 0\n\n if ($(this.element).hasClass('no-body-scroll')){\n $(\".accordion-scroll-window\").animate(\n { scrollTop: scrollTop - offset },\n this.animationDuration,\n \"easeOutQuad\"\n )\n }\n\n else {\n $(\".accordion-scroll-window,html,body\").animate(\n { scrollTop: scrollTop - offset },\n this.animationDuration,\n \"easeOutQuad\"\n )\n }\n }\n\n get animations() {\n return {\n easing: \"easeInOutQuint\",\n duration: this.animationDuration,\n down: {\n easing: \"easeInOutQuart\",\n duration: this.animationDuration\n }\n }\n }\n\n get icons() {\n if (this.data.has(\"icon\") && this.data.has(\"iconActive\")){\n return {\n \"header\": this.data.get(\"icon\"),\n \"activeHeader\": this.data.get(\"iconActive\")\n }\n }\n\n else {\n return {\n \"header\": \"pure-icon pure-icon-angle-down\",\n \"activeHeader\": \"pure-icon pure-icon-angle-up\"\n }\n }\n }\n\n get animationDuration() {\n return 850\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\";\n\nexport default class extends Controller {\n connect() {\n this.element.addEventListener(\"sl-show\", (event) => {\n setTimeout(\n () => event.target.scrollIntoView({ behavior: \"smooth\" }),\n 300\n );\n if (event.target.localName === \"sl-details\") {\n [...this.element.querySelectorAll(\"sl-details\")].map(\n (details) => (details.open = event.target === details)\n );\n }\n });\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"beer\", \"producer\", \"styleSelect\", \"actions\", \"warning\", \"error\"]\n\n connect() {\n $(this.element).on(\"ajax:beforeSend\", this.beforeSend.bind(this))\n $(this.element).on(\"ajax:success\", this.success.bind(this))\n $(this.element).on(\"ajax:error\", this.error.bind(this))\n }\n\n changeProductType(event) {\n const type = event.currentTarget.value\n\n this.styleSelectTargets.forEach(select => {\n const disabled = select.dataset.type != type\n select.classList.toggle(\"hidden\", disabled)\n select.disabled = disabled\n })\n\n this.producerTargets.forEach(target => {\n const disabled = target.dataset.type != type\n target.classList.toggle(\"hidden\", disabled)\n\n const producerIDInput = target.querySelector(\"input[type=hidden]\")\n if (producerIDInput) {\n producerIDInput.disabled = disabled\n }\n })\n }\n\n // private\n\n beforeSend() {\n this.beerTarget.classList.remove(\"box-shadow-left-green\")\n this.actionsTarget.classList.remove(\"box-shadow-right-green\")\n\n this.beerTarget.classList.remove(\"box-shadow-left-red\")\n this.actionsTarget.classList.remove(\"box-shadow-right-red\")\n\n this.errorTarget.classList.add(\"hidden\")\n }\n\n success(event, data, status, xhr) {\n if (xhr.getResponseHeader(\"SUCCESS\") == \"true\") {\n this.replaceHTML(data)\n this.noteRemovedDuplicates(xhr.getResponseHeader(\"DUPLICATE_IDS\"))\n } else {\n this.scrollToElement()\n this.replaceHTML(data)\n }\n }\n\n error() {\n this.scrollToElement()\n\n this.beerTarget.classList.add(\"box-shadow-left-red\")\n this.actionsTarget.classList.add(\"box-shadow-right-red\")\n this.errorTarget.classList.remove(\"hidden\")\n }\n\n replaceHTML(html) {\n this.element.outerHTML = html\n }\n\n noteRemovedDuplicates(duplicateIDsJSON) {\n if (duplicateIDsJSON) {\n JSON.parse(duplicateIDsJSON).forEach(id => {\n const form = document.querySelector(`[data-id='${id}']`)\n if (form) {\n const inputs = form.elements\n for (var i = 0; i < inputs.length; i++) {\n inputs[i].disabled = true\n }\n\n form.querySelector(\"[data-admin-beer-target='warning']\")\n .classList.remove(\"hidden\")\n form.querySelector(\"[data-admin-beer-target='beer']\")\n .classList.add(\"box-shadow-left-yellow\")\n form.querySelector(\"[data-admin-beer-target='actions']\")\n .classList.add(\"box-shadow-right-yellow\")\n }\n })\n }\n }\n\n scrollToElement() {\n $(\"html, body\").animate({\n scrollTop: $(this.element).offset().top\n }, \"normal\");\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"keeperID\"]\n\n keep(event) {\n event.preventDefault()\n\n this.keeperIDTarget.value = event.currentTarget.dataset.id\n\n const keeper = document.querySelector(`.${this.keeperClass}`)\n if (keeper) {\n keeper.classList.remove(this.keeperClass)\n }\n event.currentTarget.classList.add(this.keeperClass)\n }\n\n // private\n\n get keeperClass() {\n return \"keeper\"\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"form\" ]\n\n connect() {\n this.submitOnChange()\n this.submitOnEvent()\n\n $(this.formTarget).on(\"ajax:success\", this.success.bind(this))\n $(this.formTarget).on(\"ajax:error\", this.error.bind(this))\n }\n\n submitForm(event) {\n if (this.formTarget.dataset.turbo === \"true\") {\n this.formTarget.requestSubmit(this.formTarget.querySelector(\"button[type='submit']\"))\n } else {\n $.rails.fire($(this.formTarget), \"submit\")\n }\n }\n\n // private\n\n submitOnChange() {\n [...this.formTarget.elements].forEach(element => {\n if (!element.dataset.ignore) {\n element.addEventListener(\"change\", this.submitForm.bind(this))\n }\n })\n }\n\n submitOnEvent() {\n document.body.addEventListener(\"sortable:didSort\",\n this.submitForm.bind(this))\n\n document.body.addEventListener(\"customFont:selected\",\n this.submitForm.bind(this))\n\n document.body.addEventListener(\"sl-change\",\n this.submitForm.bind(this))\n\n document.body.addEventListener(\"cme-blur\",\n this.submitForm.bind(this))\n }\n\n success(event, data, status, xhr) {\n this.submitOnChange()\n }\n\n error(event, xhr) {\n console.log(\"ERROR, status: \", xhr.status)\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"textfield\"]\n\n connect() {\n if (!Browser.isIE()) {\n this.textfieldTarget.style.resize = \"none\"\n this.defaultRows = this.textfieldTarget.rows\n this.textChanged()\n } else {\n this.textfieldTarget.rows = 3\n }\n }\n\n textChanged() {\n if (!Browser.isIE()) {\n this.textfieldTarget.rows = this.defaultRows\n const rows = Math.ceil(this.textfieldTarget.scrollHeight / this.lineHeight)\n this.textfieldTarget.rows = Math.min(rows, this.maxRows)\n }\n }\n\n // private\n\n get lineHeight() {\n return 25\n }\n\n get maxRows() {\n return 6\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"search\", \"field1\", \"field2\" ]\n\n async connect() {\n let libraries = await AlgoliaSource.importLibraries()\n this.source = new AlgoliaSource(libraries[0], this.data.get(\"index\")).source\n\n $(this.searchTarget).autocomplete({ autoselect: true }, [{\n source: this.source,\n displayKey: (obj) => { return obj.name },\n templates: { suggestion: this.suggestion },\n }]).on(\"autocomplete:selected\", this.selected.bind(this))\n }\n\n // private\n\n suggestion(hit) {\n return `
${hit.name}
`\n }\n\n selected(event, suggestion, dataset, context) {\n if (this.hasField1Target && this.field1 && suggestion[this.field1]) {\n this.field1Target.value = suggestion[this.field1]\n }\n\n if (this.hasField2Target && this.field2 && suggestion[this.field2]) {\n this.field2Target.value = suggestion[this.field2]\n }\n }\n\n get field1() {\n return this.data.get(\"field1\")\n }\n\n get field2() {\n return this.data.get(\"field2\")\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"availableCheckbox\"]\n\n clickedComingSoon(event) {\n event.preventDefault()\n this.availableCheckboxTarget.checked = true\n\n $(\"#coming-soon-promo\").modal()\n BeerMenus.Analytics.track(\"Viewed coming soon um modal\", {\n \"pro promo page\": \"Edit menu\",\n \"Pro promo feature\": \"Coming Soon\"\n })\n }\n\n clickedPrivate(event) {\n event.preventDefault()\n this.availableCheckboxTarget.checked = true\n\n $(\"#private-promo\").modal()\n BeerMenus.Analytics.track(\"Viewed private um modal\", {\n \"pro promo page\": \"Edit menu\",\n \"Pro promo feature\": \"Private\"\n })\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static values = { messageId: String }\n\n open(event) {\n event.preventDefault()\n\n this.target.Beacon(\"open\")\n this.target.Beacon(\"navigate\", \"/ask\")\n }\n\n prefill(event) {\n event.preventDefault()\n\n this.target.Beacon(\"open\")\n this.target.Beacon(\"navigate\", \"/ask/message/\")\n this.target.Beacon(\"prefill\", {\n name: this.data.get(\"name\"),\n email: this.data.get(\"email\"),\n subject: this.data.get(\"subject\"),\n text: this.data.get(\"text\")\n })\n }\n\n showMessage(event) {\n event.preventDefault()\n this.target.Beacon(\"show-message\", this.messageIdValue, { delay: 1, force: true })\n }\n\n // private\n\n get target() {\n return parent ? parent : window\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n connect() {\n this.state = \"closed\"\n\n document.addEventListener(\"tab:changed\", (event) => {\n this.tabChanged(event.detail)\n })\n }\n\n // private\n\n tabChanged(tab) {\n if (tab == this.productName.toLowerCase()) {\n this.searchTarget.nextSibling.focus()\n }\n }\n\n get limit() {\n return parseInt(this.data.get(\"limit\")) || 10\n }\n\n get barID() {\n return this.data.get(\"bar-id\")\n }\n\n get productType() {\n return this.data.get(\"product-type\")\n }\n\n get productName() {\n return this.data.get(\"product-name\")\n }\n}\n", "import ProductAutocompleteController from \"./product-autocomplete-controller\"\n\nexport default class extends ProductAutocompleteController {\n static targets = [\"beerID\", \"beerName\", \"container\", \"description\", \"beerStyle\", \"beerAbv\",\n \"metaDataContainer\", \"descriptionContainer\", \"descriptionRevert\", \"styleRevert\", \"abvRevert\",\n \"modal\", \"search\", \"submit\", \"suggestions\", \"template\"]\n\n static values = {\n hasGlobalDescription: Boolean,\n styleId: Number,\n abv: Number,\n skipFocus: Boolean\n }\n\n async connect() {\n let libraries = await AlgoliaSource.importLibraries()\n const filter = `product_type = ${this.productType}`\n this.algolia = new AlgoliaSource(libraries[0], \"Beer\", filter)\n this.showDescriptionRevertTarget = this.hasGlobalDescriptionValue != \"false\"\n this.connected()\n }\n\n populate(id, name, style_id, abv) {\n this.beerIDTarget.value = id\n this.search.val(name)\n\n this.descriptionTarget.value = \"\"\n this.fetchDescription(id, true)\n\n const data = {\n beer_style_id: style_id,\n abv: abv\n }\n this.setStyleAndAbv(data)\n\n if (this.validateSelection()) {\n this.containerTarget.focus()\n }\n }\n\n showNewBeerModal(event) {\n event && event.preventDefault()\n this.algolia.index.clearCache()\n\n $.ajax({\n url: \"/beers/new.js\",\n context: this,\n data: {\n name: this.search.val(),\n product_type: this.productType,\n bar_id: this.barID,\n edit: this.edit,\n modal: true\n }\n })\n .fail((jqXHR, status, error) => console.error(error))\n }\n\n suggestionsModalClosed() {\n this.validateSelection()\n }\n\n revertDescription(event) {\n event.preventDefault()\n\n $.ajax({\n url: this.descriptionURL(this.beerIDTarget.value),\n data: {\n default: true\n },\n dataType: \"json\"\n }).done(data => {\n this.descriptionTarget.value = data.description || \"\"\n this.descriptionRevertTarget.classList.add(\"hidden\")\n this.triggerInputEvent()\n })\n }\n\n revertStyle(event) {\n event.preventDefault()\n this.beerStyleTarget.value = this.styleIdValue\n $(this.beerStyleTarget).trigger('change')\n this.styleRevertTarget.classList.add(\"hidden\")\n }\n\n revertAbv(event) {\n event.preventDefault()\n this.beerAbvTarget.value = this.abvValue\n this.abvRevertTarget.classList.add(\"hidden\")\n }\n\n get skipEmptySuggestionsModal() {\n return this.data.get(\"skip-empty-suggestions-modal\") == \"true\"\n }\n\n // private\n\n connected() {\n this.initializeSearch()\n\n this.search.focus(event => this.searchQuery = event.currentTarget.value)\n\n if (!this.skipFocusValue) {\n this.searchTarget.nextSibling.focus()\n }\n\n this.suggestions = []\n\n document.body.addEventListener(\"skip-empty-suggestions-modal-change\", (event) => {\n this.data.set(\"skip-empty-suggestions-modal\", event.detail)\n })\n\n this.addRevertListener(\"keyup\", this.descriptionTarget, this.descriptionRevertTarget, this.showDescriptionRevertTarget)\n this.addRevertListener(\"input\", this.beerAbvTarget, this.abvRevertTarget, true)\n\n $(this.beerStyleTarget).on('select2:select', (e) => {\n if (this.beerStyleTarget.value != this.styleIdValue) {\n this.styleRevertTarget.classList.remove(\"hidden\")\n }\n })\n\n this.firstNoResultsKeystroke = true\n\n super.connect()\n }\n\n addRevertListener(listener, target, revertTarget, showMethod) {\n target.addEventListener(listener, () => {\n if (showMethod) {\n revertTarget.classList.remove(\"hidden\")\n }\n })\n }\n\n initializeSearch() {\n this.search = $(this.searchTarget).autocomplete(this.options, this.dataset)\n\n this.search\n .on(\"autocomplete:selected autocomplete:autocompleted\", (event, data) => {\n this.state = data.cssClass == this.addNewBeerClass ? \"new\" : \"existing\"\n this.containerTarget.focus()\n\n if (data.objectID) {\n this.setHiddenField(data.objectID)\n this.fetchDescription(data.objectID)\n this.setStyleAndAbv(data)\n }\n })\n .on(\"autocomplete:updated\", event => {\n if (event.currentTarget.value != this.searchQuery) {\n this.clearJavaScriptMessages()\n }\n })\n .on(\"autocomplete:closed\", () => {\n // \"Delay\" so modal:willShow event fires after any other clicks.\n setTimeout(() => { this.state = \"closed\" }, 1)\n })\n }\n\n setHiddenField(id) {\n if (this.hasBeerIDTarget && this.state != \"new\") {\n this.beerIDTarget.value = id\n }\n }\n\n setStyleAndAbv(data) {\n if (this.hasBeerStyleTarget) {\n this.beerStyleTarget.value = data.beer_style_id\n // Trigger change event to update the select2 dropdown\n $(this.beerStyleTarget).trigger('change')\n this.styleIdValue = data.beer_style_id\n this.metaDataContainerTarget.classList.remove(\"hidden\")\n }\n if (this.hasBeerAbvTarget) {\n this.beerAbvTarget.value = data.abv\n this.abvValue = data.abv\n }\n }\n\n validateSelection() {\n if (this.search.val() && !this.beerIDTarget.value) {\n new Servings(this.productType, this.edit).showMissingBeerError()\n return false\n }\n return true\n }\n\n clearJavaScriptMessages() {\n new Servings(this.productType, this.edit).clearJavaScriptMessages()\n }\n\n clearAndHideDescription() {\n this.descriptionTarget.value = \"\"\n this.descriptionContainerTarget.classList.add(\"hidden\")\n }\n\n clearAndHideMetaData() {\n this.beerStyleTarget.value = \"\"\n this.styleIdValue = \"\"\n this.beerAbvTarget.value = \"\"\n this.abvValue = \"\"\n this.metaDataContainerTarget.classList.add(\"hidden\")\n }\n\n source(query, callback, isBeerIndex) {\n this.clearAndHideDescription()\n this.clearAndHideMetaData()\n\n this.algolia.source(query, (suggestions) => {\n suggestions = suggestions.slice(0, this.limit)\n this.suggestions = suggestions\n\n if (suggestions.length === 0 && this.firstNoResultsKeystroke) {\n BeerMenus.Analytics.track(\"Viewed add item to menu no results\", { \"item type\": `${this.productName}` })\n this.firstNoResultsKeystroke = false\n }\n\n suggestions.push({\n name: `${this.productName} not listed? Add it to the database`,\n cssClass: this.addNewBeerClass,\n query: query\n })\n return callback(suggestions)\n })\n }\n\n displayKey(obj) {\n return obj.cssClass == this.addNewBeerClass ? obj.query : obj.name\n }\n\n suggestion(hit) {\n return new BeerAutocompleteSuggestion(this.templateTarget).build(hit)\n }\n\n showSuggestionsModal() {\n const event = new CustomEvent(\"modal:willShow\", {\n bubbles: true,\n cancelable: true,\n })\n\n if (this.element.dispatchEvent(event)) {\n const beerSuggestionsController = this.application\n .getControllerForElementAndIdentifier(this.suggestionsTarget, \"beer-suggestions\")\n beerSuggestionsController.fetch(this.search.val(), this, this.productType)\n BeerMenus.Analytics.track(\"Viewed not in database modal\", { \"item type\": `${this.productName}` })\n }\n }\n\n tabChanged(tab) {\n if (tab == this.productName.toLowerCase()) {\n this.searchTarget.nextSibling.focus()\n }\n }\n\n fetchDescription(beerID, fullDescription = false) {\n this.submitTarget.disabled = true\n\n $.ajax({\n url: this.descriptionURL(beerID),\n data: {\n full: fullDescription\n },\n dataType: \"json\"\n }).done(data => {\n this.descriptionTarget.value = data.description || \"\"\n this.showDescriptionRevertTarget = data.default_exists\n this.descriptionRevertTarget.classList\n .toggle(\"hidden\", !(data.customized && this.showDescriptionRevertTarget))\n\n this.descriptionContainerTarget.classList.remove(\"hidden\")\n this.triggerInputEvent()\n }).always(() => this.submitTarget.disabled = false )\n }\n\n descriptionURL(beerID) {\n return `/places/${this.barID}/beer_descriptions/${beerID}`\n }\n\n triggerInputEvent() {\n if (this.showDescriptionRevertTarget && !Browser.isIE()) {\n const inputEvent = new Event(\"input\", { bubbles: true })\n this.descriptionTarget.dispatchEvent(inputEvent)\n }\n }\n\n get addNewBeerClass() {\n return \"x-add-new-beer\"\n }\n\n get dataset() {\n return {\n source: (query, callback) => { this.source(query, callback) },\n name: \"beers\",\n displayKey: this.displayKey.bind(this),\n templates: { suggestion: this.suggestion.bind(this) },\n }\n }\n\n set state(val) {\n if (val == \"closed\" && this._state) {\n if (this._state == \"new\") {\n this.beerIDTarget.value = null\n this.clearAndHideDescription()\n this.clearAndHideMetaData()\n this.showNewBeerModal()\n } else if (this._state != \"existing\") {\n this.beerIDTarget.value = null\n this.clearAndHideDescription()\n this.clearAndHideMetaData()\n\n if (this.search.val()) {\n const matchedSuggestion = this.matchedSuggestion\n if (matchedSuggestion) {\n this.search.val(matchedSuggestion.name)\n this.beerIDTarget.value = matchedSuggestion.objectID\n } else {\n this.showSuggestionsModal()\n }\n }\n }\n }\n this._state = val\n }\n\n get matchedSuggestion() {\n const query = this.search.val().toLowerCase()\n return this.suggestions.find(suggestion => {\n return suggestion.name.toLowerCase() === query\n })\n }\n\n get barID() {\n return this.data.get(\"bar-id\")\n }\n\n get edit() {\n return this.data.get(\"edit\") === \"true\"\n }\n\n get options() {\n return {\n autoselect: true\n }\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"description\" ]\n\n connect() {\n this.element.addEventListener(\"copy\", this.copy.bind(this))\n }\n\n copyDescription() {\n const text = this.descriptionTargets.map(el => el.textContent.trim()).join(\" \")\n this.copyTextToClipboard(text)\n this.copy()\n }\n\n // private\n\n copy(event) {\n BeerMenus.Analytics.track(\"Copied beer meta data on desktop\")\n\n const modal = $(\"#print-menu\")\n if (modal.length) {\n modal.modal()\n BeerMenus.Analytics.track(\"Viewed copied beer info print menu promo\")\n }\n }\n\n copyTextToClipboard(text) {\n const textarea = document.createElement(\"textarea\")\n textarea.value = text\n document.body.appendChild(textarea)\n textarea.select()\n document.execCommand(\"copy\")\n document.body.removeChild(textarea)\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"suggestions\", \"template\", \"withSuggestions\", \"noSuggestions\"]\n\n async connect() {\n let libraries = await AlgoliaSource.importLibraries()\n this.algolia = new AlgoliaSource(libraries[0], \"Beer\")\n }\n\n fetch(query, controller, productType) {\n this.beerAutocompleteController = controller\n this.reset()\n\n const searchQuery = {\n query: query,\n filters: `product_type = ${productType}`,\n hitsPerPage: this.limit\n }\n this.algolia.index.search(searchQuery).then(result => {\n if (result && result.hits && result.hits.length) {\n this.populateSuggestions(result.hits)\n $(this.element).modal()\n } else if (controller.skipEmptySuggestionsModal) {\n controller.showNewBeerModal()\n } else {\n this.noSuggestionsTargets.forEach(t => t.classList.remove(\"hidden\"))\n $(this.element).modal()\n }\n\n $(this.element).one(\"hidden.bs.modal\", this.modalHidden.bind(this))\n })\n }\n\n select(event) {\n event.preventDefault()\n\n const id = event.currentTarget.dataset[\"id\"]\n const name = event.currentTarget.dataset[\"name\"]\n this.beerAutocompleteController.populate(id, name)\n\n $(this.element).modal(\"hide\")\n }\n\n addNewBeer(event) {\n event.preventDefault()\n\n $(this.element).modal(\"hide\")\n this.beerAutocompleteController.showNewBeerModal()\n }\n\n // private\n\n suggestion(hit) {\n const suggestion = this.templateTarget.cloneNode(true)\n suggestion.classList.remove(\"hidden\")\n suggestion.classList.add(hit.cssClass)\n\n const anchor = suggestion.querySelector(\"[data-ref='anchor']\")\n anchor.dataset[\"id\"] = hit.objectID\n anchor.dataset[\"name\"] = hit.name\n anchor.dataset[\"action\"] = \"beer-suggestions#select\"\n\n suggestion.querySelector(\"[data-ref='name']\").textContent = hit.name\n\n const meta = new BeerMetadata(hit).toString()\n suggestion.querySelector(\"[data-ref='meta']\").textContent = meta\n\n return suggestion\n }\n\n reset() {\n this.suggestionsTarget.innerHTML = \"\"\n this.withSuggestionsTargets.forEach(t => t.classList.add(\"hidden\"))\n this.noSuggestionsTargets.forEach(t => t.classList.add(\"hidden\"))\n }\n\n populateSuggestions(hits) {\n hits.forEach(hit => {\n this.suggestionsTarget.appendChild(this.suggestion(hit))\n })\n this.withSuggestionsTargets.forEach(t => t.classList.remove(\"hidden\"))\n }\n\n modalHidden() {\n this.beerAutocompleteController.suggestionsModalClosed()\n }\n\n get limit() {\n return parseInt(this.data.get(\"limit\")) || 10\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n closeAndFocusServingForm(event) {\n event.preventDefault()\n $(this.element).modal(\"hide\")\n $(\".aa-input\").first().focus()\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"footer\", \"loadingOverlay\" ]\n\n async connect() {\n this.element.controller = this\n await import(\"../models/state-manager.js\")\n }\n\n disconnect() {\n clearTimeout(this.autosaveTimer)\n }\n\n get stateManager() {\n return this.element.querySelector(\"bmu-state-manager\")\n }\n\n get $modal() {\n return $(this.element.querySelector(\":scope > .modal\"))\n }\n\n set loading(isLoading) {\n this.loadingOverlayTarget.classList.toggle(\"is-shown\", isLoading)\n }\n\n set nonImageElementsHidden(isHidden) {\n const section = this.stateManager.querySelector(\".modal-body\")\n\n this.footerTarget.hidden = isHidden\n Array.from(section.children).forEach(el => {\n if (el.dataset.controller != \"image-editor\") el.hidden = isHidden\n })\n }\n\n async openModal(profileId, region, position = \"center\") {\n clearTimeout(this.autosaveTimer)\n\n const src = `${this.data.get(\"src\")}?region=${region}&position=${position}`\n\n const response = await fetch(src)\n const partial = await response.text()\n\n if (this.$modal.get(0) && this.$modal.get(0).style.display == \"block\") {\n this.$modal.removeClass(\"fade\")\n this.$modal.modal(\"hide\")\n this.element.innerHTML = partial\n this.$modal.removeClass(\"fade\") // remove it again with the new partial\n } else {\n this.element.innerHTML = partial\n }\n\n this.stateManager.stateData.profileId = profileId\n this.stateManager.stateData.region = region\n this.stateManager.stateData.position = position\n \n this.stateManager.stateData.minimalSaveOperation = true\n this.$modal.modal(\"show\")\n\n this.$modal.one(\"hidden.bs.modal\", this.hideCallback.bind(this))\n\n setTimeout(() => this.$modal.addClass(\"fade\"), 500)\n\n this.autosaveTimer = setInterval(() => {\n this.autosave()\n }, 2000)\n }\n\n handleStateChange() {\n // not currently used\n }\n\n get isEditingTab() {\n return this.stateManager.current == \"text\" || this.stateManager.current == \"edit_image\"\n }\n\n hideCallback() {\n (iframe => iframe.src = iframe.src)(document.querySelector(\"[data-tv-preview-target='preview']\"))\n }\n\n autosave() {\n if (this.stateManager.current == \"text\") {\n const newContent = this.element.querySelector(\"#tv_menu_block_content\").value\n if (newContent != this.stateManager.currentData.content) {\n this.element.querySelector(\"[data-form-submit]\").click()\n }\n this.stateManager.currentData.content = newContent\n }\n }\n\n startWithText() {\n this.stateManager.current = \"text\"\n this.stateManager.stateData.minimalSaveOperation = true\n }\n\n startWithImage() {\n this.element.querySelector(\"input[type='file']\").click()\n this.stateManager.stateData.minimalSaveOperation = false\n }\n\n saveUploadedImage() {\n this.element.querySelector(\"[data-image-submit]\").click()\n }\n\n saveForm(event) {\n event.preventDefault()\n const form = new FormData(event.target)\n\n form.append(\"profile_id\", this.stateManager.stateData.profileId)\n form.append(\"tv_menu_block[region]\", this.stateManager.stateData.region)\n form.append(\"tv_menu_block[position]\", this.stateManager.stateData.position)\n\n if (!this.stateManager.stateData.minimalSaveOperation) this.loading = true\n\n fetch(event.target.action, { method: event.target.method, body: form })\n .then(res => res.json())\n .then(json => {\n this.loading = false\n\n if (this.stateManager.stateData.minimalSaveOperation) {\n ;(iframe => iframe.src = iframe.src)(this.element.querySelector(\"iframe\"))\n\n if (!event.target.querySelector(\"[name='_method']\")) {\n this.element.querySelectorAll(\"form\").forEach(formEl => {\n const patchMethod = document.createElement(\"input\")\n patchMethod.type = \"hidden\"\n patchMethod.name = \"_method\"\n patchMethod.value = \"patch\"\n formEl.append(patchMethod)\n formEl.action = formEl.action + `/${json.id}`\n })\n this.stateManager.dataset.blockId = json.id\n }\n } else {\n this.openModal(this.stateManager.stateData.profileId, this.stateManager.stateData.region, this.stateManager.stateData.position)\n }\n })\n .catch(err => {\n console.error(err)\n this.loading = false\n })\n }\n\n async deleteBlock(id) {\n this.stateManager.stateData.minimalSaveOperation = false\n this.loading = true\n \n const baseUrl = this.stateManager.dataset.blocksUrl\n const url = `${baseUrl}/${id}`\n const authenticityToken = $(\"meta[name=csrf-token]\").prop(\"content\")\n const form = new FormData()\n form.append(\"authenticity_token\", authenticityToken)\n await fetch(url, { method: \"DELETE\", body: form })\n\n await this.openModal(this.stateManager.stateData.profileId, this.stateManager.stateData.region, this.stateManager.stateData.position)\n }\n\n async graphicToText(event) {\n await this.deleteBlock(this.stateManager.dataset.blockId)\n this.startWithText()\n }\n\n switchLeft(event) {\n event && event.preventDefault()\n this.openModal(this.stateManager.stateData.profileId, this.stateManager.stateData.region, \"left\")\n }\n\n switchCenter(event) {\n event && event.preventDefault()\n this.openModal(this.stateManager.stateData.profileId, this.stateManager.stateData.region, \"center\")\n }\n\n switchRight(event) {\n event && event.preventDefault()\n this.openModal(this.stateManager.stateData.profileId, this.stateManager.stateData.region, \"right\")\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"search\", \"breweryID\", \"error\", \"beerName\"]\n\n async connect() {\n let libraries = await AlgoliaSource.importLibraries()\n const producer = `producer_type = ${this.producerType}`\n this.algolia = new AlgoliaSource(libraries[0], \"Brewery\", producer)\n this.connected()\n }\n\n populate(id, name) {\n this.breweryIDTarget.value = id\n this.search.val(name)\n }\n\n showNewBreweryModal(eventOrShowMessage) {\n var showMessage = false\n if (eventOrShowMessage == true) {\n showMessage = true\n } else if (eventOrShowMessage) {\n eventOrShowMessage.preventDefault()\n }\n\n window.BeerMenus.controllers.breweryAutocompleteController = this\n this.algolia.index.clearCache()\n this.breweryIDTarget.value = null\n\n $(\"#new-beer\").modal(\"hide\")\n\n $.ajax(\"/breweries/new.js\", {\n data: {\n name: this.search.val(),\n producer_type: this.producerType,\n source: this.data.get(\"source\"),\n show_message: showMessage,\n },\n dataType: \"text\" // Don't evaluate response script, handle in showModal().\n }).done(this.showModal.bind(this))\n }\n\n // private\n\n connected() {\n this.suggestions = []\n this.search = $(this.searchTarget).autocomplete(this.options, this.dataset)\n .on(\"autocomplete:selected autocomplete:autocompleted\", this.selected.bind(this))\n .on(\"autocomplete:updated\", this.hideError.bind(this))\n .on(\"autocomplete:closed\", () => this.state = \"closed\")\n }\n\n selected(event, data) {\n if(data.cssClass == this.addNewBreweryClass) {\n this.state = \"new\"\n this.breweryIDTarget.value = null\n this.showNewBreweryModal()\n } else {\n this.state = \"existing\"\n this.breweryIDTarget.value = data.objectID\n\n // Check if short name is at the start of beer name and remove it if it is\n if (this.beerNameTarget.value.startsWith(data.short_name)) {\n this.beerNameTarget.value = this.beerNameTarget.value.replace(data.short_name, '').trim()\n }\n }\n }\n\n showModal(html) {\n BeerMenus.Modals.insert(html, \"#new-brewery\")\n BeerMenus.InputFocuser.focus(\"#new-brewery #brewery_name\")\n\n $(\"#new-brewery\").one(\"hidden.bs.modal\", () => {\n $(\"#new-beer\").modal()\n this.validateSelection()\n })\n }\n\n hideError() {\n if (this.hasErrorTarget) {\n this.errorTarget.classList.add(\"hidden\")\n }\n }\n\n validateSelection() {\n if (this.search.val() && !this.breweryIDTarget.value) {\n this.errorTarget.classList.remove(\"hidden\")\n }\n }\n\n source(query, callback) {\n this.algolia.source(query, (suggestions) => {\n this.suggestions = suggestions\n suggestions.push({\n name: `${this.producerName} not listed? Add it here`,\n cssClass: this.addNewBreweryClass,\n query: query\n })\n return callback(suggestions)\n })\n }\n\n displayKey(obj) {\n return obj.cssClass == this.addNewBreweryClass ? obj.query : obj.name\n }\n\n suggestion(hit) {\n return `${hit.name}
`\n }\n\n get addNewBreweryClass() {\n return \"x-add-new-brewery\"\n }\n\n get options() {\n return {\n autoselect: true\n }\n }\n\n get dataset() {\n return {\n name: \"breweries\",\n source: this.source.bind(this),\n displayKey: this.displayKey.bind(this),\n templates: { suggestion: this.suggestion }\n }\n }\n\n get producerType() {\n return this.data.get(\"producer-type\")\n }\n\n get producerName() {\n return this.data.get(\"producer-name\")\n }\n\n set state(val) {\n if (val == \"closed\" && this._state != \"new\" && this._state != \"existing\") {\n if (this.search.val()) {\n const matchedSuggestion = this.matchedSuggestion\n if (matchedSuggestion) {\n this.search.val(matchedSuggestion.name)\n this.breweryIDTarget.value = matchedSuggestion.objectID\n } else {\n this.showNewBreweryModal(true)\n }\n }\n }\n this._state = val\n }\n\n get matchedSuggestion() {\n const query = this.search.val().toLowerCase()\n return this.suggestions.find(suggestion => {\n return suggestion.name.toLowerCase() === query\n })\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"input\", \"result\", \"selection\"]\n\n async connect() {\n await this._importLibraries()\n\n let libraries = await AlgoliaSource.importLibraries()\n this.algolia = new AlgoliaSource(libraries[0], \"Brewery\", \"brewery\")\n this._initializeSelect2()\n this._selectBreweries()\n }\n\n async _importLibraries() {\n (await import(\"select2/dist/js/select2.full.js\")).default() // init the plugin\n }\n\n _initializeSelect2() {\n $(this.inputTarget).select2({\n ajax: {\n transport: this._transport.bind(this),\n data: this._data,\n processResults: this._processResults\n },\n escapeMarkup: this._escapeMarkup,\n minimumInputLength: 0,\n cache: false,\n templateResult: this._templateResult.bind(this),\n templateSelection: this._templateSelection.bind(this),\n multiple: true,\n language: this._language()\n })\n }\n\n _selectBreweries() {\n const input = $(this.inputTarget)\n\n if (this.data.get(\"breweries\")) {\n const breweries = JSON.parse(this.data.get(\"breweries\"))\n\n breweries.forEach(brewery => {\n const option = new Option(brewery.name, brewery.id, true, true)\n input.append(option).trigger(\"change\")\n })\n }\n\n input.trigger({type: \"select2:select\"})\n }\n\n _transport(params, success, failure) {\n let queryParams = params.data\n let query = queryParams.query\n delete queryParams.query\n this.algolia.index.search(query, queryParams).then(success, failure)\n }\n\n _data(params) {\n return {\n query: params.term,\n hitsPerPage: 10,\n page: (params.page || 1) - 1\n }\n }\n\n _processResults(data) {\n return {\n results: data.hits.map(hit => ({\n id: hit.objectID,\n text: hit.name\n })),\n pagination: {\n more: data.page + 1 < data.nbPages\n }\n }\n }\n\n _escapeMarkup(markup) {\n return markup\n }\n\n _templateResult(brewery) {\n const result = this.resultTarget.cloneNode(true)\n result.classList.remove(\"hidden\")\n result.querySelector(\".brewery-name\").textContent = brewery.text\n return result\n }\n\n _templateSelection(brewery) {\n const result = this.selectionTarget.cloneNode(true)\n result.classList.remove(\"hidden\")\n result.querySelector(\".brewery-name\").textContent = brewery.text\n return result\n }\n\n // https://github.com/select2/select2/blob/master/src/js/select2/i18n/en.js\n _language() {\n return {\n inputTooShort: function () {\n return \"Start typing brewery name...\";\n }\n }\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"intersection\", \"container\", \"section\"]\n\n connect() {\n if (this.hasContainerTarget) {\n const observer = new IntersectionObserver(this.toggleBulkMove.bind(this))\n observer.observe(this.intersectionTarget)\n }\n }\n\n toggleBulkMove(entries) {\n const onScreen = entries[0].isIntersecting\n const scrolledPast = entries[0].boundingClientRect.y < 0\n const hide = !onScreen && !scrolledPast\n this.containerTarget.classList.toggle(\"hidden\", hide)\n }\n\n moveTo(event) {\n event.preventDefault()\n\n const servingIDs = this.servingIDs\n if (servingIDs.length) {\n const params = `ids[]=${servingIDs.join(\"&ids[]=\")}`\n $.ajax(`${event.currentTarget.href}?${params}`)\n .done(html => BeerMenus.Modals.insert(html))\n } else {\n alert(\"Oops, you didn't select anything.\")\n }\n }\n\n // private\n\n get servingIDs() {\n var servingIDs = []\n this.sectionTargets.forEach(section => {\n this.application\n .getControllerForElementAndIdentifier(section, \"select-all\")\n .checkboxTargets.forEach(checkbox => {\n if (checkbox.checked) {\n servingIDs.push(...checkbox.value.split(\",\"))\n }\n })\n })\n return servingIDs\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"input\", \"output\", \"views\", \"roi\" ]\n\n connect() {\n this.calculate()\n }\n\n calculate(event) {\n if (event && isNaN(parseInt(event.currentTarget.value))) {\n event.currentTarget.value = null\n return window.alert(\"Enter a number.\")\n }\n\n var output = this.conversion\n this.inputTargets.forEach(el => { output *= parseInt(el.value) })\n this.outputTarget.innerText = output.toFixed(2)\n\n this.viewsTargets.forEach((el, index) => {\n const views = parseInt(el.innerText)\n const roi = output * views\n this.roiTargets[index].innerText = `$${roi.toFixed(0)}`\n })\n }\n\n get conversion() {\n return parseFloat(this.data.get(\"conversion\"))\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n connect() {\n this._insertCss()\n this._insertScript()\n }\n\n _insertCss() {\n const calendlyCss = document.getElementById(\"calendly-css\")\n if (calendlyCss) {\n } else {\n const tag = document.createElement(\"link\")\n tag.id = \"calendly-css\"\n tag.rel = \"stylesheet\"\n tag.media = \"screen\"\n tag.href = \"https://assets.calendly.com/assets/external/widget.css\"\n document.head.appendChild(tag)\n }\n }\n\n _insertScript() {\n const calendlyScript = document.getElementById(\"calendly-js\")\n if (calendlyScript) {\n } else {\n const script = document.createElement(\"script\")\n script.src = \"https://assets.calendly.com/assets/external/widget.js\"\n script.id = \"calendly-js\"\n document.head.appendChild(script)\n }\n }\n\n click() {\n BeerMenus.Analytics.track(\"Clicked Schedule Call\", {\n \"Platform\": this.data.get(\"platform\"),\n \"Logged In\": this.data.get(\"loggedIn\"),\n \"Schedule Call Campaign\": this.data.get(\"campaign\"),\n })\n\n Calendly.showPopupWidget(this.data.get(\"url\"))\n\n $(\"#next-button\").text(\"Continue\")\n }\n\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n async connect() {\n await Promise.all([\n import(\"chartkick\"),\n import(\"chart.js\")\n ])\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"primaryDisplay\", \"secondaryDisplay\", \"primary\", \"secondary\"]\n\n connect() {\n this.checkboxChanged()\n }\n\n checkboxChanged() {\n const primaryCount = this.primaryTargets.filter(cb => cb.checked).length\n this.primaryDisplayTarget.textContent = primaryCount\n\n // Only update secondary if it exists\n if (this.hasSecondaryDisplayTarget) {\n const secondaryCount = this.secondaryTargets.filter(cb => cb.checked).length\n this.secondaryDisplayTarget.textContent = secondaryCount\n }\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"checkbox\", \"form\"]\n\n change(event) {\n this.formTarget.submit()\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"source\", \"hidden\" ]\n\n toggle(event) {\n this.hiddenTargets.forEach(target => {\n if (target.classList.contains(\"hidden\")) {\n target.classList.remove(\"hidden\")\n } else {\n target.classList.add(\"hidden\")\n }\n })\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n async connect() {\n await Accordion.import()\n this.initializeAccordion()\n }\n\n // private\n\n initializeAccordion() {\n $(this.element).accordion({\n active: this.activeChecklistIndex,\n heightStyle: \"content\",\n collapsible: true,\n icons: {\n header: \"pure-icon pure-icon-angle-down\",\n activeHeader: \"pure-icon pure-icon-angle-up\"\n },\n beforeActivate: this.beforeActivate.bind(this),\n })\n }\n\n beforeActivate(event, ui) {\n const expandedIdentifier = ui.newHeader.data(\"identifier\")\n if (expandedIdentifier) { // don't update if closing the only expanded\n $.ajax({\n url: `/places/${this.barID}/menu/preferences/active_checklist`,\n method: \"POST\",\n data: {\n identifier: expandedIdentifier,\n },\n })\n }\n }\n\n get activeChecklistIndex() {\n return parseInt(this.data.get(\"active-checklist-index\")) || 0\n }\n\n get barID() {\n return this.data.get(\"bar-id\")\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"loading\", \"error\" ]\n\n connect() {\n this.fetchChecklists()\n }\n\n reload() {\n this.fetchChecklists()\n }\n\n // private\n\n fetchChecklists() {\n this.showError(false)\n\n $.ajax({\n url: `/places/${this.barID}/checklists/lists.js`,\n error: () => { this.showError(true) },\n })\n }\n\n showError(visible) {\n if (visible) {\n this.loadingTarget.classList.add(\"hidden\")\n this.errorTarget.classList.remove(\"hidden\")\n } else {\n this.loadingTarget.classList.remove(\"hidden\")\n this.errorTarget.classList.add(\"hidden\")\n }\n }\n\n get barID() {\n return this.data.get(\"bar-id\")\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"trigger\", \"card\", \"show\" ]\n\n expand(event) {\n event.preventDefault()\n\n if (this.cardTargets.length > 0) {\n this.cardTargets.forEach(t => {\n t.classList.remove(\"hidden\")\n t.classList.remove(\"collapsed-cards\")\n })\n }\n\n if (this.showTargets.length > 0) {\n this.showTargets.forEach(t => t.classList.remove(\"hidden\"))\n }\n\n if (this.triggerTargets.length > 0) {\n this.triggerTargets.forEach(t => t.classList.toggle(\"hidden\"))\n }\n }\n\n collapse(event) {\n if (this.showTargets.length > 0) {\n this.showTargets.forEach(t => t.classList.add(\"hidden\"))\n }\n\n if (this.triggerTargets.length > 0) {\n this.triggerTargets.forEach(t => t.classList.toggle(\"hidden\"))\n }\n\n if (this.cardTargets.length > 0) {\n this.cardTargets.forEach(target => {\n if (target.querySelector('input[type=radio]:checked')) {\n target.classList.add(\"collapsed-cards\")\n } else {\n target.classList.add(\"hidden\")\n }\n })\n }\n\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"source\", \"successMessage\"]\n static values = { source: String }\n\n copy(event) {\n event.preventDefault()\n navigator.clipboard.writeText(this.sourceValue).then(() => {\n this.showSuccessMessage()\n })\n }\n\n copyValue(event) {\n event.preventDefault()\n navigator.clipboard.writeText(this.sourceTarget.value).then(() => {\n this.showSuccessMessage()\n })\n }\n\n copyText(event) {\n event.preventDefault()\n navigator.clipboard.writeText(this.sourceTarget.innerText).then(() => {\n this.showSuccessMessage()\n })\n }\n\n showSuccessMessage() {\n if (this.hasSuccessMessageTarget) {\n // Remove the 'fade-out' class if it exists to reset the animation\n this.successMessageTarget.classList.remove(\"fade-out\");\n\n // Force a reflow to reset the animation (by accessing offsetWidth)\n void this.successMessageTarget.offsetWidth;\n\n // Add the 'fade-out' class to start the animation again\n this.successMessageTarget.classList.remove(\"hidden\");\n this.successMessageTarget.classList.add(\"fade-out\");\n }\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n // technique pulled from Stimulus Dialog\n close() {\n this.element.setAttribute(\"closing\", \"\")\n\n Promise.all(this.element.getAnimations().map((animation) => animation.finished)).then(() => {\n this.element.remove()\n })\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"editor\", \"field\", \"defaultCSS\", \"alternateCSS\" ]\n\n async connect() {\n await import(\"../models/codemirror-editor.js\")\n\n this.editorTarget.addEventListener(\"cme-change\", (event) => {\n this.fieldTarget.value = event.detail\n })\n }\n\n reset(event) {\n event.preventDefault()\n this.editorTarget.value = this.defaultCSSTarget.innerText\n }\n\n resetAlternate(event) {\n event.preventDefault()\n this.editorTarget.value = this.alternateCSSTarget.innerText\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"collapsed\", \"expanded\", \"arrowToggle\" ]\n\n toggle(event) {\n event.preventDefault()\n this.collapsedTarget.classList.toggle(\"hidden\")\n this.expandedTarget.classList.toggle(\"hidden\")\n this.isExpanded = this.collapsedTarget.classList.contains(\"hidden\")\n this.setLocationHash(event.currentTarget.href)\n\n if (this.hasArrowToggleTarget) {\n this.arrowToggleTarget.classList.toggle(\"pure-icon-angle-down\")\n this.arrowToggleTarget.classList.toggle(\"pure-icon-angle-right\")\n }\n }\n\n expand(event) {\n event.preventDefault()\n this.collapsedTarget.classList.toggle(\"hidden\", true)\n this.expandedTarget.classList.toggle(\"hidden\", false)\n this.isExpanded = true\n this.setLocationHash(event.currentTarget.href)\n this.scrollToElement(this.expandedTarget)\n }\n\n setLocationHash(href) {\n if (href) {\n const [hash] = href.split(\"#\").slice(-1)\n if (hash != \"\") {\n window.location.hash = hash\n }\n }\n }\n\n scrollToElement(element) {\n $(\"html, body\").animate({ scrollTop: element.offsetTop - 16 }, \"slow\")\n }\n\n set isExpanded(expanded) {\n var data = {}\n data[this.data.get(\"key\")] = expanded\n\n $.ajax({\n url: `/places/${this.barID}/menu/preferences`,\n method: \"PATCH\",\n data: { expanded_collapsibles: data },\n })\n }\n\n get key() {\n return this.data.get(\"key\")\n }\n\n get barID() {\n return this.data.get(\"bar-id\")\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"content\", \"arrow\" ]\n\n connect() {\n this.arrowTarget.addEventListener(\"click\", (e) => {\n e.preventDefault()\n this.toggleContent()\n })\n }\n\n // private\n\n toggleContent() {\n this.contentTarget.classList.toggle(\"closed\")\n this.arrowTarget.classList.toggle(\"rotate-90\")\n }\n\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"selectedItems\", \"modal\", \"item\", \"itemName\" ]\n\n connect() {\n this.toggle()\n }\n\n showModal() {\n $(this.modalTarget).modal()\n }\n\n toggle() {\n const itemNames = this.itemNameTargets.map(target => target.innerText)\n const selectedItems = itemNames.filter((name, index) => {\n return this.itemTargets[index].checked\n })\n\n if (selectedItems.length == 0) {\n this.selectedItemsTarget.innerHTML = \"(nothing selected)\"\n } else {\n this.selectedItemsTarget.innerHTML = selectedItems.join(\"${this.displayKey(hit)}
`\n }\n\n displayKey(obj) {\n return obj.displayLines.join(\", \")\n }\n\n populateForm(result) {\n this.latitudeTarget.value = result.coordinate.latitude\n this.longitudeTarget.value = result.coordinate.longitude\n this.nameTarget.value = result.displayLines.join(\", \")\n }\n\n mapkitError(event) {\n var message = null\n switch (event.status) {\n case \"Unauthorized\":\n message = \"MapKit JS unauthorized.\"\n break\n case \"Too Many Requests\":\n message = \"MapKit JS over daily request limit.\"\n break\n }\n\n if (message != null) {\n $.ajax({\n method: \"POST\",\n url: \"/api/internal/logs\",\n data: { message: `[MapKit] ${message}` },\n })\n }\n }\n\n get search() {\n if (this._search == undefined) {\n this._search = new mapkit.Search\n }\n return this._search\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"container\"]\n\n async connect() {\n\n var Masonry = require('masonry-layout')\n var imagesLoaded = require('imagesloaded')\n var container = this.containerTarget\n\n self.msnry = new Masonry(container, {\n itemSelector: '.grid-item',\n columnWidth: '.grid-sizer',\n percentPosition: true\n })\n\n $(container).imagesLoaded().progress( function() {\n self.msnry.layout()\n })\n\n }\n\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"loading\", \"content\", \"error\"]\n\n connect() {\n window.BeerMenus.controllers.menuController = this\n this.loadMenu()\n }\n\n refresh() {\n this.loadMenu()\n }\n\n // private\n\n loadMenu() {\n this.show(this.loadingTarget)\n\n $.ajax(`/places/${this.data.get(\"bar-id\")}/menu`)\n .done((html) => {\n this.show(this.contentTarget)\n this.contentTarget.innerHTML = html\n })\n .fail(() => this.show(this.errorTarget))\n }\n\n show(target) {\n [this.loadingTarget, this.contentTarget, this.errorTarget]\n .forEach((t) => t.classList.add(\"hidden\"))\n target.classList.remove(\"hidden\")\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"search\", \"beerTemplate\", \"servingTemplate\", \"modal\" ]\n\n connect() {\n if (this.searchTarget.getAttribute(\"aria-hidden\") == \"true\") { return }\n\n $(this.searchTarget).one(\"focus\",\n this.fetchServingsAndInitializeSearch.bind(this))\n }\n\n teardown() {\n this.search.autocomplete(\"destroy\")\n }\n\n showModal() {\n if (this.hasModalTarget) {\n $(this.modalTarget).modal()\n window.scrollTo(0, 0)\n $(this.searchTargets).focus()\n }\n }\n\n closeModal() {\n $(this.searchTargets).autocomplete(\"val\", \"\")\n\n if (this.hasModalTarget) {\n $(this.modalTarget).modal(\"hide\")\n }\n }\n\n // private\n\n fetchServingsAndInitializeSearch() {\n Promise.all([\n $.ajax(`/places/${this.barID}/menu/search.json?buy=${this.buyingEnabled}&edit=${this.isEdit}`),\n AlgoliaSource.importLibraries()\n ]).then(promises => {\n this.servings = promises[0]\n this.initializeAlgolia(promises[1][0])\n this.initializeSearch()\n $(this.searchTargets).focus()\n })\n }\n\n initializeAlgolia(algoliasearch) {\n const filters = Object.keys(this.servings)\n .map(id => `objectID:${id}`).join(\" OR \")\n this.baseSource = new AlgoliaSource(algoliasearch, \"Beer\", filters).source\n }\n\n initializeSearch() {\n this.search = $(this.searchTarget).autocomplete(this.options, this.dataset)\n .on(\"autocomplete:opened\", this.opened.bind(this))\n .on(\"autocomplete:selected autocomplete:autocompleted\", this.selected.bind(this))\n }\n\n opened(event) {\n if (!isNaN(this.scrollOffset)) {\n const offset = $(event.currentTarget).offset().top - this.scrollOffset\n $(\"html, body\").animate({ scrollTop: offset }, \"slow\")\n }\n }\n\n selected(event, suggestion) {\n this.closeModal()\n\n if (this.buyingEnabled) {\n $.ajax(this.buyPath(suggestion))\n } else if (this.isEdit) {\n Turbo.visit(this.editPath(suggestion), { frame: `serving_${suggestion.servings[0].id}` })\n } else {\n if (typeof(Turbolinks) == \"object\") {\n Turbolinks.visit(suggestion.path)\n } else {\n location.href = suggestion.path\n }\n }\n }\n\n source(query, callback) {\n this.baseSource(query, (suggestions) => {\n const servings = suggestions.map(suggestion => {\n const servings = this.servings[suggestion.objectID]\n suggestion.servings = servings\n return suggestion\n })\n return callback(servings)\n })\n }\n\n suggestion(hit) {\n const beerTemplate = this.beerTemplateTarget.cloneNode(true)\n beerTemplate.classList.remove(\"hidden\")\n beerTemplate.querySelector(\"[data-ref='name']\").textContent = hit.name\n\n const meta = new BeerMetadata(hit).toString()\n beerTemplate.querySelector(\"[data-ref='meta']\").textContent = meta\n\n hit.servings.forEach(serving => {\n const servingTemplate = this.servingTemplateTarget.cloneNode(true)\n servingTemplate.classList.remove(\"hidden\")\n servingTemplate.querySelector(\"[data-ref='availability']\").classList.add(serving.availability)\n servingTemplate.querySelector(\"[data-ref='details']\").textContent = serving.details\n beerTemplate.querySelector(\"[data-ref='servings']\").appendChild(servingTemplate)\n })\n\n const editButton = beerTemplate.querySelector(\"[data-ref='edit']\")\n if (editButton) {\n editButton.addEventListener(\"click\", (e) => e.preventDefault())\n }\n\n return beerTemplate\n }\n\n editPath(hit) {\n const servingID = hit.servings[0].id\n return `/servings/${servingID}/choose?bar_id=${this.barID}`\n }\n\n buyPath(hit) {\n const beerID = hit.objectID\n return `/places/${this.barID}/buy/?beer_id=${beerID}&cart_id=${this.cartID}&edit_order=${this.editOrder}`\n }\n\n get options() {\n return {\n autoselect: true,\n openOnFocus: true,\n clearOnSelected: true,\n debug: false,\n cssClasses: {\n prefix: \"menu-search\",\n cursor: \"cursor\",\n },\n }\n }\n\n get dataset() {\n return {\n source: this.source.bind(this),\n name: \"beers\",\n displayKey: (suggestion) => { return suggestion.name },\n templates: { suggestion: this.suggestion.bind(this) },\n }\n }\n\n get barID() {\n return this.data.get(\"bar-id\")\n }\n\n get cartID() {\n return this.data.get(\"cart-id\")\n }\n\n get scrollOffset() {\n return parseInt(this.data.get(\"scroll-offset\"))\n }\n\n get buyingEnabled() {\n return this.data.get(\"buying-enabled\") == \"true\"\n }\n\n get editOrder() {\n return this.data.get(\"edit-order\") == \"true\"\n }\n\n get isEdit() {\n return this.data.get(\"is-edit\") == \"true\"\n }\n\n get editMenuVersion() {\n return this.data.get(\"edit-menu-version\")\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n showNewSectionModal(event) {\n event.preventDefault()\n\n $(\"#menu-sections\").modal(\"hide\")\n MenuSections.showNewSectionModal(this.data.get(\"product-type\"))\n }\n}\n", "import { Controller} from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"menuSection\", \"servingType\", \"error\"]\n\n sectionChanged(event) {\n let selectedOption = null\n if (event.currentTarget.selectedOptions) {\n selectedOption = event.currentTarget.selectedOptions[0]\n } else {\n // IE 11\n selectedOption = event.currentTarget.options[event.currentTarget.selectedIndex]\n }\n\n if (selectedOption.dataset[\"type\"] == \"create\") {\n this.showNewSectionModal()\n }\n\n this.clearError()\n }\n\n servingTypeChanged(event) {\n this.selectMenuSection(event.currentTarget.value)\n }\n\n newSection(event) {\n event.preventDefault()\n this.showNewSectionModal()\n }\n\n // private\n\n showNewSectionModal() {\n MenuSections.showNewSectionModal(this.data.get(\"product-type\"))\n\n document.querySelector(\"#new-menu-section button\")\n .addEventListener(\"click\", (e) => {\n this.selectMenuSection(this.servingTypeTarget.value)\n })\n }\n\n selectMenuSection(servingType) {\n if (this.globalMenuSectionSelected) {\n const servingTypeInt = parseInt(servingType)\n for (let [sectionID, servingTypes] of Object.entries(this.sectionIDs)) {\n if (servingTypes.includes(servingTypeInt)) {\n this.menuSectionTarget.value = sectionID\n }\n }\n }\n }\n\n clearError() {\n if (this.hasErrorTarget) {\n this.errorTarget.remove()\n }\n }\n\n get globalMenuSectionSelected() {\n const selectedMenuSectionID = parseInt(this.menuSectionTarget.value)\n return this.globalSectionIDs.includes(selectedMenuSectionID)\n }\n\n get sectionIDs() {\n if (this._sectionIDs === undefined) {\n this._sectionIDs = JSON.parse(this.data.get(\"section-ids\"))\n }\n return this._sectionIDs\n }\n\n get globalSectionIDs() {\n if (this._globalSectionIDs === undefined) {\n this._globalSectionIDs = JSON.parse(this.data.get(\"global-section-ids\"))\n }\n return this._globalSectionIDs\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport const MAX_MONTHLY_PRICE = 99\nexport const MAX_ANNUAL_PRICE = 599\nexport const MAX_ANNUAL_SAVINGS = 589\n\nexport default class extends Controller {\n static targets = [ \"option\", \"monthly\", \"annual\", \"plans\", \"names\",\n \"monthlyPrice\", \"annualPrice\", \"annualSavings\", \"modalPlanNames\",\n \"modalPrice\", \"modalSavings\", \"modalAllInclusivePrice\", \"mobile\",\n ]\n\n connect() {\n this.allInclusiveOption = this.optionTargets.shift()\n this.updateContent()\n }\n\n toggle(event) {\n $(event.target).closest(\".modular-checkbox\").toggleClass(\"checked\")\n\n if (event.target == this.allInclusiveOption && event.target.checked) {\n this.selectOnlyAllInclusive(false)\n } else if (event.target != this.monthlyTarget && event.target != this.annualTarget) {\n this.updateContent(event.target)\n }\n\n var atAnnualMaxPrice = this.annualPriceTarget.innerText == MAX_ANNUAL_PRICE\n if (event.target == this.annualTarget && atAnnualMaxPrice) {\n this.selectOnlyAllInclusive(!this.allInclusiveOption.checked)\n }\n }\n\n updateContent(checkbox) {\n var planNames = []\n var monthlyPlans = []\n var annualPlans = []\n var monthlyPrice = 0\n var annualPrice = 0\n var annualSavings = 0\n\n var selectedPlans = this.optionTargets.filter(checkbox => checkbox.checked)\n selectedPlans.forEach(plan => {\n planNames.push(plan.dataset.name)\n monthlyPlans.push(plan.dataset.monthly)\n annualPlans.push(plan.dataset.annual)\n monthlyPrice += parseFloat(plan.dataset.monthlyPrice)\n annualPrice += parseFloat(plan.dataset.annualPrice)\n annualSavings += parseFloat(plan.dataset.annualSavings)\n })\n\n if (checkbox != null && checkbox.checked && this.allInclusiveOption.checked) {\n this.allInclusiveOption.checked = false\n $(this.allInclusiveOption).closest(\".modular-checkbox\").removeClass(\"checked\")\n this.updateContent()\n } else if (this.shouldSelectAllInclusive(monthlyPrice, annualPrice)) {\n this.selectOnlyAllInclusive(true, planNames, monthlyPrice, annualPrice)\n } else {\n this.populateHtml(planNames, monthlyPlans, monthlyPrice, annualPlans, annualPrice, annualSavings)\n }\n }\n\n shouldSelectAllInclusive(monthlyPrice, annualPrice) {\n var shouldSelectMonthly = this.monthlyTarget.checked && monthlyPrice > MAX_MONTHLY_PRICE\n var shouldSelectAnnual = this.annualTarget.checked && annualPrice > MAX_ANNUAL_PRICE\n return shouldSelectMonthly || shouldSelectAnnual\n }\n\n selectOnlyAllInclusive(showModal, planNames, monthlyPrice, annualPrice) {\n this.optionTargets.forEach(checkbox => {\n checkbox.checked = false\n $(checkbox.closest(\".modular-checkbox\")).removeClass(\"checked\");\n })\n this.allInclusiveOption.checked = true\n $(this.allInclusiveOption).closest(\".modular-checkbox\").addClass(\"checked\")\n this.updateContent()\n\n if (showModal) {\n this.modalPlanNamesTarget.innerHTML = planNames.joinSentence(true)\n\n if (this.monthlyTarget.checked) {\n this.modalPriceTarget.innerHTML = `$${monthlyPrice}/month`\n this.modalSavingsTarget.innerHTML = `$${(monthlyPrice - MAX_MONTHLY_PRICE) * 12}/year`\n this.modalAllInclusivePriceTarget.innerHTML = `$${MAX_MONTHLY_PRICE}/month`\n } else {\n this.modalPriceTarget.innerHTML = `$${annualPrice}/year`\n this.modalSavingsTarget.innerHTML = `$${annualPrice - MAX_ANNUAL_PRICE}/year`\n this.modalAllInclusivePriceTarget.innerHTML = `$${MAX_ANNUAL_PRICE}/year`\n }\n\n $(\"#all-inclusive\").modal()\n if (this.mobile) {\n setTimeout(() => $(\"#payment-form\")[0].scrollIntoView(false), 1)\n }\n }\n }\n\n populateHtml(planNames, monthlyPlans, monthlyPrice, annualPlans, annualPrice, annualSavings) {\n this.plansTarget.innerHTML = \"Plan\"\n\n if (planNames.length == 0) {\n this.namesTarget.innerHTML = \"Choose tools\"\n } else {\n this.namesTarget.innerHTML = planNames.joinSentence(true)\n }\n\n this.monthlyTarget.value = monthlyPlans\n this.monthlyPriceTarget.innerHTML = Math.min(monthlyPrice, MAX_MONTHLY_PRICE)\n this.annualTarget.value = annualPlans\n\n if (annualPrice >= MAX_ANNUAL_PRICE) {\n this.annualPriceTarget.innerHTML = MAX_ANNUAL_PRICE\n this.annualSavingsTarget.innerHTML = MAX_ANNUAL_SAVINGS\n } else {\n this.annualPriceTarget.innerHTML = annualPrice\n this.annualSavingsTarget.innerHTML = annualSavings\n }\n }\n\n get mobile() {\n return this.hasMobileTarget\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"parent\"]\n\n async connect() {\n if (!window.Browser.isIE()) {\n (await import(\"select2/dist/js/select2.full.js\")).default() // init the plugin\n this.initializeSelect2()\n }\n }\n\n // private\n\n initializeSelect2() {\n const containerClass = this.data.get(\"container\")\n const dropdownClass = this.data.get(\"dropdown\")\n\n if (this.hasParentTarget) {\n $(this.element).select2({\n dropdownParent: $(this.parentTarget.dataset.parent),\n containerCssClass: containerClass,\n dropdownCssClass: dropdownClass\n })\n }\n else {\n $(this.element).select2({\n containerCssClass: containerClass,\n dropdownCssClass: dropdownClass\n })\n }\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n initialize() {\n this.timeout = null\n this.url = this.data.get(\"url\")\n this.pickup = this.data.get(\"pickup\")\n }\n\n search(event) {\n clearTimeout(this.timeout)\n\n this.timeout = setTimeout(() => {\n $.ajax({\n url: this.url,\n data: {\n query: event.target.value,\n pickup: this.pickup,\n },\n dataType: \"script\",\n })\n }, 500)\n };\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n change(event) {\n var url = new URL(window.location)\n\n var pickupId = event.currentTarget.value\n if (pickupId === \"all\") {\n url.searchParams.delete(\"pickup\")\n } else {\n url.searchParams.set(\"pickup\", pickupId)\n }\n\n window.location = url\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"location\", \"name\", \"remove\", \"destroy\", \"add\" ]\n\n connect() {\n this.nameTargets.forEach((target, index) => {\n const hide = target.attributes[\"value\"] === undefined && index != 0\n this.locationTargets[index].classList.toggle(\"hidden\", hide)\n\n if (!hide && index === this.max - 1) {\n this.addTarget.classList.toggle(\"hidden\", true)\n }\n })\n\n this.removeTargets.forEach((target, index) => {\n const hide = index == 0 || target.dataset[\"neverShow\"] === \"true\"\n target.classList.toggle(\"hidden\", hide)\n })\n }\n\n add(event) {\n event.preventDefault()\n\n var showedALocation = false\n this.locationTargets.forEach((target, index) => {\n if (!showedALocation && target.classList.contains(\"hidden\")) {\n target.classList.toggle(\"hidden\", false)\n this.destroyTargets[index].value = \"0\"\n showedALocation = true\n\n if (index === this.locationTargets.length - 1) {\n event.currentTarget.classList.toggle(\"hidden\", true)\n }\n }\n })\n }\n\n remove(event) {\n event.preventDefault()\n\n const index = this.removeTargets.indexOf(event.currentTarget)\n this.locationTargets[index].classList.toggle(\"hidden\", true)\n this.destroyTargets[index].value = \"1\"\n\n this.addTarget.classList.toggle(\"hidden\", false)\n }\n\n get max() {\n return parseInt(this.data.get(\"max\"))\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n qualify(event) {\n this.updateLead(true)\n }\n\n disqualify(event) {\n this.updateLead(false)\n }\n\n // private\n\n updateLead(qualified) {\n $.ajax({\n type: \"PUT\",\n url: this.data.get(\"url\"),\n dataType: \"json\",\n data: {\n \"authenticity_token\": this.authenticityToken,\n \"place_lead[qualified]\": qualified,\n },\n success: (response) => {\n if (!response.success) {\n this.errorAlert()\n }\n },\n error: () => this.errorAlert()\n })\n }\n\n get authenticityToken() {\n return document.querySelector(\"meta[name='csrf-token']\").content\n }\n\n get errorAlert() {\n alert(\"Error saving. Please reload the page and try again.\")\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"retailerPrice\", \"buyerPrice\", \"validPrice\", \"invalidPrice\" ]\n\n connect() {\n this.calculateBuyerPrice()\n }\n\n calculateBuyerPrice() {\n if (this.retailerPrice == 0) {\n this.validPriceTarget.classList.add(\"hidden\")\n this.invalidPriceTarget.classList.remove(\"hidden\")\n } else {\n this.invalidPriceTarget.classList.add(\"hidden\")\n this.validPriceTarget.classList.remove(\"hidden\")\n\n this.buyerPriceTarget.textContent = `$${this.buyerPrice}`\n }\n }\n\n // private\n\n get retailerPrice() {\n return parseFloat(this.retailerPriceTarget.value) || 0\n }\n\n get buyerPrice() {\n return (this.retailerPrice + this.fee).toFixed(2)\n }\n\n get fee() {\n if (this.retailerPrice < 14) {\n return 0.5\n } else if (this.retailerPrice <= 25) {\n return 1\n } else {\n return this.retailerPrice * 0.05\n }\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"iframe\" ]\n\n print() {\n this.iframeTarget.contentWindow.print()\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"header\", \"hero\", \"stickySlide\"]\n\n connect() {\n this.$window = $(window)\n\n this.startWatchingIntersection()\n\n if (window.innerWidth >= 812) {\n this.startWatchingScroll()\n this.fadeOutStickySlides()\n }\n }\n\n // private\n\n startWatchingIntersection() {\n const observer = new IntersectionObserver(this.toggleScrolledOnHeader.bind(this))\n observer.observe(this.heroTarget)\n }\n\n toggleScrolledOnHeader(entries) {\n if (entries[0].isIntersecting) {\n this.headerTarget.classList.remove(\"scrolled\")\n } else {\n this.headerTarget.classList.add(\"scrolled\")\n }\n }\n\n startWatchingScroll() {\n document.addEventListener(\"scroll\",\n Debouncer.debounce(this.fadeOutStickySlides.bind(this)),\n { passive: true }\n )\n }\n\n fadeOutStickySlides() {\n this.stickySlideTargets.forEach(target => {\n const position = $(target).offset().top - this.$window.scrollTop()\n\n if (position < this.windowHeight * this.startPosition) {\n target.style.opacity = position / (this.windowHeight * this.startPosition)\n } else {\n target.style.opacity = 1\n }\n })\n }\n\n get startPosition() {\n return 0.1\n }\n\n get windowHeight() {\n return this.$window.height()\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"form\", \"overlay\", \"groupByStyle\", \"sectionBreakOption\",\n \"beer_descriptionFont\", \"submit\", \"modal\", \"disablePdfReload\"]\n\n connect() {\n this.formTarget.dataset.remote = this.data.get(\"auto-save\") == \"true\"\n\n this.submitOnChange()\n this.submitOnEvent()\n\n $(this.formTarget).on(\"ajax:success\", this.success.bind(this))\n $(this.formTarget).on(\"ajax:error\", this.error.bind(this))\n }\n\n showStyleOptions() {\n this.groupByStyleTargets.forEach(t => t.classList.remove(\"hidden\"))\n }\n\n hideStyleOptions() {\n this.groupByStyleTargets.forEach(t => t.classList.add(\"hidden\"))\n }\n\n showSectionBreakOption() {\n this.sectionBreakOptionTarget.classList.remove(\"hidden\")\n }\n\n hideSectionBreakOption() {\n this.sectionBreakOptionTarget.classList.add(\"hidden\")\n }\n\n toggleBeerDescriptionFont(event) {\n const checked = event.currentTarget.checked\n this.beer_descriptionFontTarget.classList.toggle(\"hidden\", !checked)\n }\n\n toggleAutoSave(event) {\n this.data.set(\"auto-save\", !event.currentTarget.checked)\n this.formTarget.dataset.remote = !event.currentTarget.checked\n this.submitTarget.classList.toggle(\"hidden\", !event.currentTarget.checked)\n }\n\n submitForm(event) {\n if (this.data.get(\"auto-save\") == \"true\") {\n this.overlayTarget.classList.remove(\"hidden\")\n\n if (event.currentTarget.dataset.disablePdfReload == \"true\") {\n this.disablePdfReloadTarget.value = true\n $.rails.fire($(this.formTarget), \"submit\")\n this.disablePdfReloadTarget.value = false\n } else {\n window.BeerMenus.controllers.printPreviewController.showLoading()\n $.rails.fire($(this.formTarget), \"submit\")\n }\n }\n }\n\n // private\n\n submitOnChange() {\n [...this.formTarget.elements].forEach(element => {\n if (!element.dataset.ignore) {\n element.addEventListener(\"change\", this.submitForm.bind(this))\n }\n })\n }\n\n submitOnEvent() {\n document.body.addEventListener(\"sortable:didSort\",\n this.submitForm.bind(this))\n\n document.body.addEventListener(\"customFont:selected\",\n this.submitForm.bind(this))\n\n document.body.addEventListener(\"cme-blur\",\n this.submitForm.bind(this))\n }\n\n success(event, data, status, xhr) {\n this.overlayTarget.classList.add(\"hidden\")\n this.submitOnChange()\n }\n\n error(event, xhr) {\n window.BeerMenus.controllers.printPreviewController.showServerError()\n this.overlayTarget.classList.add(\"hidden\")\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"loading\", \"loadingText\", \"pdf\", \"error\"]\n\n connect() {\n this.pdfTarget.onload = this.validatePDF.bind(this)\n window.BeerMenus.controllers.printPreviewController = this\n }\n\n showLoading() {\n if (Browser.isIE()) {\n this.pdfTarget.src = \"about:blank\"\n } else {\n this.loadingTextTarget.innerText = \"Updating\"\n this.loadingTarget.classList.remove(\"hidden\")\n this.errorTarget.classList.add(\"hidden\")\n }\n }\n\n showValidationError(html) {\n this.errorTarget.innerHTML = html\n this.loadingTarget.classList.add(\"hidden\")\n this.errorTarget.classList.remove(\"hidden\")\n }\n\n showServerError() {\n $.ajax({ url: this.errorURL, success: this.populateErrorHTML.bind(this) })\n }\n\n // private\n\n validatePDF() {\n if (Browser.isIE()) {\n return\n } else if (this.isFirefox || this.isIpad || this.isPDFValid) {\n this.loadingTarget.classList.add(\"hidden\")\n this.errorTarget.classList.add(\"hidden\")\n } else if (this.errorPresent) {\n this.loadingTarget.classList.add(\"hidden\")\n this.errorTarget.classList.add(\"hidden\")\n this.bindReload()\n } else {\n this.showServerError()\n }\n }\n\n populateErrorHTML(html) {\n this.iframe.body.innerHTML = html\n this.loadingTarget.classList.add(\"hidden\")\n this.bindReload()\n this.bindHelp()\n }\n\n bindReload() {\n this.iframe.getElementById(\"reload-button\").addEventListener(\"click\", (event) => {\n event.preventDefault()\n this.loadingTarget.classList.remove(\"hidden\")\n this.pdfTarget.contentWindow.location.reload()\n })\n }\n\n bindHelp() {\n this.iframe.getElementById(\"help-link\").addEventListener(\"click\", (event) => {\n event.preventDefault()\n const target = parent ? parent : window\n target.Beacon(\"open\")\n target.Beacon(\"navigate\", \"/ask\")\n })\n }\n\n get isFirefox() {\n return navigator.userAgent.toLowerCase().indexOf('firefox') > -1\n }\n\n get isIpad() {\n return this.data.get(\"is-ipad\") == \"true\"\n }\n\n get isPDFValid() {\n const embed = this.iframe.getElementsByTagName(\"embed\")[0]\n return embed && embed.getAttribute(\"type\") == \"application/pdf\"\n }\n\n get errorPresent() {\n return this.iframe.getElementById(\"pdf-error\") != null\n }\n\n get iframe() {\n return this.pdfTarget.contentDocument\n }\n\n get url() {\n return this.data.get(\"url\")\n }\n\n get errorURL() {\n return this.data.get(\"error-url\")\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"save\", \"error\"]\n\n enableForm() {\n this.saveTarget.classList.remove(\"hidden\")\n this.errorTarget.classList.add(\"hidden\")\n }\n\n disableForm() {\n this.errorTarget.classList.remove(\"hidden\")\n this.saveTarget.classList.add(\"hidden\")\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"dayvariables\", \"day\", \"nearvariables\", \"near\" ]\n\n propertyChanged(event) {\n if (event.currentTarget.value == \"days_since_last_update\") {\n this.dayvariablesTarget.classList.toggle(\"hidden\", false)\n } else if (event.currentTarget.value == \"near_city\") {\n this.nearvariablesTarget.classList.toggle(\"hidden\", false)\n } else {\n this.dayvariablesTarget.classList.toggle(\"hidden\", true)\n this.dayTargets.forEach(t => t.value = \"\")\n this.nearvariablesTarget.classList.toggle(\"hidden\", true)\n this.nearTargets.forEach(t => t.value = \"\")\n }\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"select\", \"field\" ]\n\n connect() {\n this.showHideField()\n }\n\n change() {\n this.showHideField()\n }\n\n showHideField() {\n const hide = this.selectTarget.value == \"false\"\n this.fieldTarget.classList.toggle(\"hidden\", hide)\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n connect() {\n // Only get involved if a file upload is present.\n $(this.element).bind(\"ajax:aborted:file\", () => {\n this.disableForm()\n this.manuallyPOST()\n\n // Tell jquery-ujs to not submit the form; we got this.\n return false\n })\n }\n\n // private\n\n disableForm() {\n // Wait for jquery-ujs to \"finish\" before disabling.\n setTimeout(() => {\n $.rails.disableFormElements($(this.element))\n }, 20)\n }\n\n // https://makandracards.com/makandra/39225-manually-uploading-files-via-ajax\n manuallyPOST() {\n $.ajax({\n url: `${this.element.action}.js`,\n type: \"POST\",\n data: new FormData(this.element),\n contentType: false,\n processData: false,\n complete: () => $.rails.enableFormElements($(this.element))\n })\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n connect() {\n this.element.addEventListener(\"click\", () => window.scrollTo(0, 0))\n }\n}\n", "// Handles interaction between radio buttons and text inputs in segmented fields\nimport { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"radio\", \"textInput\"]\n\n connect() {\n // Initialize radio value if text input has a value\n if (this.hasTextInputTarget && this.textInputTarget.value) {\n this.syncRadioValue()\n }\n }\n\n focusInput() {\n if (this.hasTextInputTarget) {\n this.textInputTarget.focus()\n }\n }\n\n selectRadio() {\n if (this.hasRadioTarget) {\n this.radioTarget.checked = true\n this.syncRadioValue()\n }\n }\n\n // Called when text input changes\n handleTextInput() {\n if (this.hasRadioTarget) {\n this.radioTarget.checked = true\n this.syncRadioValue()\n }\n }\n\n // Sync radio value with text input value\n syncRadioValue() {\n if (this.hasRadioTarget && this.hasTextInputTarget) {\n this.radioTarget.value = this.textInputTarget.value\n }\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"type\", \"event\", \"property\" ]\n\n async connect() {\n (await import(\"cocoon-js\")).default\n }\n\n toggle(event) {\n const index = this.typeTargets.indexOf(event.currentTarget)\n this.eventTargets[index].classList.toggle(\"hidden\")\n this.propertyTargets[index].classList.toggle(\"hidden\")\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"checkbox\"]\n\n connect() {\n window.BeerMenus.controllers.selectAllControllers =\n window.BeerMenus.controllers.selectAllControllers || []\n window.BeerMenus.controllers.selectAllControllers.push(this)\n }\n\n toggle(event) {\n const checked = event.currentTarget.checked\n this.checkboxTargets.forEach(el => el.checked = checked)\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"destroy\"]\n\n remove(event) {\n event.preventDefault()\n this.element.remove()\n }\n\n destroy(event) {\n event.preventDefault()\n\n this.element.classList.add(\"hidden\")\n this.destroyTarget.value = 1\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"servings\", \"serving\", \"type\", \"unit\", \"sell\"]\n\n add(event) {\n event.preventDefault()\n\n $.ajax(\"/servings/add_size\", { data: this.params })\n .done((html) => BeerMenus.DOM.insertHTML(html, this.servingsTarget))\n .fail((jqXHR, status, error) => console.error(error))\n }\n\n reset(event) {\n event.preventDefault()\n\n Servings.hideEditForm()\n Servings.scrollToTopOfForm()\n }\n\n // private\n\n get params() {\n const lastIndex = this.servingTargets.length - 1\n const index = parseInt(this.servingTargets[lastIndex].dataset[\"index\"])\n\n if (this.hasTypeTarget) {\n var serving_type_id = this.typeTargets[lastIndex].value\n var serving_unit_id = this.unitTargets[lastIndex].value\n } else {\n var serving_type_id = \"\"\n var serving_unit_id = \"\"\n }\n\n return {\n bar_id: this.barID,\n new_index: index + 1,\n serving_type_id: serving_type_id,\n serving_unit_id: serving_unit_id,\n product_type: this.productType,\n sell: this.sellTarget.checked\n }\n }\n\n get barID() {\n return this.data.get(\"bar-id\")\n }\n\n get productType() {\n return this.data.get(\"product-type\")\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nclass FormDataEventPolyfill extends Event {\n constructor(formData) {\n super('formdata');\n this.formData = formData;\n }\n}\n\nclass WorkingFormDataPolyfill extends FormData {\n constructor(form=null) {\n if (form) {\n super(form)\n this.form = form\n form.dispatchEvent(new FormDataEventPolyfill(this))\n } else {\n super()\n }\n }\n\n append(name, value) {\n if (!this.form) {\n return super.append(name, value)\n }\n\n let input = this.form.elements[name]\n\n if (!input) {\n input = document.createElement('input');\n input.type = 'hidden';\n input.name = name;\n this.form.appendChild(input);\n }\n\n if (this.has(name)) {\n const entries = this.getAll(name);\n const index = entries.indexOf(input.value);\n\n if (index !== -1) {\n entries.splice(index, 1);\n }\n\n entries.push(value);\n this.set(name, entries);\n } else {\n super.append(name, value);\n }\n\n input.value = value;\n }\n}\n\nwindow.WorkingFormDataPolyfill = WorkingFormDataPolyfill\n\nexport default class extends Controller {\n async connect() {\n await import(\"../app/shoelace\")\n\n // TODO: once we're using Shoelace within the design system, we don't need this\n await import(\"@shoelace-style/shoelace/dist/themes/light.css\")\n\n await customElements.whenDefined(\"sl-color-picker\")\n\n this.element.querySelectorAll(\"sl-color-picker\").forEach((picker) => {\n picker.swatches = [\n \"#cd2020\",\n \"#fba820\",\n \"#f8e71c\",\n \"#7d5f4b\",\n \"#9CE2B6\",\n \"#f470fc\",\n \"#ae65ee\",\n \"#287DDB\",\n \"#50e3c2\",\n \"#DFEEFD\",\n \"#000000\",\n \"#444444\",\n \"#cdcdcd\",\n \"#ddd\",\n \"#fff\",\n ]\n })\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"truncated\", \"full\", \"showMore\", \"showLess\" ]\n\n toggle(event) {\n event.preventDefault()\n\n if (this.hasTruncatedTarget) {\n this.truncatedTarget.classList.toggle(\"hidden\")\n }\n this.fullTarget.classList.toggle(\"hidden\")\n\n this.showMoreTarget.classList.toggle(\"hidden\")\n this.showLessTarget.classList.toggle(\"hidden\")\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"search\", \"beerID\", \"template\"]\n\n async connect() {\n let libraries = await AlgoliaSource.importLibraries()\n const filters = `product_type = 0 OR product_type = 1 OR product_type = 3`\n this.algolia = new AlgoliaSource(libraries[0], \"Beer\", filters)\n this.connected()\n }\n\n // private\n\n connected() {\n this.search = $(this.searchTarget).autocomplete(this.options, this.dataset)\n this.search\n .on(\"autocomplete:selected autocomplete:autocompleted\", (event, data) => {\n this.setHiddenField(data.objectID)\n })\n }\n\n setHiddenField(id) {\n this.beerIDTarget.value = id\n }\n\n source(query, callback) {\n this.algolia.source(query, (suggestions) => {\n return callback(suggestions)\n })\n }\n\n displayKey(obj) {\n return obj.cssClass == this.addNewBeerClass ? obj.query : obj.name\n }\n\n suggestion(hit) {\n return new BeerAutocompleteSuggestion(this.templateTarget).build(hit)\n }\n\n get dataset() {\n return {\n source: (query, callback) => { this.source(query, callback) },\n name: \"beers\",\n displayKey: (obj) => { return obj.name },\n templates: { suggestion: this.suggestion.bind(this) },\n }\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\n \"monthlyTerm\", \"monthlyPlan\", \"annualPlan\",\n \"plan\", \"tool\", \"paymentPlan\", \"effectiveMonthlyPrice\",\n \"monthlyPrice\", \"annualPrice\", \"annualSavings\",\n \"popularPlan\", \"potentialSavings\", \"realizedSavings\",\n \"mySubscription\", \"chooseTools\", \"button\", \"newSubscription\", \"switchToAnnual\",\n \"discountMessage\", \"discountDescription\", \"discountValue\", \"discountedTotal\", \"monthlyFullPrice\", \"annualFullPrice\",\n \"stripeCoupon\"\n ]\n\n connect() {\n this.setPlan()\n this.setPlanName()\n this.setPrices()\n }\n\n toggleTool(event) {\n this.setPlan()\n this.setPlanName()\n this.setPrices()\n }\n\n toggleTerm(event) {\n this.setPrices()\n this.setPlan()\n }\n\n // private\n\n setPrices() {\n const tools = this.enabledTools\n const pricing = this.pricing.find(p => p.tools == tools)\n\n if (pricing) {\n if (this.annual) {\n if (this.hasStripeCouponTarget) { this.discountMessageTargets.forEach(t => t.classList.remove(\"hidden\")) }\n var effectivePrice = pricing.annual_price_monthly\n var price = pricing.annual_price\n this.potentialSavingsTarget.classList.add(\"hidden\")\n this.realizedSavingsTarget.classList.remove(\"hidden\")\n if (this.hasCoupon) {\n this.stripeCouponTarget.value = this.data.get(\"coupon-annual\")\n this.discountDescriptionTargets.forEach(t => t.innerText = this.annualDiscountDescription)\n this.monthlyFullPriceTarget.classList.add(\"hidden\")\n this.annualFullPriceTarget.classList.remove(\"hidden\")\n this.discountValueTarget.innerText = pricing.annual_discount_value.toFixed(2)\n this.discountedTotalTarget.innerText = pricing.discounted_annual_price.toFixed(2)\n var price = pricing.discounted_annual_price.toFixed(2)\n }\n } else {\n var effectivePrice = pricing.price\n var price = pricing.price\n this.potentialSavingsTarget.classList.remove(\"hidden\")\n this.realizedSavingsTarget.classList.add(\"hidden\")\n if (this.hasCoupon) {\n if (pricing.discounted_monthly_price > 0) {\n this.stripeCouponTarget.value = this.data.get(\"coupon-monthly\")\n this.discountDescriptionTargets.forEach(t => t.innerText = this.monthlyDiscountDescription)\n this.monthlyFullPriceTarget.classList.remove(\"hidden\")\n this.annualFullPriceTarget.classList.add(\"hidden\")\n this.discountValueTarget.innerText = pricing.monthly_discount_value.toFixed(2)\n this.discountedTotalTarget.innerText = pricing.discounted_monthly_price.toFixed(2)\n var price = pricing.discounted_monthly_price.toFixed(2)\n } else {\n this.stripeCouponTarget.value = \"\"\n this.discountMessageTargets.forEach(t => t.classList.add(\"hidden\"))\n }\n }\n }\n\n this.effectiveMonthlyPriceTarget.innerText = effectivePrice\n\n if (this.hasNewSubscriptionTarget) {\n var buttonLabel = \"Subscribe and pay $\" + price\n this.buttonTarget.innerText = buttonLabel\n this.buttonTarget.dataset[\"disableWith\"] = buttonLabel\n this.buttonTarget.dataset[\"originalLabel\"] = buttonLabel\n } else if (this.hasSwitchToAnnualTarget) {\n if (this.annual) {\n var buttonLabel = \"Switch to annual billing\"\n } else {\n var buttonLabel = \"Update subscription\"\n }\n\n this.buttonTarget.innerText = buttonLabel\n this.buttonTarget.dataset[\"disableWith\"] = buttonLabel\n this.buttonTarget.dataset[\"originalLabel\"] = buttonLabel\n }\n\n this.monthlyPriceTargets.forEach(t => t.innerText = pricing.price)\n this.annualPriceTargets.forEach(t => t.innerText = pricing.annual_price)\n this.annualSavingsTargets.forEach(t => t.innerText = pricing.annual_savings)\n }\n }\n\n setPlanName() {\n this.paymentPlanTarget.innerText = this.planName\n }\n\n get planName() {\n return this.toolTargets.filter(t => t.checked).map(t => t.dataset[\"planName\"]).join(' + ')\n }\n\n setPlan() {\n this.planTarget.value = this.plan\n\n if (this.enabledTools == 0) {\n this.mySubscriptionTarget.classList.add(\"hidden\")\n this.chooseToolsTarget.classList.remove(\"hidden\")\n } else {\n this.mySubscriptionTarget.classList.remove(\"hidden\")\n this.chooseToolsTarget.classList.add(\"hidden\")\n }\n\n if (this.popularPlan) {\n this.popularPlanTarget.classList.remove(\"hidden\")\n } else {\n this.popularPlanTarget.classList.add(\"hidden\")\n }\n }\n\n get plan() {\n if (this.annual) {\n return this.annualPlan\n } else {\n return this.monthlyPlan\n }\n }\n\n get annualPlan() {\n const tools = this.toolTargets.filter(t => t.checked)\n switch(tools.length) {\n case 0:\n return null\n case 1:\n return tools[0].dataset[\"annualPlanId\"]\n default:\n return 63\n }\n }\n\n get monthlyPlan() {\n const tools = this.toolTargets.filter(t => t.checked)\n switch(tools.length) {\n case 0:\n return null\n case 1:\n return tools[0].dataset[\"monthlyPlanId\"]\n case 2:\n const tool1Plans = tools[0].dataset[\"monthly-2PlanIds\"].split(\" \")\n const tool2Plans = tools[1].dataset[\"monthly-2PlanIds\"].split(\" \")\n return tool1Plans.find(x => tool2Plans.includes(x))\n default:\n return 59\n }\n }\n\n get enabledTools() {\n return this.toolTargets.filter(t => t.checked).length\n }\n\n get monthly() {\n return this.monthlyTermTarget.checked\n }\n\n get annual() {\n return !this.monthly\n }\n\n get popularPlan() {\n const tvMenus = this.toolTargets.find(t => t.dataset[\"planSlug\"] == \"digital_beer_boards\")\n return this.enabledTools == 2 && !tvMenus.checked\n }\n\n get pricing() {\n return JSON.parse(this.data.get(\"pricing\"))\n }\n\n get hasCoupon() {\n return this.hasDiscountMessageTarget\n }\n\n get monthlyDiscountDescription() {\n return this.data.get(\"monthly-discount-description\")\n }\n\n get annualDiscountDescription() {\n return this.data.get(\"annual-discount-description\")\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static values = {\n speed: { type: Number, default: 800 }\n }\n\n connect() {\n this.element.addEventListener(\"click\", (event) => {\n event.preventDefault()\n\n const anchor = event.currentTarget.href.split(\"#\").pop()\n const offset = parseInt(this.data.get(\"offset\")) || 0\n const target = document.getElementById(anchor)\n\n if (target) {\n this.smoothScroll(target, offset)\n }\n\n if (this.data.has(\"focus\")) {\n document.getElementById(this.data.get(\"focus\")).focus()\n }\n })\n }\n\n smoothScroll(target, offset) {\n const targetPosition = target.getBoundingClientRect().top + window.pageYOffset - offset\n const startPosition = window.pageYOffset\n const distance = targetPosition - startPosition\n const duration = this.speedValue\n let start = null\n\n const animation = (currentTime) => {\n if (start === null) start = currentTime\n const timeElapsed = currentTime - start\n const progress = Math.min(timeElapsed / duration, 1)\n\n // Easing function - easeInOutQuad\n const easing = progress => {\n return progress < 0.5\n ? 2 * progress * progress\n : 1 - Math.pow(-2 * progress + 2, 2) / 2\n }\n\n window.scrollTo(0, startPosition + (distance * easing(progress)))\n\n if (progress < 1) {\n requestAnimationFrame(animation)\n }\n }\n\n requestAnimationFrame(animation)\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"container\", \"position\", \"itemNumber\", \"item\"]\n\n async connect() {\n const draggable = await import(\"@shopify/draggable/lib/draggable.bundle.legacy\")\n this.initializeDraggable(draggable.default)\n }\n\n savePositions(skipSave) {\n // \"Delay\" so Sortable can settle and remove the mirror.\n setTimeout(() => {\n this.itemTargets.forEach((_, index) => {\n if (index < this.positionTargets.length) {\n this.positionTargets[index].value = index + 1\n }\n\n if (index < this.itemNumberTargets.length) {\n this.itemNumberTargets[index].innerHTML = `${index + 1}.`\n }\n })\n\n this.dispatchCustomEvent()\n\n if (skipSave != true && this.data.get(\"skip-save\") != \"true\") {\n this.save()\n }\n })\n }\n\n // private\n\n initializeDraggable(draggable) {\n const sortable = new draggable.Sortable(this.containerTarget, {\n draggable: \"li:not([data-sortable-ignore])\",\n handle: this.data.has(\"no-handle\") ? null : \".sort-icon\",\n mirror: {\n appendTo: \"#sortable-mirror-wrapper\",\n constrainDimensions: true,\n xAxis: false\n }\n })\n\n sortable.on(\"drag:stop\", this.savePositions.bind(this))\n }\n\n dispatchCustomEvent() {\n const event = new CustomEvent(\"sortable:didSort\", { bubbles: true })\n this.element.dispatchEvent(event)\n }\n\n save() {\n const url = this.data.get(\"url\")\n if (url) {\n var data = {}\n data[this.data.get(\"data-key\")] = this.items\n\n $.ajax(url, { method: \"PUT\", data: data })\n .fail(() => alert(this.errorMessage))\n }\n }\n\n get items() {\n return this.itemTargets.map(item => {\n if (item.dataset.key) {\n return [item.dataset.key, item.dataset.value]\n } else {\n return item.dataset.value.split(\",\")\n }\n })\n }\n\n get placeholderClass() {\n return this.data.get(\"placeholder-class\") || \"\"\n }\n\n get errorMessage() {\n return this.data.get(\"error\") ||\n \"Something went wrong, please try again.\"\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n connect() {\n if ((document.body.classList.contains(\"web\")) || (this.element.classList.contains(\"msticky\")) ) {\n $(this.element).stick_in_parent()\n }\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"streamlineable\", \"collapsible\" ]\n\n connect() {\n window.BeerMenus.controllers.streamlinedMenuController = this\n\n this.windowHashChanged(window.location.hash)\n $(window).on(\"hashchange\", (event) => {\n this.windowHashChanged(window.location.hash)\n })\n }\n\n showCollapsibleMenu() {\n this.showStreamlineableElements()\n this.showCollapsibleElements()\n }\n\n showStreamlineableElements() {\n this.streamlineableTargets.forEach(el => {\n el.classList.toggle(\"hidden\", false)\n })\n }\n\n showCollapsibleElements() {\n this.collapsibleTargets.forEach(el => {\n el.classList.toggle(\"hidden\", false)\n })\n }\n\n windowHashChanged(hash) {\n this.performAction(hash.replace(\"#\", \"\"))\n }\n\n performAction(hash) {\n $(\".modal\").modal(\"hide\") // Close any open modal.\n BeerMenus.Checklists.closeDriver()\n\n switch (hash) {\n case \"new-serving\":\n this.removeHash()\n BeerMenus.Checklists.highlightServingForm()\n break\n case \"update-address\":\n this.removeHash()\n BeerMenus.Checklists.showAddressModal(this.barID)\n break\n case \"connect-facebook\":\n this.removeHash()\n BeerMenus.Checklists.showFacebookModal()\n break\n case \"connect-twitter\":\n this.removeHash()\n BeerMenus.Checklists.showTwitterModal()\n break\n case \"new-print-menu\":\n this.removeHash()\n BeerMenus.Checklists.showPrintMenuModal(this.barID)\n break\n case \"add_beers\":\n case \"beers_added\":\n case \"print_welcome\":\n case \"tv_hardware\":\n case \"tv_setup\":\n case \"tv_welcome\":\n case \"not_open\":\n this.removeHash()\n BeerMenus.Checklists.showUpdateMenuMessageModal(hash)\n break\n case \"welcome\":\n this.removeHash()\n BeerMenus.Checklists.spotlight(hash)\n break\n }\n }\n\n removeHash() {\n const state = window.location.pathname + window.location.search\n history.pushState(\"\", document.title, state)\n }\n\n get barID() {\n return this.data.get(\"bar-id\")\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n connect() {\n this._insertMetaTag()\n this._insertScript()\n }\n\n _insertMetaTag() {\n let tag = document.querySelector(\"meta[name='stripe-key']\")\n if (!tag) {\n tag = document.createElement(\"meta\")\n tag.name = \"stripe-key\"\n document.head.appendChild(tag)\n }\n tag.content = this.data.get(\"key\")\n }\n\n _insertScript() {\n ScriptInserter.insert(\"stripe.js\", \"https://js.stripe.com/v3/\", () => {\n new StripeLoader().load()\n })\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n connect() {\n $.ajax(this.data.get(\"path\"))\n .done(data => this.element.innerHTML = data)\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"tab\", \"panel\"]\n static values = { smoothScrollerLink: String }\n\n connect() {\n this.setHashFromURLIfBlank()\n this.showTab()\n this.cancelModal = false\n\n $(window).on(\"hashchange\", (event) => {\n this.hash = window.location.hash.replace(\"#\", \"\")\n this.showTab()\n })\n\n document.body.addEventListener(\"modal:willShow\", (event) => {\n if (this.cancelModal) {\n event.preventDefault()\n this.cancelModal = false\n }\n })\n\n if (this.hasSmoothScrollerLinkValue) {\n this.observeSmoothScrollerLink()\n } else {\n return\n }\n\n }\n\n change(event) {\n event.preventDefault()\n\n this.cancelModal = true\n this.hash = event.currentTarget.dataset[\"hash\"]\n this.showTab()\n this.replaceHistoryState()\n this.updateSmoothScrollerFocus()\n\n const changedEvent = new CustomEvent(\"tab:changed\", {\n bubbles: true,\n detail: this.hash\n })\n this.element.dispatchEvent(changedEvent)\n }\n\n // private\n\n setHashFromURLIfBlank() {\n if (!this.hash && window.location.hash) {\n this.hash = window.location.hash.replace(\"#\", \"\")\n }\n }\n\n showTab() {\n this.tabTargets.forEach(tab => {\n const hash = tab.dataset[\"hash\"]\n tab.classList.toggle(\"pure-tabs-item-selected\", hash == this.hash)\n })\n\n this.panelTargets.forEach(panel => {\n const hash = panel.dataset[\"hash\"]\n panel.classList.toggle(\"hidden\", hash != this.hash)\n })\n\n this.showFirstPanelIfAllHidden()\n this.recalculateStickyHeaders()\n }\n\n showFirstPanelIfAllHidden() {\n const anyPanelVisible = this.panelTargets.some(panel => {\n return !panel.classList.contains(\"hidden\")\n })\n\n if (!anyPanelVisible) {\n this.hash = this.panelTarget.dataset[\"hash\"] // first tab\n this.showTab()\n }\n }\n\n recalculateStickyHeaders() {\n $(document.body).trigger(\"sticky_kit:recalc\")\n }\n\n replaceHistoryState() {\n window.history.replaceState(null, null, `#${this.hash}`)\n }\n\n updateSmoothScrollerFocus() {\n const activeTab = this.tabTargets.find(tab => tab.classList.contains(\"pure-tabs-item-selected\"))\n if (activeTab) {\n const focusId = activeTab.dataset[\"focus\"]\n if (!this.hasSmoothScrollerLinkValue) {\n return\n }\n const smoothScrollerLink = document.querySelector(this.smoothScrollerLinkValue)\n if (focusId && smoothScrollerLink) {\n smoothScrollerLink.setAttribute(\"data-smooth-scroller-focus\", focusId)\n } else {\n }\n }\n }\n\n observeSmoothScrollerLink() {\n const observer = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n if (mutation.addedNodes.length > 0) {\n mutation.addedNodes.forEach((node) => {\n if (node.nodeType == Node.ELEMENT_NODE && (node.id === this.smoothScrollerLinkValue.slice(1) || node.querySelector(this.smoothScrollerLinkValue))) {\n this.updateSmoothScrollerFocus()\n observer.disconnect()\n }\n })\n }\n })\n })\n\n observer.observe(document.querySelector(`div[data-observing=\"${this.smoothScrollerLinkValue}\"]`), { childList: true, subtree: true })\n }\n\n get hash() {\n return this.data.get(\"hash\")\n }\n\n set hash(hash) {\n this.data.set(\"hash\", hash)\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\n/**\n * This implementation was based on the W3C ARIA Guide:\n * https://www.w3.org/WAI/ARIA/apg/patterns/tabs/examples/tabs-automatic/\n */\nexport default class extends Controller {\n static targets = [ \"tab\", \"panel\" ]\n\n connect() {\n this.element.controller = this\n this.change({ currentTarget: this.tabTargets[0] }, false)\n }\n\n change(e, setFocus = true) {\n const tabToSelect = e.currentTarget\n\n // Set tab to selected and show the relevant panel\n tabToSelect.setAttribute(\"aria-selected\", \"true\")\n tabToSelect.removeAttribute(\"tabindex\")\n this.panelTargets.find((panel) => panel.getAttribute(\"aria-labelledby\") === tabToSelect.id).classList.remove(\"hidden\")\n\n // Deselect other tabs\n this.tabTargets.forEach(tab => {\n if (tab != e.currentTarget) {\n tab.setAttribute(\"aria-selected\", \"false\")\n tab.tabIndex = -1\n }\n })\n\n // Hide other panels\n this.panelTargets.forEach(panel => {\n if (panel.getAttribute(\"aria-labelledby\") !== tabToSelect.id) {\n panel.classList.add(\"hidden\")\n }\n })\n\n // Focus on the selected tab if necessary\n if (setFocus) {\n tabToSelect.focus()\n }\n }\n\n get currentTab() {\n return this.tabTargets.find(tab => tab.getAttribute(\"aria-selected\") === \"true\")\n }\n\n setSelectedTo(e) {\n let keyHandled = true\n if (e.key === \"ArrowLeft\") {\n this.setSelectedToPreviousTab()\n } else if (e.key === \"ArrowRight\") {\n this.setSelectedToNextTab()\n } else if (e.key === \"Home\") {\n this.change({ currentTarget: this.tabTargets[0] })\n } else if (e.key === \"End\") {\n this.change({ currentTarget: this.tabTargets[this.tabTargets.length - 1] })\n } else {\n keyHandled = false\n }\n\n if (!keyHandled) return\n\n e.stopPropagation()\n e.preventDefault()\n }\n\n setSelectedToPreviousTab() {\n let index = this.tabTargets.indexOf(this.currentTab)\n index--;\n\n if (index === -1) {\n index = this.tabTargets.length - 1\n }\n this.change({ currentTarget: this.tabTargets[index] })\n }\n\n setSelectedToNextTab() {\n let index = this.tabTargets.indexOf(this.currentTab)\n index++;\n\n if (index === this.tabTargets.length) {\n index = 0\n }\n this.change({ currentTarget: this.tabTargets[index] })\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"wrapper\" ]\n\n stepValue = 0.05\n columnsSelector = \".columns\"\n lastItemSelector = \"li:last-of-type\"\n bodyVerticalClassName = \"vertical\"\n overflowWarningShown = false\n\n async connect() {\n this.minFontSize = this.data.has(\"minfontsize\") ? parseFloat(this.data.get(\"minfontsize\")) : 0.8\n this.maxFontSize = this.data.has(\"maxfontsize\") ? parseFloat(this.data.get(\"maxfontsize\")) : 2.0\n if (this.data.has(\"lastitem\")) this.lastItemSelector = this.data.get(\"lastitem\")\n\n this.determineCoordinates()\n\n this.resizeObserver = new ResizeObserver(this.fitContent.bind(this))\n this.resizeObserver.observe(this.element)\n\n // Ensure the content fit is attempted once webfonts have loaded, or\n // at least once 5 seconds have passed\n const fontsTimer = setTimeout(() => this.fitContent(), 5000)\n await document.fonts.ready\n clearTimeout(fontsTimer)\n this.fitContent()\n }\n\n disconnect() {\n this.resizeObserver.disconnect()\n }\n\n /**\n * Looks at the orientation of the \"screen\" (horizontal or vertical) and sets\n * up the coordinate property defaults\n */\n determineCoordinates() {\n const vertical = this.bodyVerticalClassName\n\n if (\n (document.body.classList.contains(vertical) && this.data.get(\"columns\") != \"1\") ||\n (!document.body.classList.contains(vertical) && this.data.get(\"columns\") == \"1\")\n ) {\n // The case where the screen is vertical and multi-column, or horizontal\n // with only one column\n this.coordinates = { pos: \"y\", size: \"height\" }\n } else {\n // The case where the screen is horiztonal and multi-column, or vertical\n // with only column\n this.coordinates = { pos: \"x\", size: \"width\" }\n\n // and in that latter case, the x coordinates are reversed\u2026aka x will be a\n // negative number for overflows instead of positive\n this.coordinates.invert = document.body.classList.contains(vertical)\n }\n }\n\n get normalOverflowing() {\n let lastItemPos = this.lastItem.getBoundingClientRect()\n let columnsRect = this.columns.getBoundingClientRect()\n\n if (this.coordinates.pos == \"y\") {\n // the last item will be positioned below the bottom edge of the\n // column if there's an overflow\n lastItemPos = lastItemPos[this.coordinates.pos] + lastItemPos[this.coordinates.size] - columnsRect[this.coordinates.pos]\n } else {\n // multicolumn: the last item will be offscreen if there's an overflow\n lastItemPos = lastItemPos[this.coordinates.pos]\n }\n\n return lastItemPos > columnsRect[this.coordinates.size]\n }\n\n get invertedOverflowing() {\n return this.lastItem.getBoundingClientRect()[this.coordinates.pos] <\n this.columns.getBoundingClientRect()[this.coordinates.pos]\n }\n\n get isOverflowing() {\n return (!this.coordinates.invert && this.normalOverflowing) ||\n (this.coordinates.invert && this.invertedOverflowing)\n }\n\n /**\n * Runs through an algorithm to start with a maximum font size like 1.7vw,\n * then decrement by 0.05 until all the items in the columns are visible,\n * or a minimum font size has been reached.\n */\n fitContent() {\n document.body.style.fontSize = `${this.maxFontSize}vw`\n let fontSize = this.maxFontSize\n\n this.columns = this.element.querySelector(this.columnsSelector)\n this.lastItem = this.element.querySelector(this.lastItemSelector)\n\n let complete = false\n while (!complete) {\n if (fontSize > this.minFontSize && this.isOverflowing) {\n fontSize = (fontSize - this.stepValue).toFixed(2)\n document.body.style.fontSize = `${fontSize}vw`\n } else if (fontSize <= this.minFontSize && this.isOverflowing) {\n this.overflowWarning = true\n complete = true\n } else {\n this.overflowWarning = false\n complete = true\n }\n }\n\n this.wrapperTarget.style.visibility = \"visible\"\n }\n\n set overflowWarning(shown) {\n if (document.body.dataset.previewing !== \"true\") return\n\n window.parent.document.querySelector(\"#overflow-warning\").hidden = !shown\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n click(event) {\n event.preventDefault()\n this.track().always(this.redirectTo(event.currentTarget.href))\n }\n\n // private\n\n track() {\n return $.ajax(\"/api/internal/redis\", {\n method: \"POST\",\n timeout: 5000,\n data: {\n key: this.data.get(\"key\"),\n id: this.data.get(\"id\"),\n },\n })\n }\n\n redirectTo(href) {\n window.location.href = href\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"extra\", \"editor\", \"fontsSelect\", \"fontSizesSelect\" ]\n\n async connect() {\n if (this.hasExtraTarget) {\n this.setupToolbar()\n }\n\n window.Trix = (await import(\"trix\")).default\n\n if (this.data.get(\"fonts\") && this.data.get(\"fonts\") != \"\") {\n this.fonts = JSON.parse(this.data.get(\"fonts\"))\n this.fonts.forEach(([fontId, fontName]) => {\n Trix.config.textAttributes[fontId] = {\n style: { fontFamily: fontName },\n parser: (element) => {\n return element.style.fontFamily.includes(fontName)\n },\n inheritable: true\n }\n })\n\n Trix.config.blockAttributes[\"align-left\"] = {\n tagName: \"text-align-left\",\n nestable: false,\n exclusive: true,\n }\n\n Trix.config.blockAttributes[\"align-center\"] = {\n tagName: \"text-align-center\",\n nestable: false,\n exclusive: true,\n }\n\n Trix.config.blockAttributes[\"align-right\"] = {\n tagName: \"text-align-right\",\n nestable: false,\n exclusive: true,\n }\n }\n\n if (this.data.get(\"fontSizes\") && this.data.get(\"fontSizes\") != \"\") {\n this.fontSizes = JSON.parse(this.data.get(\"fontSizes\"))\n this.fontSizes.forEach(([sizeId, sizeName]) => {\n Trix.config.textAttributes[sizeId] = {\n style: { fontSize: sizeName },\n parser: (element) => {\n return element.style.fontSize.includes(sizeName)\n },\n inheritable: true\n }\n })\n }\n\n if (this.hasEditorTarget) {\n const editor = this.editorTarget.content.cloneNode(true)\n this.element.append(editor)\n }\n }\n\n async setupToolbar() {\n (await import(\"select2/dist/js/select2.full.js\")).default() // init the plugin\n\n const extraTools = this.extraTarget.content.cloneNode(true)\n this.element.addEventListener(\"trix-initialize\", event => { \n event.target.toolbarElement.\n querySelector(\".trix-button-group--text-tools\").\n append(extraTools)\n\n $(this.fontSizesSelectTarget).select2({\n minimumResultsForSearch: Infinity,\n templateResult: (data, container) => {\n if (data.element) container.style.fontSize = data.element.dataset.size\n return data.text\n },\n }).on(\"select2:select\", () => {\n const event = new CustomEvent(\"customFontSize:selected\", { bubbles: true })\n this.fontSizesSelectTarget.dispatchEvent(event)\n }).on(\"select2:open\", () => {\n // We need this for when the user selects the same exact option\n setTimeout(() => {\n document.querySelector(\".select2-results__option[aria-selected=true]\").addEventListener(\"mouseup\", () => {\n const event = new CustomEvent(\"customFontSize:selected\", { bubbles: true })\n this.fontSizesSelectTarget.dispatchEvent(event)\n })\n })\n })\n })\n }\n\n changeFonts(event) {\n this.changeAttributes(event.target.value, this.fonts)\n }\n\n changeSizes(event) {\n this.changeAttributes(event.target.value, this.fontSizes)\n }\n\n sizesClick(event) {\n console.info(event)\n }\n\n changeAttributes(selection, options) {\n const element = this.element.querySelector(\"trix-editor\")\n const blankStart = element.editor.getDocument().toString() === \"\\n\"\n\n if (blankStart) element.editor.setSelectedRange([0, 0])\n\n options.forEach(([attrId, _attrName]) => {\n element.editor.deactivateAttribute(attrId)\n })\n\n if (!selection.startsWith(\"-\")) element.editor.activateAttribute(selection)\n if (blankStart) this.newSelection()\n }\n\n alignLeft() {\n const element = this.element.querySelector(\"trix-editor\")\n\n element.editor.deactivateAttribute(\"align-center\")\n element.editor.deactivateAttribute(\"align-right\")\n element.editor.activateAttribute(\"align-left\")\n }\n\n alignCenter() {\n const element = this.element.querySelector(\"trix-editor\")\n\n element.editor.deactivateAttribute(\"align-left\")\n element.editor.deactivateAttribute(\"align-right\")\n element.editor.activateAttribute(\"align-center\")\n }\n\n alignRight() {\n const element = this.element.querySelector(\"trix-editor\")\n\n element.editor.deactivateAttribute(\"align-left\")\n element.editor.deactivateAttribute(\"align-center\")\n element.editor.activateAttribute(\"align-right\")\n }\n\n newSelection(event) {\n const element = this.element.querySelector(\"trix-editor\")\n\n let fontFound = false\n let fontSizeFound = false\n let alignmentFound = false\n\n Object.keys(element.editor.composition.currentAttributes).forEach(key => {\n if (this.fontsSelectTarget.querySelector(`option[value=\"${key}\"]`)) {\n $(this.fontsSelectTarget).val(key).trigger(\"change\")\n fontFound = true\n } else if (this.fontSizesSelectTarget.querySelector(`option[value=\"${key}\"]`)) {\n $(this.fontSizesSelectTarget).val(key).trigger(\"change\")\n fontSizeFound = true\n }\n\n if (key.startsWith(\"align-\")) alignmentFound = true\n })\n\n if (!fontFound) $(this.fontsSelectTarget).val(\"-default-\").trigger(\"change\")\n if (!fontSizeFound) $(this.fontSizesSelectTarget).val(\"-default-\").trigger(\"change\")\n if (!alignmentFound) this.element.querySelector('[data-trix-attribute=\"align-left\"]').dataset.trixActive = true\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static values = {\n siteKey: String,\n theme: String,\n size: String,\n appearance: String,\n action: String,\n buttonSelector: String,\n disableButton: Boolean\n }\n\n static targets = [\"tokenField\"]\n\n connect() {\n if (window.turnstile) {\n this.renderTurnstile()\n } else {\n if (!window.securityWidgetCallbacks) {\n window.securityWidgetCallbacks = []\n window.securityWidgetCb = () => {\n if (window.securityWidgetCallbacks && window.securityWidgetCallbacks.length > 0) {\n window.securityWidgetCallbacks.forEach(callback => callback())\n }\n }\n }\n window.securityWidgetCallbacks.push(() => this.renderTurnstile())\n }\n }\n\n renderTurnstile() {\n if (this.button && this.disableButtonValue) {\n this.button.disabled = true\n }\n\n const visibleClasses = ['visible']\n\n this.id = turnstile.render(`#${this.element.id}`, {\n sitekey: this.siteKeyValue,\n theme: this.themeValue,\n size: this.sizeValue,\n action: this.actionValue,\n appearance: this.appearanceValue,\n callback: (token) => {\n if (this.hasTokenFieldTarget) {\n this.tokenFieldTarget.value = token\n }\n if (this.button && this.disableButtonValue) {\n this.button.disabled = false\n }\n },\n \"before-interactive-callback\": () => this.element.classList.add(...visibleClasses)\n })\n }\n\n disconnect() {\n if (window.turnstile && this.id) {\n turnstile.remove(this.id)\n }\n\n if (window.securityWidgetCallbacks) {\n const callbackIndex = window.securityWidgetCallbacks.findIndex(\n callback => callback.toString().includes(this.element.id)\n )\n\n if (callbackIndex !== -1) {\n window.securityWidgetCallbacks.splice(callbackIndex, 1)\n }\n }\n }\n\n get form() {\n return this.element.closest(\"form\")\n }\n\n get button() {\n if (this.hasButtonSelectorValue) {\n return document.querySelector(this.buttonSelectorValue)\n }\n\n if (this.form) {\n return this.form.querySelector(\"input[type=submit], button[type=submit]\")\n }\n\n return null\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"url\", \"currentScreen\", \"previous\", \"next\", \"preview\" ]\n\n connect() {\n this.urls = this.urlTargets.map(el => el.innerText)\n\n var currentScreen = this.getCurrentScreen()\n this.previousTarget.setAttribute(\"href\", this.urls[currentScreen - 1])\n this.nextTarget.setAttribute(\"href\", this.urls[currentScreen + 1])\n\n this.updateDisabledState()\n }\n\n previous(event) {\n event.preventDefault()\n\n var url = event.target.getAttribute(\"href\")\n this.previewTarget.setAttribute(\"src\", url)\n\n var currentScreen = this.getCurrentScreen()\n this.setCurrentScreen(currentScreen - 1)\n\n this.previousTarget.setAttribute(\"href\", this.urls[currentScreen - 2])\n this.nextTarget.setAttribute(\"href\", this.urls[currentScreen])\n\n this.updateDisabledState()\n }\n\n next(event) {\n event.preventDefault()\n\n var url = event.target.getAttribute(\"href\")\n this.previewTarget.setAttribute(\"src\", url)\n\n var currentScreen = this.getCurrentScreen()\n this.setCurrentScreen(currentScreen + 1)\n\n this.previousTarget.setAttribute(\"href\", this.urls[currentScreen])\n this.nextTarget.setAttribute(\"href\", this.urls[currentScreen + 2])\n\n this.updateDisabledState()\n }\n\n updateDisabledState() {\n var currentScreen = this.getCurrentScreen()\n\n if (currentScreen <= 0) {\n this.previousTarget.classList.add(\"disabled\")\n } else {\n this.previousTarget.classList.remove(\"disabled\")\n }\n\n if (currentScreen >= this.urls.length - 1) {\n this.nextTarget.classList.add(\"disabled\")\n } else {\n this.nextTarget.classList.remove(\"disabled\")\n }\n }\n\n getCurrentScreen() {\n return parseInt(this.currentScreenTarget.innerText) - 1\n }\n\n setCurrentScreen(screen) {\n this.currentScreenTarget.innerText = screen + 1\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"confirmation\"]\n\n update(event) {\n this.confirmationTarget.classList.add(\"hidden\")\n const checked = event.currentTarget.checked\n\n $.ajax({\n url: `/users/${this.data.get(\"user-id\")}/preferences`,\n method: \"PATCH\",\n data: {\n preference: event.currentTarget.value,\n value: event.currentTarget.checked\n }\n }).done(() => {\n this.confirmationTarget.classList.remove(\"hidden\")\n\n const customEvent = new CustomEvent(\"skip-empty-suggestions-modal-change\", {\n bubbles: true,\n detail: checked,\n })\n document.body.dispatchEvent(customEvent)\n })\n }\n\n dismiss(event) {\n event.preventDefault()\n\n this.element.classList.add(\"hidden\")\n\n $.ajax({\n url: `/users/${this.data.get(\"user-id\")}/preferences`,\n method: \"PATCH\",\n data: {\n preference: this.data.get(\"preference\"),\n value: true\n }\n })\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"video\"]\n\n connect() {\n\n const src = $(this.videoTarget).attr(\"src\")\n const origin = this.data.get(\"origin\")\n\n $(this.element).on('show.bs.modal', (event) => {\n if (origin == null) {\n $(this.videoTarget).attr('src', `${src}?autoplay=1`);\n }\n else {\n $(this.videoTarget).attr('src', `${src}?autoplay=1&origin=${origin}`);\n }\n })\n\n $(this.element).on('hide.bs.modal', (event) => {\n $(this.videoTarget).attr('src', ' ');\n })\n\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n connect() {\n this.calculate()\n }\n\n calculate(){\n const vh = window.innerHeight * 0.01\n document.documentElement.style.setProperty('--vh', `${vh}px`);\n }\n}", "import { Controller } from \"@hotwired/stimulus\"\nexport default class extends Controller {\n initialize() {\n this.intersectionObserver = new IntersectionObserver(entries => this.processIntersectionEntries(entries))\n }\n connect() {\n this.intersectionObserver.observe(this.element)\n }\n disconnect() {\n this.intersectionObserver.unobserve(this.element)\n }\n\n // Private\n processIntersectionEntries(entries) {\n entries.forEach(entry => {\n this.element.classList.toggle(this.data.get(\"class\"), entry.isIntersecting)\n })\n }\n}", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"hidden\"]\n\n toggle(event) {\n event.preventDefault();\n\n const anchor = this.data.get(\"id\")\n const offset = parseInt(this.data.get(\"offset\")) || 0\n\n if (this.hiddenTarget.classList.contains('hidden')){\n $(\"html, body\").animate({\n scrollTop: $(`#${anchor}`).offset().top - offset}, 300)\n }\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"content\", \"hidden\", \"required\" ]\n\n toggle(event) {\n event.preventDefault()\n\n if (this.contentTargets.length > 0) {\n this.contentTargets.forEach(t => t.classList.toggle(\"hidden\"))\n }\n\n if (this.hiddenTargets.length > 0) {\n this.hiddenTargets.forEach(t => t.classList.toggle(\"hidden\"))\n }\n\n if (this.requiredTargets.length > 0) {\n this.requiredTargets.forEach(t => t.classList.toggle(\"required\"))\n }\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"source\", \"hidden\" ]\n\n toggle(event) {\n if (this.sourceTarget.checked) {\n this.hiddenTarget.classList.remove(\"hidden\")\n } else {\n this.hiddenTarget.classList.add(\"hidden\")\n }\n }\n}\n", "import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n change(event) {\n const previewSize = event.target.value\n const menuPreview = this.locateMenuPreview()\n\n switch (previewSize) {\n case \"mobile\":\n menuPreview.style.width = \"var(--preview-mobile-width)\"\n menuPreview.style.height = \"var(--preview-mobile-height)\"\n break;\n case \"tablet\":\n menuPreview.style.width = \"var(--preview-tablet-width)\"\n menuPreview.style.height = \"var(--preview-tablet-height)\"\n break;\n case \"desktop\":\n menuPreview.style.width = \"var(--preview-desktop-width)\"\n menuPreview.style.height = \"var(--preview-desktop-height)\"\n }\n }\n\n locateMenuPreview() {\n return document.querySelector(\"beermenus-web\").closest(\".pm-menu-chrome\")\n }\n}\n", "\n import * as module0 from './controllers/accordion-controller.js';import * as module1 from './controllers/accordion2-controller.js';import * as module2 from './controllers/admin-beer-controller.js';import * as module3 from './controllers/admin-merge-controller.js';import * as module4 from './controllers/auto-save-controller.js';import * as module5 from './controllers/auto-textfield-height-controller.js';import * as module6 from './controllers/autocomplete-controller.js';import * as module7 from './controllers/availability-promo-controller.js';import * as module8 from './controllers/beacon-controller.js';import * as module9 from './controllers/beer-autocomplete-controller.js';import * as module10 from './controllers/beer-info-controller.js';import * as module11 from './controllers/beer-suggestions-controller.js';import * as module12 from './controllers/beers-added-modal-controller.js';import * as module13 from './controllers/block-modal-controller.js';import * as module14 from './controllers/brewery-autocomplete-controller.js';import * as module15 from './controllers/brewery-multi-select-controller.js';import * as module16 from './controllers/bulk-move-controller.js';import * as module17 from './controllers/calculator-controller.js';import * as module18 from './controllers/calendly-controller.js';import * as module19 from './controllers/charts-controller.js';import * as module20 from './controllers/checkbox-counter-controller.js';import * as module21 from './controllers/checkbox-submit-controller.js';import * as module22 from './controllers/checkbox-toggle-controller.js';import * as module23 from './controllers/checklist-accordion-controller.js';import * as module24 from './controllers/checklists-controller.js';import * as module25 from './controllers/choose-saved-card-controller.js';import * as module26 from './controllers/clipboard_controller.js';import * as module27 from './controllers/closeable-controller.js';import * as module28 from './controllers/codemirror-controller.js';import * as module29 from './controllers/collapsible-controller.js';import * as module30 from './controllers/collapsible-simple-controller.js';import * as module31 from './controllers/condition-ids-controller.js';import * as module32 from './controllers/conditional-input-controller.js';import * as module33 from './controllers/custom-product-autocomplete-controller.js';import * as module34 from './controllers/date-input-controller.js';import * as module35 from './controllers/digital-display-controller.js';import * as module36 from './controllers/filter-templates-controller.js';import * as module37 from './controllers/fonts-controller.js';import * as module38 from './controllers/google-autocomplete-controller.js';import * as module39 from './controllers/hamburger-menu-controller.js';import * as module40 from './controllers/hiding-header-controller.js';import * as module41 from './controllers/honeybadger-controller.js';import * as module42 from './controllers/image-background-remover-controller.js';import * as module43 from './controllers/image-editor-controller.js';import * as module44 from './controllers/location-autocomplete-controller.js';import * as module45 from './controllers/masonry-grid-controller.js';import * as module46 from './controllers/menu-controller.js';import * as module47 from './controllers/menu-search-controller.js';import * as module48 from './controllers/menu-section-controller.js';import * as module49 from './controllers/menu-sections-controller.js';import * as module50 from './controllers/modular-controller.js';import * as module51 from './controllers/multi-select-controller.js';import * as module52 from './controllers/order-search-controller.js';import * as module53 from './controllers/orders-controller.js';import * as module54 from './controllers/pickup-locations-controller.js';import * as module55 from './controllers/place-lead-controller.js';import * as module56 from './controllers/price-calculator-controller.js';import * as module57 from './controllers/print-iframe-controller.js';import * as module58 from './controllers/print-menu-landing-page-controller.js';import * as module59 from './controllers/print-menus-controller.js';import * as module60 from './controllers/print-preview-controller.js';import * as module61 from './controllers/product-autocomplete-controller.js';import * as module62 from './controllers/product-type-controller.js';import * as module63 from './controllers/property-segments-controller.js';import * as module64 from './controllers/purchase-limit-controller.js';import * as module65 from './controllers/region-preview-controller.js';import * as module66 from './controllers/remote-file-form-controller.js';import * as module67 from './controllers/scroll-to-top-controller.js';import * as module68 from './controllers/segmented_field_controller.js';import * as module69 from './controllers/segments-controller.js';import * as module70 from './controllers/select-all-controller.js';import * as module71 from './controllers/serving-controller.js';import * as module72 from './controllers/servings-controller.js';import * as module73 from './controllers/shoelace-controller.js';import * as module74 from './controllers/show-more-controller.js';import * as module75 from './controllers/simple-beer-autocomplete-controller.js';import * as module76 from './controllers/simple-modular-controller.js';import * as module77 from './controllers/smooth-scroller-controller.js';import * as module78 from './controllers/sortable-controller.js';import * as module79 from './controllers/sticky-controller.js';import * as module80 from './controllers/streamlined-menu-controller.js';import * as module81 from './controllers/stripe-controller.js';import * as module82 from './controllers/structured-data-controller.js';import * as module83 from './controllers/tabs-controller.js';import * as module84 from './controllers/tabs2-controller.js';import * as module85 from './controllers/textfit-controller.js';import * as module86 from './controllers/tracked-clicks-controller.js';import * as module87 from './controllers/trix-controller.js';import * as module88 from './controllers/turnstile_controller.js';import * as module89 from './controllers/tv-preview-controller.js';import * as module90 from './controllers/user-preferences-controller.js';import * as module91 from './controllers/video-modal-controller.js';import * as module92 from './controllers/viewport-calculate-controller.js';import * as module93 from './controllers/viewport-entrance-toggle-controller.js';import * as module94 from './controllers/visible-anchor-controller.js';import * as module95 from './controllers/visible-controller.js';import * as module96 from './controllers/visible-from-radio-controller.js';import * as module97 from './controllers/web-menu-preview-sizes-controller.js'\n const modules = {\"./controllers/accordion-controller.js\": module0,\"./controllers/accordion2-controller.js\": module1,\"./controllers/admin-beer-controller.js\": module2,\"./controllers/admin-merge-controller.js\": module3,\"./controllers/auto-save-controller.js\": module4,\"./controllers/auto-textfield-height-controller.js\": module5,\"./controllers/autocomplete-controller.js\": module6,\"./controllers/availability-promo-controller.js\": module7,\"./controllers/beacon-controller.js\": module8,\"./controllers/beer-autocomplete-controller.js\": module9,\"./controllers/beer-info-controller.js\": module10,\"./controllers/beer-suggestions-controller.js\": module11,\"./controllers/beers-added-modal-controller.js\": module12,\"./controllers/block-modal-controller.js\": module13,\"./controllers/brewery-autocomplete-controller.js\": module14,\"./controllers/brewery-multi-select-controller.js\": module15,\"./controllers/bulk-move-controller.js\": module16,\"./controllers/calculator-controller.js\": module17,\"./controllers/calendly-controller.js\": module18,\"./controllers/charts-controller.js\": module19,\"./controllers/checkbox-counter-controller.js\": module20,\"./controllers/checkbox-submit-controller.js\": module21,\"./controllers/checkbox-toggle-controller.js\": module22,\"./controllers/checklist-accordion-controller.js\": module23,\"./controllers/checklists-controller.js\": module24,\"./controllers/choose-saved-card-controller.js\": module25,\"./controllers/clipboard_controller.js\": module26,\"./controllers/closeable-controller.js\": module27,\"./controllers/codemirror-controller.js\": module28,\"./controllers/collapsible-controller.js\": module29,\"./controllers/collapsible-simple-controller.js\": module30,\"./controllers/condition-ids-controller.js\": module31,\"./controllers/conditional-input-controller.js\": module32,\"./controllers/custom-product-autocomplete-controller.js\": module33,\"./controllers/date-input-controller.js\": module34,\"./controllers/digital-display-controller.js\": module35,\"./controllers/filter-templates-controller.js\": module36,\"./controllers/fonts-controller.js\": module37,\"./controllers/google-autocomplete-controller.js\": module38,\"./controllers/hamburger-menu-controller.js\": module39,\"./controllers/hiding-header-controller.js\": module40,\"./controllers/honeybadger-controller.js\": module41,\"./controllers/image-background-remover-controller.js\": module42,\"./controllers/image-editor-controller.js\": module43,\"./controllers/location-autocomplete-controller.js\": module44,\"./controllers/masonry-grid-controller.js\": module45,\"./controllers/menu-controller.js\": module46,\"./controllers/menu-search-controller.js\": module47,\"./controllers/menu-section-controller.js\": module48,\"./controllers/menu-sections-controller.js\": module49,\"./controllers/modular-controller.js\": module50,\"./controllers/multi-select-controller.js\": module51,\"./controllers/order-search-controller.js\": module52,\"./controllers/orders-controller.js\": module53,\"./controllers/pickup-locations-controller.js\": module54,\"./controllers/place-lead-controller.js\": module55,\"./controllers/price-calculator-controller.js\": module56,\"./controllers/print-iframe-controller.js\": module57,\"./controllers/print-menu-landing-page-controller.js\": module58,\"./controllers/print-menus-controller.js\": module59,\"./controllers/print-preview-controller.js\": module60,\"./controllers/product-autocomplete-controller.js\": module61,\"./controllers/product-type-controller.js\": module62,\"./controllers/property-segments-controller.js\": module63,\"./controllers/purchase-limit-controller.js\": module64,\"./controllers/region-preview-controller.js\": module65,\"./controllers/remote-file-form-controller.js\": module66,\"./controllers/scroll-to-top-controller.js\": module67,\"./controllers/segmented_field_controller.js\": module68,\"./controllers/segments-controller.js\": module69,\"./controllers/select-all-controller.js\": module70,\"./controllers/serving-controller.js\": module71,\"./controllers/servings-controller.js\": module72,\"./controllers/shoelace-controller.js\": module73,\"./controllers/show-more-controller.js\": module74,\"./controllers/simple-beer-autocomplete-controller.js\": module75,\"./controllers/simple-modular-controller.js\": module76,\"./controllers/smooth-scroller-controller.js\": module77,\"./controllers/sortable-controller.js\": module78,\"./controllers/sticky-controller.js\": module79,\"./controllers/streamlined-menu-controller.js\": module80,\"./controllers/stripe-controller.js\": module81,\"./controllers/structured-data-controller.js\": module82,\"./controllers/tabs-controller.js\": module83,\"./controllers/tabs2-controller.js\": module84,\"./controllers/textfit-controller.js\": module85,\"./controllers/tracked-clicks-controller.js\": module86,\"./controllers/trix-controller.js\": module87,\"./controllers/turnstile_controller.js\": module88,\"./controllers/tv-preview-controller.js\": module89,\"./controllers/user-preferences-controller.js\": module90,\"./controllers/video-modal-controller.js\": module91,\"./controllers/viewport-calculate-controller.js\": module92,\"./controllers/viewport-entrance-toggle-controller.js\": module93,\"./controllers/visible-anchor-controller.js\": module94,\"./controllers/visible-controller.js\": module95,\"./controllers/visible-from-radio-controller.js\": module96,\"./controllers/web-menu-preview-sizes-controller.js\": module97,\n };\n export default modules;\n ", "import { Controller } from \"@hotwired/stimulus\";\nconst _Dialog = class _Dialog extends Controller {\n initialize() {\n this.forceClose = this.forceClose.bind(this);\n }\n connect() {\n this.openValue && this.open(), document.addEventListener(\"turbo:before-render\", this.forceClose);\n }\n disconnect() {\n document.removeEventListener(\"turbo:before-render\", this.forceClose);\n }\n open() {\n this.dialogTarget.showModal();\n }\n close() {\n this.dialogTarget.setAttribute(\"closing\", \"\"), Promise.all(this.dialogTarget.getAnimations().map((animation) => animation.finished)).then(() => {\n this.dialogTarget.removeAttribute(\"closing\"), this.dialogTarget.close();\n });\n }\n backdropClose(event) {\n event.target === this.dialogTarget && this.close();\n }\n forceClose() {\n this.dialogTarget.close();\n }\n};\n_Dialog.targets = [\"dialog\"], _Dialog.values = {\n open: {\n type: Boolean,\n default: !1\n }\n};\nlet Dialog = _Dialog;\nexport {\n Dialog as default\n};\n", "/*\n * stimulus-use 0.52.1\n */\nimport { Controller } from \"@hotwired/stimulus\";\n\nconst method = (controller, methodName) => {\n const method = controller[methodName];\n if (typeof method == \"function\") {\n return method;\n } else {\n return (...args) => {};\n }\n};\n\nconst composeEventName = (name, controller, eventPrefix) => {\n let composedName = name;\n if (eventPrefix === true) {\n composedName = `${controller.identifier}:${name}`;\n } else if (typeof eventPrefix === \"string\") {\n composedName = `${eventPrefix}:${name}`;\n }\n return composedName;\n};\n\nconst extendedEvent = (type, event, detail) => {\n const {bubbles: bubbles, cancelable: cancelable, composed: composed} = event || {\n bubbles: true,\n cancelable: true,\n composed: true\n };\n if (event) {\n Object.assign(detail, {\n originalEvent: event\n });\n }\n const customEvent = new CustomEvent(type, {\n bubbles: bubbles,\n cancelable: cancelable,\n composed: composed,\n detail: detail\n });\n return customEvent;\n};\n\nfunction isElementInViewport(el) {\n const rect = el.getBoundingClientRect();\n const windowHeight = window.innerHeight || document.documentElement.clientHeight;\n const windowWidth = window.innerWidth || document.documentElement.clientWidth;\n const vertInView = rect.top <= windowHeight && rect.top + rect.height > 0;\n const horInView = rect.left <= windowWidth && rect.left + rect.width > 0;\n return vertInView && horInView;\n}\n\nfunction camelize(value) {\n return value.replace(/(?:[_-])([a-z0-9])/g, ((_, char) => char.toUpperCase()));\n}\n\n/******************************************************************************\nCopyright (c) Microsoft Corporation.\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n***************************************************************************** */\n/* global Reflect, Promise */ function __rest(s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];\n }\n return t;\n}\n\nconst defaultOptions$8 = {\n debug: false,\n logger: console,\n dispatchEvent: true,\n eventPrefix: true\n};\n\nclass StimulusUse {\n constructor(controller, options = {}) {\n var _a, _b, _c;\n this.log = (functionName, args) => {\n if (!this.debug) return;\n this.logger.groupCollapsed(`%c${this.controller.identifier} %c#${functionName}`, \"color: #3B82F6\", \"color: unset\");\n this.logger.log(Object.assign({\n controllerId: this.controllerId\n }, args));\n this.logger.groupEnd();\n };\n this.warn = message => {\n this.logger.warn(`%c${this.controller.identifier} %c${message}`, \"color: #3B82F6; font-weight: bold\", \"color: unset\");\n };\n this.dispatch = (eventName, details = {}) => {\n if (this.dispatchEvent) {\n const {event: event} = details, eventDetails = __rest(details, [ \"event\" ]);\n const customEvent = this.extendedEvent(eventName, event || null, eventDetails);\n this.targetElement.dispatchEvent(customEvent);\n this.log(\"dispatchEvent\", Object.assign({\n eventName: customEvent.type\n }, eventDetails));\n }\n };\n this.call = (methodName, args = {}) => {\n const method = this.controller[methodName];\n if (typeof method == \"function\") {\n return method.call(this.controller, args);\n }\n };\n this.extendedEvent = (name, event, detail) => {\n const {bubbles: bubbles, cancelable: cancelable, composed: composed} = event || {\n bubbles: true,\n cancelable: true,\n composed: true\n };\n if (event) {\n Object.assign(detail, {\n originalEvent: event\n });\n }\n const customEvent = new CustomEvent(this.composeEventName(name), {\n bubbles: bubbles,\n cancelable: cancelable,\n composed: composed,\n detail: detail\n });\n return customEvent;\n };\n this.composeEventName = name => {\n let composedName = name;\n if (this.eventPrefix === true) {\n composedName = `${this.controller.identifier}:${name}`;\n } else if (typeof this.eventPrefix === \"string\") {\n composedName = `${this.eventPrefix}:${name}`;\n }\n return composedName;\n };\n this.debug = (_b = (_a = options === null || options === void 0 ? void 0 : options.debug) !== null && _a !== void 0 ? _a : controller.application.stimulusUseDebug) !== null && _b !== void 0 ? _b : defaultOptions$8.debug;\n this.logger = (_c = options === null || options === void 0 ? void 0 : options.logger) !== null && _c !== void 0 ? _c : defaultOptions$8.logger;\n this.controller = controller;\n this.controllerId = controller.element.id || controller.element.dataset.id;\n this.targetElement = (options === null || options === void 0 ? void 0 : options.element) || controller.element;\n const {dispatchEvent: dispatchEvent, eventPrefix: eventPrefix} = Object.assign({}, defaultOptions$8, options);\n Object.assign(this, {\n dispatchEvent: dispatchEvent,\n eventPrefix: eventPrefix\n });\n this.controllerInitialize = controller.initialize.bind(controller);\n this.controllerConnect = controller.connect.bind(controller);\n this.controllerDisconnect = controller.disconnect.bind(controller);\n }\n}\n\nconst defaultOptions$7 = {\n eventPrefix: true,\n bubbles: true,\n cancelable: true\n};\n\nclass UseDispatch extends StimulusUse {\n constructor(controller, options = {}) {\n var _a, _b, _c, _d;\n super(controller, options);\n this.dispatch = (eventName, detail = {}) => {\n const {controller: controller, targetElement: targetElement, eventPrefix: eventPrefix, bubbles: bubbles, cancelable: cancelable, log: log, warn: warn} = this;\n Object.assign(detail, {\n controller: controller\n });\n const eventNameWithPrefix = composeEventName(eventName, this.controller, eventPrefix);\n const event = new CustomEvent(eventNameWithPrefix, {\n detail: detail,\n bubbles: bubbles,\n cancelable: cancelable\n });\n targetElement.dispatchEvent(event);\n warn(\"`useDispatch()` is deprecated. Please use the built-in `this.dispatch()` function from Stimulus. You can find more information on how to upgrade at: https://stimulus-use.github.io/stimulus-use/#/use-dispatch\");\n log(\"dispatch\", {\n eventName: eventNameWithPrefix,\n detail: detail,\n bubbles: bubbles,\n cancelable: cancelable\n });\n return event;\n };\n this.targetElement = (_a = options.element) !== null && _a !== void 0 ? _a : controller.element;\n this.eventPrefix = (_b = options.eventPrefix) !== null && _b !== void 0 ? _b : defaultOptions$7.eventPrefix;\n this.bubbles = (_c = options.bubbles) !== null && _c !== void 0 ? _c : defaultOptions$7.bubbles;\n this.cancelable = (_d = options.cancelable) !== null && _d !== void 0 ? _d : defaultOptions$7.cancelable;\n this.enhanceController();\n }\n enhanceController() {\n Object.assign(this.controller, {\n dispatch: this.dispatch\n });\n }\n}\n\nconst useDispatch = (controller, options = {}) => new UseDispatch(controller, options);\n\nconst defaultOptions$6 = {\n overwriteDispatch: true\n};\n\nconst useApplication = (controller, options = {}) => {\n const {overwriteDispatch: overwriteDispatch} = Object.assign({}, defaultOptions$6, options);\n Object.defineProperty(controller, \"isPreview\", {\n get() {\n return document.documentElement.hasAttribute(\"data-turbolinks-preview\") || document.documentElement.hasAttribute(\"data-turbo-preview\");\n }\n });\n Object.defineProperty(controller, \"isConnected\", {\n get() {\n return !!Array.from(this.context.module.connectedContexts).find((c => c === this.context));\n }\n });\n Object.defineProperty(controller, \"csrfToken\", {\n get() {\n return this.metaValue(\"csrf-token\");\n }\n });\n if (overwriteDispatch) {\n useDispatch(controller, options);\n }\n Object.assign(controller, {\n metaValue(name) {\n const element = document.head.querySelector(`meta[name=\"${name}\"]`);\n return element && element.getAttribute(\"content\");\n }\n });\n};\n\nclass ApplicationController extends Controller {\n constructor(context) {\n super(context);\n this.isPreview = false;\n this.isConnected = false;\n this.csrfToken = \"\";\n useApplication(this, this.options);\n }\n}\n\nconst defaultOptions$5 = {\n events: [ \"click\", \"touchend\" ],\n onlyVisible: true,\n dispatchEvent: true,\n eventPrefix: true\n};\n\nconst useClickOutside = (composableController, options = {}) => {\n const controller = composableController;\n const {onlyVisible: onlyVisible, dispatchEvent: dispatchEvent, events: events, eventPrefix: eventPrefix} = Object.assign({}, defaultOptions$5, options);\n const onEvent = event => {\n const targetElement = (options === null || options === void 0 ? void 0 : options.element) || controller.element;\n if (targetElement.contains(event.target) || !isElementInViewport(targetElement) && onlyVisible) {\n return;\n }\n if (controller.clickOutside) {\n controller.clickOutside(event);\n }\n if (dispatchEvent) {\n const eventName = composeEventName(\"click:outside\", controller, eventPrefix);\n const clickOutsideEvent = extendedEvent(eventName, event, {\n controller: controller\n });\n targetElement.dispatchEvent(clickOutsideEvent);\n }\n };\n const observe = () => {\n events === null || events === void 0 ? void 0 : events.forEach((event => {\n window.addEventListener(event, onEvent, true);\n }));\n };\n const unobserve = () => {\n events === null || events === void 0 ? void 0 : events.forEach((event => {\n window.removeEventListener(event, onEvent, true);\n }));\n };\n const controllerDisconnect = controller.disconnect.bind(controller);\n Object.assign(controller, {\n disconnect() {\n unobserve();\n controllerDisconnect();\n }\n });\n observe();\n return [ observe, unobserve ];\n};\n\nclass ClickOutsideComposableController extends Controller {}\n\nclass ClickOutsideController extends ClickOutsideComposableController {\n constructor(context) {\n super(context);\n requestAnimationFrame((() => {\n const [observe, unobserve] = useClickOutside(this, this.options);\n Object.assign(this, {\n observe: observe,\n unobserve: unobserve\n });\n }));\n }\n}\n\nclass DebounceController extends Controller {}\n\nDebounceController.debounces = [];\n\nconst defaultWait$1 = 200;\n\nconst debounce = (fn, wait = defaultWait$1) => {\n let timeoutId = null;\n return function() {\n const args = Array.from(arguments);\n const context = this;\n const params = args.map((arg => arg.params));\n const callback = () => {\n args.forEach(((arg, index) => arg.params = params[index]));\n return fn.apply(context, args);\n };\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n timeoutId = setTimeout(callback, wait);\n };\n};\n\nconst useDebounce = (composableController, options) => {\n const controller = composableController;\n const constructor = controller.constructor;\n constructor.debounces.forEach((func => {\n if (typeof func === \"string\") {\n controller[func] = debounce(controller[func], options === null || options === void 0 ? void 0 : options.wait);\n }\n if (typeof func === \"object\") {\n const {name: name, wait: wait} = func;\n if (!name) return;\n controller[name] = debounce(controller[name], wait || (options === null || options === void 0 ? void 0 : options.wait));\n }\n }));\n};\n\nclass UseHover extends StimulusUse {\n constructor(controller, options = {}) {\n super(controller, options);\n this.observe = () => {\n this.targetElement.addEventListener(\"mouseenter\", this.onEnter);\n this.targetElement.addEventListener(\"mouseleave\", this.onLeave);\n };\n this.unobserve = () => {\n this.targetElement.removeEventListener(\"mouseenter\", this.onEnter);\n this.targetElement.removeEventListener(\"mouseleave\", this.onLeave);\n };\n this.onEnter = event => {\n this.call(\"mouseEnter\", event);\n this.log(\"mouseEnter\", {\n hover: true\n });\n this.dispatch(\"mouseEnter\", {\n hover: false\n });\n };\n this.onLeave = event => {\n this.call(\"mouseLeave\", event);\n this.log(\"mouseLeave\", {\n hover: false\n });\n this.dispatch(\"mouseLeave\", {\n hover: false\n });\n };\n this.controller = controller;\n this.enhanceController();\n this.observe();\n }\n enhanceController() {\n const controllerDisconnect = this.controller.disconnect.bind(this.controller);\n const disconnect = () => {\n this.unobserve();\n controllerDisconnect();\n };\n Object.assign(this.controller, {\n disconnect: disconnect\n });\n }\n}\n\nconst useHover = (composableController, options = {}) => {\n const controller = composableController;\n const observer = new UseHover(controller, options);\n return [ observer.observe, observer.unobserve ];\n};\n\nclass HoverComposableController extends Controller {}\n\nclass HoverController extends HoverComposableController {\n constructor(context) {\n super(context);\n requestAnimationFrame((() => {\n const [observe, unobserve] = useHover(this, this.options);\n Object.assign(this, {\n observe: observe,\n unobserve: unobserve\n });\n }));\n }\n}\n\nconst defaultEvents = [ \"mousemove\", \"mousedown\", \"resize\", \"keydown\", \"touchstart\", \"wheel\" ];\n\nconst oneMinute = 6e4;\n\nconst defaultOptions$4 = {\n ms: oneMinute,\n initialState: false,\n events: defaultEvents,\n dispatchEvent: true,\n eventPrefix: true\n};\n\nconst useIdle = (composableController, options = {}) => {\n const controller = composableController;\n const {ms: ms, initialState: initialState, events: events, dispatchEvent: dispatchEvent, eventPrefix: eventPrefix} = Object.assign({}, defaultOptions$4, options);\n let isIdle = initialState;\n let timeout = setTimeout((() => {\n isIdle = true;\n dispatchAway();\n }), ms);\n const dispatchAway = event => {\n const eventName = composeEventName(\"away\", controller, eventPrefix);\n controller.isIdle = true;\n method(controller, \"away\").call(controller, event);\n if (dispatchEvent) {\n const clickOutsideEvent = extendedEvent(eventName, event || null, {\n controller: controller\n });\n controller.element.dispatchEvent(clickOutsideEvent);\n }\n };\n const dispatchBack = event => {\n const eventName = composeEventName(\"back\", controller, eventPrefix);\n controller.isIdle = false;\n method(controller, \"back\").call(controller, event);\n if (dispatchEvent) {\n const clickOutsideEvent = extendedEvent(eventName, event || null, {\n controller: controller\n });\n controller.element.dispatchEvent(clickOutsideEvent);\n }\n };\n const onEvent = event => {\n if (isIdle) dispatchBack(event);\n isIdle = false;\n clearTimeout(timeout);\n timeout = setTimeout((() => {\n isIdle = true;\n dispatchAway(event);\n }), ms);\n };\n const onVisibility = event => {\n if (!document.hidden) onEvent(event);\n };\n if (isIdle) {\n dispatchAway();\n } else {\n dispatchBack();\n }\n const controllerDisconnect = controller.disconnect.bind(controller);\n const observe = () => {\n events.forEach((event => {\n window.addEventListener(event, onEvent);\n }));\n document.addEventListener(\"visibilitychange\", onVisibility);\n };\n const unobserve = () => {\n clearTimeout(timeout);\n events.forEach((event => {\n window.removeEventListener(event, onEvent);\n }));\n document.removeEventListener(\"visibilitychange\", onVisibility);\n };\n Object.assign(controller, {\n disconnect() {\n unobserve();\n controllerDisconnect();\n }\n });\n observe();\n return [ observe, unobserve ];\n};\n\nclass IdleComposableController extends Controller {\n constructor() {\n super(...arguments);\n this.isIdle = false;\n }\n}\n\nclass IdleController extends IdleComposableController {\n constructor(context) {\n super(context);\n requestAnimationFrame((() => {\n const [observe, unobserve] = useIdle(this, this.options);\n Object.assign(this, {\n observe: observe,\n unobserve: unobserve\n });\n }));\n }\n}\n\nconst defaultOptions$3 = {\n dispatchEvent: true,\n eventPrefix: true,\n visibleAttribute: \"isVisible\"\n};\n\nconst useIntersection = (composableController, options = {}) => {\n const controller = composableController;\n const {dispatchEvent: dispatchEvent, eventPrefix: eventPrefix, visibleAttribute: visibleAttribute} = Object.assign({}, defaultOptions$3, options);\n const targetElement = (options === null || options === void 0 ? void 0 : options.element) || controller.element;\n if (!controller.intersectionElements) controller.intersectionElements = [];\n controller.intersectionElements.push(targetElement);\n const callback = entries => {\n const [entry] = entries;\n if (entry.isIntersecting) {\n dispatchAppear(entry);\n } else if (targetElement.hasAttribute(visibleAttribute)) {\n dispatchDisappear(entry);\n }\n };\n const observer = new IntersectionObserver(callback, options);\n const dispatchAppear = entry => {\n targetElement.setAttribute(visibleAttribute, \"true\");\n method(controller, \"appear\").call(controller, entry, observer);\n if (dispatchEvent) {\n const eventName = composeEventName(\"appear\", controller, eventPrefix);\n const appearEvent = extendedEvent(eventName, null, {\n controller: controller,\n entry: entry,\n observer: observer\n });\n targetElement.dispatchEvent(appearEvent);\n }\n };\n const dispatchDisappear = entry => {\n targetElement.removeAttribute(visibleAttribute);\n method(controller, \"disappear\").call(controller, entry, observer);\n if (dispatchEvent) {\n const eventName = composeEventName(\"disappear\", controller, eventPrefix);\n const disappearEvent = extendedEvent(eventName, null, {\n controller: controller,\n entry: entry,\n observer: observer\n });\n targetElement.dispatchEvent(disappearEvent);\n }\n };\n const controllerDisconnect = controller.disconnect.bind(controller);\n const disconnect = () => {\n unobserve();\n controllerDisconnect();\n };\n const observe = () => {\n observer.observe(targetElement);\n };\n const unobserve = () => {\n observer.unobserve(targetElement);\n };\n const noneVisible = () => controller.intersectionElements.filter((element => element.hasAttribute(visibleAttribute))).length === 0;\n const oneVisible = () => controller.intersectionElements.filter((element => element.hasAttribute(visibleAttribute))).length === 1;\n const atLeastOneVisible = () => controller.intersectionElements.some((element => element.hasAttribute(visibleAttribute)));\n const allVisible = () => controller.intersectionElements.every((element => element.hasAttribute(visibleAttribute)));\n const isVisible = allVisible;\n Object.assign(controller, {\n isVisible: isVisible,\n noneVisible: noneVisible,\n oneVisible: oneVisible,\n atLeastOneVisible: atLeastOneVisible,\n allVisible: allVisible,\n disconnect: disconnect\n });\n observe();\n return [ observe, unobserve ];\n};\n\nclass IntersectionComposableController extends Controller {}\n\nclass IntersectionController extends IntersectionComposableController {\n constructor(context) {\n super(context);\n requestAnimationFrame((() => {\n const [observe, unobserve] = useIntersection(this, this.options);\n Object.assign(this, {\n observe: observe,\n unobserve: unobserve\n });\n }));\n }\n}\n\nconst useLazyLoad = (controller, options) => {\n const callback = entries => {\n const [entry] = entries;\n if (entry.isIntersecting && !controller.isLoaded) {\n handleAppear();\n }\n };\n const handleAppear = entry => {\n const src = controller.data.get(\"src\");\n if (!src) return;\n const imageElement = controller.element;\n controller.isLoading = true;\n method(controller, \"loading\").call(controller, src);\n imageElement.onload = () => {\n handleLoaded(src);\n };\n imageElement.src = src;\n };\n const handleLoaded = src => {\n controller.isLoading = false;\n controller.isLoaded = true;\n method(controller, \"loaded\").call(controller, src);\n };\n const controllerDisconnect = controller.disconnect.bind(controller);\n const observer = new IntersectionObserver(callback, options);\n const observe = () => {\n observer.observe(controller.element);\n };\n const unobserve = () => {\n observer.unobserve(controller.element);\n };\n Object.assign(controller, {\n isVisible: false,\n disconnect() {\n unobserve();\n controllerDisconnect();\n }\n });\n observe();\n return [ observe, unobserve ];\n};\n\nclass LazyLoadComposableController extends Controller {\n constructor() {\n super(...arguments);\n this.isLoading = false;\n this.isLoaded = false;\n }\n}\n\nclass LazyLoadController extends LazyLoadComposableController {\n constructor(context) {\n super(context);\n this.options = {\n rootMargin: \"10%\"\n };\n requestAnimationFrame((() => {\n const [observe, unobserve] = useLazyLoad(this, this.options);\n Object.assign(this, {\n observe: observe,\n unobserve: unobserve\n });\n }));\n }\n}\n\nconst defaultOptions$2 = {\n mediaQueries: {},\n dispatchEvent: true,\n eventPrefix: true,\n debug: false\n};\n\nclass UseMatchMedia extends StimulusUse {\n constructor(controller, options = {}) {\n var _a, _b, _c, _d;\n super(controller, options);\n this.matches = [];\n this.callback = event => {\n const name = Object.keys(this.mediaQueries).find((name => this.mediaQueries[name] === event.media));\n if (!name) return;\n const {media: media, matches: matches} = event;\n this.changed({\n name: name,\n media: media,\n matches: matches,\n event: event\n });\n };\n this.changed = payload => {\n const {name: name} = payload;\n if (payload.event) {\n this.call(camelize(`${name}_changed`), payload);\n this.dispatch(`${name}:changed`, payload);\n this.log(`media query \"${name}\" changed`, payload);\n }\n if (payload.matches) {\n this.call(camelize(`is_${name}`), payload);\n this.dispatch(`is:${name}`, payload);\n } else {\n this.call(camelize(`not_${name}`), payload);\n this.dispatch(`not:${name}`, payload);\n }\n };\n this.observe = () => {\n Object.keys(this.mediaQueries).forEach((name => {\n const media = this.mediaQueries[name];\n const match = window.matchMedia(media);\n match.addListener(this.callback);\n this.matches.push(match);\n this.changed({\n name: name,\n media: media,\n matches: match.matches\n });\n }));\n };\n this.unobserve = () => {\n this.matches.forEach((match => match.removeListener(this.callback)));\n };\n this.controller = controller;\n this.mediaQueries = (_a = options.mediaQueries) !== null && _a !== void 0 ? _a : defaultOptions$2.mediaQueries;\n this.dispatchEvent = (_b = options.dispatchEvent) !== null && _b !== void 0 ? _b : defaultOptions$2.dispatchEvent;\n this.eventPrefix = (_c = options.eventPrefix) !== null && _c !== void 0 ? _c : defaultOptions$2.eventPrefix;\n this.debug = (_d = options.debug) !== null && _d !== void 0 ? _d : defaultOptions$2.debug;\n if (!window.matchMedia) {\n console.error(\"window.matchMedia() is not available\");\n return;\n }\n this.enhanceController();\n this.observe();\n }\n enhanceController() {\n const controllerDisconnect = this.controller.disconnect.bind(this.controller);\n const disconnect = () => {\n this.unobserve();\n controllerDisconnect();\n };\n Object.assign(this.controller, {\n disconnect: disconnect\n });\n }\n}\n\nconst useMatchMedia = (controller, options = {}) => {\n const observer = new UseMatchMedia(controller, options);\n return [ observer.observe, observer.unobserve ];\n};\n\nconst memoize = (controller, name, value) => {\n Object.defineProperty(controller, name, {\n value: value\n });\n return value;\n};\n\nconst useMemo = controller => {\n var _a;\n (_a = controller.constructor.memos) === null || _a === void 0 ? void 0 : _a.forEach((getter => {\n memoize(controller, getter, controller[getter]);\n }));\n};\n\nconst defineMetaGetter = (controller, metaName, suffix) => {\n const getterName = suffix ? `${camelize(metaName)}Meta` : camelize(metaName);\n Object.defineProperty(controller, getterName, {\n get() {\n return typeCast(metaValue(metaName));\n }\n });\n};\n\nfunction metaValue(name) {\n const element = document.head.querySelector(`meta[name=\"${name}\"]`);\n return element && element.getAttribute(\"content\");\n}\n\nfunction typeCast(value) {\n try {\n return JSON.parse(value);\n } catch (o_O) {\n return value;\n }\n}\n\nconst useMeta = (controller, options = {\n suffix: true\n}) => {\n const metaNames = controller.constructor.metaNames;\n const suffix = options.suffix;\n metaNames === null || metaNames === void 0 ? void 0 : metaNames.forEach((metaName => {\n defineMetaGetter(controller, metaName, suffix);\n }));\n Object.defineProperty(controller, \"metas\", {\n get() {\n const result = {};\n metaNames === null || metaNames === void 0 ? void 0 : metaNames.forEach((metaName => {\n const value = typeCast(metaValue(metaName));\n if (value !== undefined && value !== null) {\n result[camelize(metaName)] = value;\n }\n }));\n return result;\n }\n });\n};\n\nclass UseMutation extends StimulusUse {\n constructor(controller, options = {}) {\n super(controller, options);\n this.observe = () => {\n try {\n this.observer.observe(this.targetElement, this.options);\n } catch (error) {\n this.controller.application.handleError(error, \"At a minimum, one of childList, attributes, and/or characterData must be true\", {});\n }\n };\n this.unobserve = () => {\n this.observer.disconnect();\n };\n this.mutation = entries => {\n this.call(\"mutate\", entries);\n this.log(\"mutate\", {\n entries: entries\n });\n this.dispatch(\"mutate\", {\n entries: entries\n });\n };\n this.targetElement = (options === null || options === void 0 ? void 0 : options.element) || controller.element;\n this.controller = controller;\n this.options = options;\n this.observer = new MutationObserver(this.mutation);\n this.enhanceController();\n this.observe();\n }\n enhanceController() {\n const controllerDisconnect = this.controller.disconnect.bind(this.controller);\n const disconnect = () => {\n this.unobserve();\n controllerDisconnect();\n };\n Object.assign(this.controller, {\n disconnect: disconnect\n });\n }\n}\n\nconst useMutation = (controller, options = {}) => {\n const observer = new UseMutation(controller, options);\n return [ observer.observe, observer.unobserve ];\n};\n\nclass MutationComposableController extends Controller {}\n\nclass MutationController extends MutationComposableController {\n constructor(context) {\n super(context);\n requestAnimationFrame((() => {\n const [observe, unobserve] = useMutation(this, this.options);\n Object.assign(this, {\n observe: observe,\n unobserve: unobserve\n });\n }));\n }\n}\n\nconst defaultOptions$1 = {\n dispatchEvent: true,\n eventPrefix: true\n};\n\nconst useResize = (composableController, options = {}) => {\n const controller = composableController;\n const {dispatchEvent: dispatchEvent, eventPrefix: eventPrefix} = Object.assign({}, defaultOptions$1, options);\n const targetElement = (options === null || options === void 0 ? void 0 : options.element) || controller.element;\n const callback = entries => {\n const [entry] = entries;\n method(controller, \"resize\").call(controller, entry.contentRect);\n if (dispatchEvent) {\n const eventName = composeEventName(\"resize\", controller, eventPrefix);\n const appearEvent = extendedEvent(eventName, null, {\n controller: controller,\n entry: entry\n });\n targetElement.dispatchEvent(appearEvent);\n }\n };\n const controllerDisconnect = controller.disconnect.bind(controller);\n const observer = new ResizeObserver(callback);\n const observe = () => {\n observer.observe(targetElement);\n };\n const unobserve = () => {\n observer.unobserve(targetElement);\n };\n Object.assign(controller, {\n disconnect() {\n unobserve();\n controllerDisconnect();\n }\n });\n observe();\n return [ observe, unobserve ];\n};\n\nclass ResizeComposableController extends Controller {}\n\nclass ResizeController extends ResizeComposableController {\n constructor(context) {\n super(context);\n requestAnimationFrame((() => {\n const [observe, unobserve] = useResize(this, this.options);\n Object.assign(this, {\n observe: observe,\n unobserve: unobserve\n });\n }));\n }\n}\n\nclass UseTargetMutation extends StimulusUse {\n constructor(controller, options = {}) {\n super(controller, options);\n this.observe = () => {\n this.observer.observe(this.targetElement, {\n subtree: true,\n characterData: true,\n childList: true,\n attributes: true,\n attributeOldValue: true,\n attributeFilter: [ this.targetSelector, this.scopedTargetSelector ]\n });\n };\n this.unobserve = () => {\n this.observer.disconnect();\n };\n this.mutation = entries => {\n for (const mutation of entries) {\n switch (mutation.type) {\n case \"attributes\":\n let newValue = mutation.target.getAttribute(mutation.attributeName);\n let oldValue = mutation.oldValue;\n if (mutation.attributeName === this.targetSelector || mutation.attributeName === this.scopedTargetSelector) {\n let oldTargets = this.targetsUsedByThisController(oldValue);\n let newTargets = this.targetsUsedByThisController(newValue);\n let removedTargets = oldTargets.filter((target => !newTargets.includes(target)));\n let addedTargets = newTargets.filter((target => !oldTargets.includes(target)));\n removedTargets.forEach((target => this.targetRemoved(this.stripIdentifierPrefix(target), mutation.target, \"attributeChange\")));\n addedTargets.forEach((target => this.targetAdded(this.stripIdentifierPrefix(target), mutation.target, \"attributeChange\")));\n }\n break;\n\n case \"characterData\":\n let nodule = this.findTargetInAncestry(mutation.target);\n if (nodule == null) {\n return;\n } else {\n let supportedTargets = this.targetsUsedByThisControllerFromNode(nodule);\n supportedTargets.forEach((target => {\n this.targetChanged(this.stripIdentifierPrefix(target), nodule, \"domMutation\");\n }));\n }\n break;\n\n case \"childList\":\n let {addedNodes: addedNodes, removedNodes: removedNodes} = mutation;\n addedNodes.forEach((node => this.processNodeDOMMutation(node, this.targetAdded)));\n removedNodes.forEach((node => this.processNodeDOMMutation(node, this.targetRemoved)));\n break;\n }\n }\n };\n this.controller = controller;\n this.options = options;\n this.targetElement = controller.element;\n this.identifier = controller.scope.identifier;\n this.identifierPrefix = `${this.identifier}.`;\n this.targetSelector = controller.scope.schema.targetAttribute;\n this.scopedTargetSelector = `data-${this.identifier}-target`;\n this.targets = options.targets || controller.constructor.targets;\n this.prefixedTargets = this.targets.map((target => `${this.identifierPrefix}${target}`));\n this.observer = new MutationObserver(this.mutation);\n this.enhanceController();\n this.observe();\n }\n processNodeDOMMutation(node, initialChangeModeAssumption) {\n let nodule = node;\n let change = initialChangeModeAssumption;\n let supportedTargets = [];\n if (nodule.nodeName == \"#text\" || this.targetsUsedByThisControllerFromNode(nodule).length == 0) {\n change = this.targetChanged;\n nodule = this.findTargetInAncestry(node);\n } else {\n supportedTargets = this.targetsUsedByThisControllerFromNode(nodule);\n }\n if (nodule == null) {\n return;\n } else if (supportedTargets.length == 0) {\n supportedTargets = this.targetsUsedByThisControllerFromNode(nodule);\n }\n supportedTargets.forEach((target => {\n change.call(this, this.stripIdentifierPrefix(target), nodule, \"domMutation\");\n }));\n }\n findTargetInAncestry(node) {\n let nodule = node;\n let supportedTargets = [];\n if (nodule.nodeName != \"#text\") {\n supportedTargets = this.targetsUsedByThisControllerFromNode(nodule);\n }\n while (nodule.parentNode !== null && nodule.parentNode != this.targetElement && supportedTargets.length == 0) {\n nodule = nodule.parentNode;\n if (nodule.nodeName !== \"#text\") {\n let supportedTargets = this.targetsUsedByThisControllerFromNode(nodule);\n if (supportedTargets.length > 0) {\n return nodule;\n }\n }\n }\n if (nodule.nodeName == \"#text\") {\n return null;\n }\n if (nodule.parentNode == null) {\n return null;\n }\n if (nodule.parentNode == this.targetElement) {\n if (this.targetsUsedByThisControllerFromNode(nodule).length > 0) {\n return nodule;\n }\n return null;\n }\n return null;\n }\n targetAdded(name, node, trigger) {\n let targetCallback = `${name}TargetAdded`;\n this.controller[targetCallback] && method(this.controller, targetCallback).call(this.controller, node);\n this.log(\"targetAdded\", {\n target: name,\n node: node,\n trigger: trigger\n });\n }\n targetRemoved(name, node, trigger) {\n let targetCallback = `${name}TargetRemoved`;\n this.controller[targetCallback] && method(this.controller, targetCallback).call(this.controller, node);\n this.log(\"targetRemoved\", {\n target: name,\n node: node,\n trigger: trigger\n });\n }\n targetChanged(name, node, trigger) {\n let targetCallback = `${name}TargetChanged`;\n this.controller[targetCallback] && method(this.controller, targetCallback).call(this.controller, node);\n this.log(\"targetChanged\", {\n target: name,\n node: node,\n trigger: trigger\n });\n }\n targetsUsedByThisControllerFromNode(node) {\n if (node.nodeName == \"#text\" || node.nodeName == \"#comment\") {\n return [];\n }\n let nodeElement = node;\n return this.targetsUsedByThisController(nodeElement.getAttribute(this.scopedTargetSelector) || nodeElement.getAttribute(this.targetSelector));\n }\n targetsUsedByThisController(targetStr) {\n targetStr = targetStr || \"\";\n let targetsToCheck = this.stripIdentifierPrefix(targetStr).split(\" \");\n return this.targets.filter((n => targetsToCheck.indexOf(n) !== -1));\n }\n stripIdentifierPrefix(target) {\n return target.replace(new RegExp(this.identifierPrefix, \"g\"), \"\");\n }\n enhanceController() {\n const controllerDisconnect = this.controller.disconnect.bind(this.controller);\n const disconnect = () => {\n this.unobserve();\n controllerDisconnect();\n };\n Object.assign(this.controller, {\n disconnect: disconnect\n });\n }\n}\n\nconst useTargetMutation = (composableController, options = {}) => {\n const controller = composableController;\n const observer = new UseTargetMutation(controller, options);\n return [ observer.observe, observer.unobserve ];\n};\n\nclass TargetMutationComposableController extends Controller {}\n\nclass TargetMutationController extends TargetMutationComposableController {\n constructor(context) {\n super(context);\n requestAnimationFrame((() => {\n const [observe, unobserve] = useTargetMutation(this, this.options);\n Object.assign(this, {\n observe: observe,\n unobserve: unobserve\n });\n }));\n }\n}\n\nclass ThrottleController extends Controller {}\n\nThrottleController.throttles = [];\n\nconst defaultWait = 200;\n\nfunction throttle(func, wait = defaultWait) {\n let inThrottle;\n return function() {\n const args = arguments;\n const context = this;\n if (!inThrottle) {\n inThrottle = true;\n func.apply(context, args);\n setTimeout((() => inThrottle = false), wait);\n }\n };\n}\n\nconst useThrottle = (composableController, options = {}) => {\n var _a;\n const controller = composableController;\n const constructor = controller.constructor;\n (_a = constructor.throttles) === null || _a === void 0 ? void 0 : _a.forEach((func => {\n if (typeof func === \"string\") {\n controller[func] = throttle(controller[func], options === null || options === void 0 ? void 0 : options.wait);\n }\n if (typeof func === \"object\") {\n const {name: name, wait: wait} = func;\n if (!name) return;\n controller[name] = throttle(controller[name], wait || (options === null || options === void 0 ? void 0 : options.wait));\n }\n }));\n};\n\nconst alpineNames = {\n enterFromClass: \"enter\",\n enterActiveClass: \"enterStart\",\n enterToClass: \"enterEnd\",\n leaveFromClass: \"leave\",\n leaveActiveClass: \"leaveStart\",\n leaveToClass: \"leaveEnd\"\n};\n\nconst defaultOptions = {\n transitioned: false,\n hiddenClass: \"hidden\",\n preserveOriginalClass: true,\n removeToClasses: true\n};\n\nconst useTransition = (composableController, options = {}) => {\n var _a, _b, _c;\n const controller = composableController;\n const targetName = controller.element.dataset.transitionTarget;\n let targetFromAttribute;\n if (targetName) {\n targetFromAttribute = controller[`${targetName}Target`];\n }\n const targetElement = (options === null || options === void 0 ? void 0 : options.element) || targetFromAttribute || controller.element;\n if (!(targetElement instanceof HTMLElement || targetElement instanceof SVGElement)) return;\n const dataset = targetElement.dataset;\n const leaveAfter = parseInt(dataset.leaveAfter || \"\") || options.leaveAfter || 0;\n const {transitioned: transitioned, hiddenClass: hiddenClass, preserveOriginalClass: preserveOriginalClass, removeToClasses: removeToClasses} = Object.assign({}, defaultOptions, options);\n const controllerEnter = (_a = controller.enter) === null || _a === void 0 ? void 0 : _a.bind(controller);\n const controllerLeave = (_b = controller.leave) === null || _b === void 0 ? void 0 : _b.bind(controller);\n const controllerToggleTransition = (_c = controller.toggleTransition) === null || _c === void 0 ? void 0 : _c.bind(controller);\n async function enter(event) {\n if (controller.transitioned) return;\n controller.transitioned = true;\n controllerEnter && controllerEnter(event);\n const enterFromClasses = getAttribute(\"enterFrom\", options, dataset);\n const enterActiveClasses = getAttribute(\"enterActive\", options, dataset);\n const enterToClasses = getAttribute(\"enterTo\", options, dataset);\n const leaveToClasses = getAttribute(\"leaveTo\", options, dataset);\n if (!!hiddenClass) {\n targetElement.classList.remove(hiddenClass);\n }\n if (!removeToClasses) {\n removeClasses(targetElement, leaveToClasses);\n }\n await transition(targetElement, enterFromClasses, enterActiveClasses, enterToClasses, hiddenClass, preserveOriginalClass, removeToClasses);\n if (leaveAfter > 0) {\n setTimeout((() => {\n leave(event);\n }), leaveAfter);\n }\n }\n async function leave(event) {\n if (!controller.transitioned) return;\n controller.transitioned = false;\n controllerLeave && controllerLeave(event);\n const leaveFromClasses = getAttribute(\"leaveFrom\", options, dataset);\n const leaveActiveClasses = getAttribute(\"leaveActive\", options, dataset);\n const leaveToClasses = getAttribute(\"leaveTo\", options, dataset);\n const enterToClasses = getAttribute(\"enterTo\", options, dataset);\n if (!removeToClasses) {\n removeClasses(targetElement, enterToClasses);\n }\n await transition(targetElement, leaveFromClasses, leaveActiveClasses, leaveToClasses, hiddenClass, preserveOriginalClass, removeToClasses);\n if (!!hiddenClass) {\n targetElement.classList.add(hiddenClass);\n }\n }\n function toggleTransition(event) {\n controllerToggleTransition && controllerToggleTransition(event);\n if (controller.transitioned) {\n leave();\n } else {\n enter();\n }\n }\n async function transition(element, initialClasses, activeClasses, endClasses, hiddenClass, preserveOriginalClass, removeEndClasses) {\n const stashedClasses = [];\n if (preserveOriginalClass) {\n initialClasses.forEach((cls => element.classList.contains(cls) && cls !== hiddenClass && stashedClasses.push(cls)));\n activeClasses.forEach((cls => element.classList.contains(cls) && cls !== hiddenClass && stashedClasses.push(cls)));\n endClasses.forEach((cls => element.classList.contains(cls) && cls !== hiddenClass && stashedClasses.push(cls)));\n }\n addClasses(element, initialClasses);\n removeClasses(element, stashedClasses);\n addClasses(element, activeClasses);\n await nextAnimationFrame();\n removeClasses(element, initialClasses);\n addClasses(element, endClasses);\n await afterTransition(element);\n removeClasses(element, activeClasses);\n if (removeEndClasses) {\n removeClasses(element, endClasses);\n }\n addClasses(element, stashedClasses);\n }\n function initialState() {\n controller.transitioned = transitioned;\n if (transitioned) {\n if (!!hiddenClass) {\n targetElement.classList.remove(hiddenClass);\n }\n enter();\n } else {\n if (!!hiddenClass) {\n targetElement.classList.add(hiddenClass);\n }\n leave();\n }\n }\n function addClasses(element, classes) {\n if (classes.length > 0) {\n element.classList.add(...classes);\n }\n }\n function removeClasses(element, classes) {\n if (classes.length > 0) {\n element.classList.remove(...classes);\n }\n }\n initialState();\n Object.assign(controller, {\n enter: enter,\n leave: leave,\n toggleTransition: toggleTransition\n });\n return [ enter, leave, toggleTransition ];\n};\n\nfunction getAttribute(name, options, dataset) {\n const datasetName = `transition${name[0].toUpperCase()}${name.substr(1)}`;\n const datasetAlpineName = alpineNames[name];\n const classes = options[name] || dataset[datasetName] || dataset[datasetAlpineName] || \" \";\n return isEmpty(classes) ? [] : classes.split(\" \");\n}\n\nasync function afterTransition(element) {\n return new Promise((resolve => {\n const duration = Number(getComputedStyle(element).transitionDuration.split(\",\")[0].replace(\"s\", \"\")) * 1e3;\n setTimeout((() => {\n resolve(duration);\n }), duration);\n }));\n}\n\nasync function nextAnimationFrame() {\n return new Promise((resolve => {\n requestAnimationFrame((() => {\n requestAnimationFrame(resolve);\n }));\n }));\n}\n\nfunction isEmpty(str) {\n return str.length === 0 || !str.trim();\n}\n\nclass TransitionComposableController extends Controller {\n constructor() {\n super(...arguments);\n this.transitioned = false;\n }\n}\n\nclass TransitionController extends TransitionComposableController {\n constructor(context) {\n super(context);\n requestAnimationFrame((() => {\n useTransition(this, this.options);\n }));\n }\n}\n\nclass UseVisibility extends StimulusUse {\n constructor(controller, options = {}) {\n super(controller, options);\n this.observe = () => {\n this.controller.isVisible = !document.hidden;\n document.addEventListener(\"visibilitychange\", this.handleVisibilityChange);\n this.handleVisibilityChange();\n };\n this.unobserve = () => {\n document.removeEventListener(\"visibilitychange\", this.handleVisibilityChange);\n };\n this.becomesInvisible = event => {\n this.controller.isVisible = false;\n this.call(\"invisible\", event);\n this.log(\"invisible\", {\n isVisible: false\n });\n this.dispatch(\"invisible\", {\n event: event,\n isVisible: false\n });\n };\n this.becomesVisible = event => {\n this.controller.isVisible = true;\n this.call(\"visible\", event);\n this.log(\"visible\", {\n isVisible: true\n });\n this.dispatch(\"visible\", {\n event: event,\n isVisible: true\n });\n };\n this.handleVisibilityChange = event => {\n if (document.hidden) {\n this.becomesInvisible(event);\n } else {\n this.becomesVisible(event);\n }\n };\n this.controller = controller;\n this.enhanceController();\n this.observe();\n }\n enhanceController() {\n const controllerDisconnect = this.controllerDisconnect;\n const disconnect = () => {\n this.unobserve();\n controllerDisconnect();\n };\n Object.assign(this.controller, {\n disconnect: disconnect\n });\n }\n}\n\nconst useVisibility = (composableController, options = {}) => {\n const controller = composableController;\n const observer = new UseVisibility(controller, options);\n return [ observer.observe, observer.unobserve ];\n};\n\nclass VisibilityComposableController extends Controller {\n constructor() {\n super(...arguments);\n this.isVisible = false;\n }\n}\n\nclass VisibilityController extends VisibilityComposableController {\n constructor(context) {\n super(context);\n requestAnimationFrame((() => {\n const [observe, unobserve] = useVisibility(this, this.options);\n Object.assign(this, {\n observe: observe,\n unobserve: unobserve\n });\n }));\n }\n}\n\nclass UseWindowFocus extends StimulusUse {\n constructor(controller, options = {}) {\n super(controller, options);\n this.observe = () => {\n if (document.hasFocus()) {\n this.becomesFocused();\n } else {\n this.becomesUnfocused();\n }\n this.interval = setInterval((() => {\n this.handleWindowFocusChange();\n }), this.intervalDuration);\n };\n this.unobserve = () => {\n clearInterval(this.interval);\n };\n this.becomesUnfocused = event => {\n this.controller.hasFocus = false;\n this.call(\"unfocus\", event);\n this.log(\"unfocus\", {\n hasFocus: false\n });\n this.dispatch(\"unfocus\", {\n event: event,\n hasFocus: false\n });\n };\n this.becomesFocused = event => {\n this.controller.hasFocus = true;\n this.call(\"focus\", event);\n this.log(\"focus\", {\n hasFocus: true\n });\n this.dispatch(\"focus\", {\n event: event,\n hasFocus: true\n });\n };\n this.handleWindowFocusChange = event => {\n if (document.hasFocus() && !this.controller.hasFocus) {\n this.becomesFocused(event);\n } else if (!document.hasFocus() && this.controller.hasFocus) {\n this.becomesUnfocused(event);\n }\n };\n this.controller = controller;\n this.intervalDuration = options.interval || 200;\n this.enhanceController();\n this.observe();\n }\n enhanceController() {\n const controllerDisconnect = this.controllerDisconnect;\n const disconnect = () => {\n this.unobserve();\n controllerDisconnect();\n };\n Object.assign(this.controller, {\n disconnect: disconnect\n });\n }\n}\n\nconst useWindowFocus = (composableController, options = {}) => {\n const controller = composableController;\n const observer = new UseWindowFocus(controller, options);\n return [ observer.observe, observer.unobserve ];\n};\n\nclass WindowFocusComposableController extends Controller {\n constructor() {\n super(...arguments);\n this.hasFocus = false;\n }\n}\n\nclass WindowFocusController extends WindowFocusComposableController {\n constructor(context) {\n super(context);\n requestAnimationFrame((() => {\n const [observe, unobserve] = useWindowFocus(this, this.options);\n Object.assign(this, {\n observe: observe,\n unobserve: unobserve\n });\n }));\n }\n}\n\nconst useWindowResize = composableController => {\n const controller = composableController;\n const callback = event => {\n const {innerWidth: innerWidth, innerHeight: innerHeight} = window;\n const payload = {\n height: innerHeight || Infinity,\n width: innerWidth || Infinity,\n event: event\n };\n method(controller, \"windowResize\").call(controller, payload);\n };\n const controllerDisconnect = controller.disconnect.bind(controller);\n const observe = () => {\n window.addEventListener(\"resize\", callback);\n callback();\n };\n const unobserve = () => {\n window.removeEventListener(\"resize\", callback);\n };\n Object.assign(controller, {\n disconnect() {\n unobserve();\n controllerDisconnect();\n }\n });\n observe();\n return [ observe, unobserve ];\n};\n\nclass WindowResizeComposableController extends Controller {}\n\nclass WindowResizeController extends WindowResizeComposableController {\n constructor(context) {\n super(context);\n requestAnimationFrame((() => {\n const [observe, unobserve] = useWindowResize(this);\n Object.assign(this, {\n observe: observe,\n unobserve: unobserve\n });\n }));\n }\n}\n\nfunction useHotkeys() {\n throw \"[stimulus-use] Notice: The import for `useHotkeys()` has been moved from `stimulus-use` to `stimulus-use/hotkeys`. \\nPlease change the import accordingly and add `hotkey-js` as a dependency to your project. \\n\\nFor more information see: https://stimulus-use.github.io/stimulus-use/#/use-hotkeys?id=importing-the-behavior\";\n}\n\nexport { ApplicationController, ClickOutsideController, HoverController, IdleController, IntersectionController, LazyLoadController, MutationController, ResizeController, TargetMutationController, TransitionController, UseHover, UseMutation, UseTargetMutation, UseVisibility, UseWindowFocus, VisibilityController, WindowFocusController, WindowResizeController, debounce, useApplication, useClickOutside, useDebounce, useDispatch, useHotkeys, useHover, useIdle, useIntersection, useLazyLoad, useMatchMedia, useMemo, useMeta, useMutation, useResize, useTargetMutation, useThrottle, useTransition, useVisibility, useWindowFocus, useWindowResize };\n", "import { Controller } from \"@hotwired/stimulus\";\nimport { useTransition } from \"stimulus-use\";\nconst _Dropdown = class _Dropdown extends Controller {\n connect() {\n useTransition(this, {\n element: this.menuTarget\n });\n }\n toggle() {\n this.toggleTransition();\n }\n hide(event) {\n !this.element.contains(event.target) && !this.menuTarget.classList.contains(\"hidden\") && this.leave();\n }\n};\n_Dropdown.targets = [\"menu\"];\nlet Dropdown = _Dropdown;\nexport {\n Dropdown as default\n};\n", "window.BeerMenus = window.BeerMenus || {};\nwindow.BeerMenus.controllers = window.BeerMenus.controllers || {};\n", "/**\n * @typedef { import(\"@amplitude/analytics-types\").BrowserClient } BrowserClient\n * @typedef { typeof import(\"@amplitude/analytics-browser\").Identify } Identify\n */\n\nBeerMenus.Analytics = class Analytics extends HTMLElement {\n /**\n * @type {BrowserClient}\n * @private\n */\n static _BrowserClient = null\n\n /**\n * @type {Identify}\n * @private\n */\n static _UserIdentify = null\n\n /**\n * @type {Array