alchemy_cms 8.1.13 → 8.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,9 @@
1
1
  <<<<<<< HEAD
2
+ <<<<<<< HEAD
2
3
  {"version":3,"file":"alchemy_admin.min.js","sources":["../../../javascript/alchemy_admin/i18n.js","../../../javascript/alchemy_admin/hotkeys.js","../../../javascript/alchemy_admin/utils/dom_helpers.js","../../../javascript/alchemy_admin/spinner.js","../../../javascript/alchemy_admin/dialog.js","../../../javascript/alchemy_admin/confirm_dialog.js","../../../javascript/alchemy_admin/please_wait_overlay.js","../../../javascript/alchemy_admin/dirty.js","../../../javascript/alchemy_admin/fixed_elements.js","../../../javascript/alchemy_admin/growler.js","../../../javascript/alchemy_admin/link_dialog.js","../../../javascript/alchemy_admin/components/preview_window.js","../../../javascript/alchemy_admin/ingredient_anchor_link.js","../../../javascript/alchemy_admin/components/action.js","../../../javascript/alchemy_admin/components/alchemy_html_element.js","../../../javascript/alchemy_admin/utils/string_conversions.js","../../../javascript/alchemy_admin/components/remote_select.js","../../../javascript/alchemy_admin/components/attachment_select.js","../../../javascript/alchemy_admin/components/auto_submit.js","../../../javascript/alchemy_admin/components/button.js","../../../javascript/alchemy_admin/components/char_counter.js","../../../javascript/alchemy_admin/components/clipboard_button.js","../../../javascript/alchemy_admin/components/color_select.js","../../../javascript/alchemy_admin/components/datepicker.js","../../../javascript/alchemy_admin/components/dialog_link.js","../../../javascript/alchemy_admin/utils/ajax.js","../../../javascript/alchemy_admin/components/dom_id_select.js","../../../javascript/alchemy_admin/components/element_editor/publish_element_button.js","../../../javascript/alchemy_admin/components/element_editor/delete_element_button.js","../../../javascript/alchemy_admin/components/element_editor.js","../../../javascript/alchemy_admin/components/element_select.js","../../../javascript/alchemy_admin/components/elements_window.js","../../../javascript/alchemy_admin/components/elements_window_handle.js","../../../javascript/alchemy_admin/components/file_editor.js","../../../javascript/alchemy_admin/components/list_filter.js","../../../javascript/alchemy_admin/components/message.js","../../../javascript/alchemy_admin/components/growl.js","../../../javascript/alchemy_admin/components/icon.js","../../../javascript/alchemy_admin/components/ingredient_group.js","../../../javascript/alchemy_admin/components/link_buttons/link_button.js","../../../javascript/alchemy_admin/components/link_buttons/unlink_button.js","../../../javascript/alchemy_admin/components/link_buttons.js","../../../javascript/alchemy_admin/utils/format.js","../../../javascript/alchemy_admin/components/node_select.js","../../../javascript/alchemy_admin/components/uploader/file_upload.js","../../../javascript/alchemy_admin/components/uploader/progress.js","../../../javascript/alchemy_admin/components/uploader.js","../../../javascript/alchemy_admin/components/overlay.js","../../../javascript/alchemy_admin/components/page_node.js","../../../javascript/alchemy_admin/components/page_publication_fields.js","../../../javascript/alchemy_admin/components/page_select.js","../../../javascript/alchemy_admin/components/picture_description_select.js","../../../javascript/alchemy_admin/components/picture_editor.js","../../../javascript/alchemy_admin/utils/debounce.js","../../../javascript/alchemy_admin/utils/max.js","../../../javascript/alchemy_admin/components/picture_thumbnail.js","../../../javascript/alchemy_admin/components/publish_page_button.js","../../../javascript/alchemy_admin/components/select.js","../../../javascript/alchemy_admin/components/sitemap.js","../../../javascript/alchemy_admin/components/sortable_elements.js","../../../javascript/alchemy_admin/components/spinner.js","../../../javascript/alchemy_admin/components/tags_autocomplete.js","../../../javascript/alchemy_admin/components/tinymce.js","../../../javascript/alchemy_admin/components/update_check.js","../../../javascript/alchemy_admin/templates/compiled.js","../../../javascript/alchemy_admin/shoelace_theme.js","../../../javascript/alchemy_admin/utils/events.js","../../../javascript/alchemy_admin/image_cropper.js","../../../javascript/alchemy_admin/image_overlay.js","../../../javascript/alchemy_admin/picture_selector.js","../../../javascript/alchemy_admin/node_tree.js","../../../javascript/alchemy_admin.js","../../../javascript/alchemy_admin/initializer.js"],"sourcesContent":["const KEY_SEPARATOR = /\\./\n\nfunction nestedTranslation(translations, key) {\n const keys = key.split(KEY_SEPARATOR)\n const group = translations[keys[0]]\n if (group) {\n return group[keys[1]] || key\n }\n return key\n}\n\nfunction getTranslation(key) {\n const locale = currentLocale()\n const translations = Alchemy.translations\n\n if (!translations) {\n console.warn(`Translations for locale ${locale} not found!`)\n return key\n }\n\n if (KEY_SEPARATOR.test(key)) {\n return nestedTranslation(translations, key)\n }\n return translations[key] || key\n}\n\nexport function currentLocale() {\n if (document.documentElement.lang) {\n return document.documentElement.lang\n }\n return \"en\"\n}\n\nexport function translate(key, replacement = undefined) {\n let translation = getTranslation(key)\n\n if (replacement) {\n return translation.replace(/%\\{.+\\}/, replacement)\n }\n return translation\n}\n\nexport async function setupSelectLocale() {\n const locale = currentLocale()\n if (locale === \"en\") return\n\n await import(`select2/${locale}.js`)\n $.extend($.fn.select2.defaults, $.fn.select2.locales[locale])\n}\n","import \"keymaster\"\nimport { openDialog } from \"alchemy_admin/dialog\"\n\nconst bindedHotkeys = []\n\nfunction showHelp(evt) {\n if (\n !$(evt.target).is(\"input, textarea\") &&\n String.fromCharCode(evt.which) === \"?\"\n ) {\n openDialog(\"/admin/help\", {\n title: Alchemy.t(\"help\"),\n size: \"400x492\"\n })\n return false\n } else {\n return true\n }\n}\n\nexport default function (scope = document) {\n // The scope can be a jQuery object because we still use jQuery in alchemy_admin/dialog.js.\n if (scope instanceof jQuery) {\n scope = scope[0]\n }\n\n // Unbind all previously registered hotkeys if we are not inside a dialog.\n if (scope === document) {\n document.removeEventListener(\"keypress\", showHelp)\n document.addEventListener(\"keypress\", showHelp)\n bindedHotkeys.forEach((hotkey) => key.unbind(hotkey))\n }\n\n // Binds keyboard shortcuts to search fields.\n const search_fields = scope.querySelectorAll(\".search_input_field\")\n const search_fields_clear = scope.querySelectorAll(\n \".search_field_clear, .js_filter_field_clear\"\n )\n key(\"alt+f\", function () {\n key.setScope(\"search\")\n search_fields.forEach((el) => el.focus({ focusVisible: true }))\n return false\n })\n bindedHotkeys.push(\"alt+f\")\n key(\"esc\", \"search\", function () {\n search_fields_clear.forEach((el) => el.click())\n search_fields.forEach((el) => el.blur())\n })\n bindedHotkeys.push(\"esc\")\n\n // Binds click events to buttons with hotkeys.\n //\n // Simply add a data-alchemy-hotkey attribute to your link.\n // If a hotkey is triggered by user, the click event of the element gets triggerd.\n //\n scope.querySelectorAll(\"[data-alchemy-hotkey]\").forEach(function (el) {\n const hotkey = el.dataset.alchemyHotkey\n key(hotkey, () => el.click())\n bindedHotkeys.push(hotkey)\n })\n}\n","/**\n * create a HTML element\n * @param {string} text\n * @returns {HTMLElement}\n */\nexport function createHtmlElement(text) {\n const element = document.createElement(\"template\")\n element.innerHTML = text\n return element.content.children[0]\n}\n\n/**\n * wrap element with wrappingElement\n * @param {HTMLElement} element\n * @param {HTMLElement} wrappingElement\n */\nexport function wrap(element, wrappingElement) {\n element.replaceWith(wrappingElement)\n wrappingElement.appendChild(element)\n}\n","import { createHtmlElement } from \"alchemy_admin/utils/dom_helpers\"\n\nexport default class Spinner {\n constructor(size, color = \"currentColor\") {\n this.size = size\n this.color = color\n this.spinner = undefined\n }\n\n /**\n * @returns {HTMLElement|undefined}\n */\n get el() {\n return this.spinner\n }\n /**\n * @param {HTMLElement|undefined} parent\n */\n spin(parent) {\n if (typeof parent === \"undefined\") {\n parent = document.body\n }\n this.spinner = createHtmlElement(\n `<alchemy-spinner size=\"${this.size}\" color=\"${this.color}\"></alchemy-spinner>`\n )\n parent.append(this.spinner)\n return this\n }\n\n stop() {\n if (this.spinner) {\n this.spinner.remove()\n this.spinner = undefined\n }\n }\n}\n","import Hotkeys from \"alchemy_admin/hotkeys\"\nimport Spinner from \"alchemy_admin/spinner\"\n\n// Collection of all current dialog instances\nconst currentDialogs = []\n\nconst DEFAULTS = {\n header_height: 36,\n size: \"400x300\",\n padding: true,\n title: \"\",\n modal: true,\n overflow: \"visible\",\n ready: () => {},\n closed: () => {}\n}\n\nexport class Dialog {\n // Arguments:\n // - url: The url to load the content from via ajax\n // - options: A object holding options\n // - size: The maximum size of the Dialog\n // - title: The title of the Dialog\n constructor(url, options = {}) {\n this.url = url\n this.options = { ...DEFAULTS, ...options }\n this.$document = $(document)\n this.$window = $(window)\n this.$body = $(\"body\")\n const size = this.options.size.split(\"x\")\n this.width = parseInt(size[0], 10)\n this.height = parseInt(size[1], 10)\n this.build()\n this.resize()\n }\n\n // Opens the Dialog and loads the content via ajax.\n open() {\n this.dialog.trigger(\"Alchemy.DialogOpen\")\n this.bind_close_events()\n window.requestAnimationFrame(() => {\n this.dialog_container.addClass(\"open\")\n if (this.overlay != null) {\n return this.overlay.addClass(\"open\")\n }\n })\n this.$body.addClass(\"prevent-scrolling\")\n currentDialogs.push(this)\n this.load()\n }\n\n // Closes the Dialog and removes it from the DOM\n close() {\n this.dialog.trigger(\"DialogClose.Alchemy\")\n this.$document.off(\"keydown\")\n this.dialog_container.removeClass(\"open\")\n if (this.overlay != null) {\n this.overlay.removeClass(\"open\")\n }\n this.$document.on(\n \"webkitTransitionEnd transitionend oTransitionEnd\",\n () => {\n this.$document.off(\"webkitTransitionEnd transitionend oTransitionEnd\")\n this.dialog_container.remove()\n if (this.overlay != null) {\n this.overlay.remove()\n }\n this.$body.removeClass(\"prevent-scrolling\")\n currentDialogs.pop(this)\n if (this.options.closed != null) {\n return this.options.closed()\n }\n }\n )\n return true\n }\n\n // Loads the content via ajax and replaces the Dialog body with server response.\n load() {\n this.show_spinner()\n $.get(this.url, (data) => {\n this.replace(data)\n }).fail((xhr) => {\n this.show_error(xhr)\n })\n }\n\n // Reloads the Dialog content\n reload() {\n this.dialog_body.empty()\n this.load()\n }\n\n // Replaces the dialog body with given content and initializes it.\n replace(data) {\n this.remove_spinner()\n this.dialog_body.hide()\n this.dialog_body.html(data)\n this.init()\n this.dialog[0].dispatchEvent(\n new CustomEvent(\"DialogReady.Alchemy\", {\n bubbles: true,\n detail: {\n body: this.dialog_body[0]\n }\n })\n )\n if (this.options.ready != null) {\n this.options.ready(this.dialog_body)\n }\n this.dialog_body.show()\n }\n\n // Adds a spinner into Dialog body\n show_spinner() {\n this.spinner = new Spinner(\"medium\")\n this.spinner.spin(this.dialog_body[0])\n }\n\n // Removes the spinner from Dialog body\n remove_spinner() {\n this.spinner.stop()\n }\n\n // Initializes the Dialog body\n init() {\n Hotkeys(this.dialog_body)\n this.watch_remote_forms()\n }\n\n // Watches ajax requests inside of dialog body and replaces the content accordingly\n watch_remote_forms() {\n const $form = $('[data-remote=\"true\"]', this.dialog_body)\n\n $form.on(\"ajax:success\", (event) => {\n const xhr = event.detail[2]\n const content_type = xhr.getResponseHeader(\"Content-Type\")\n if (content_type.match(/javascript/)) {\n return\n } else {\n this.dialog_body.html(xhr.responseText)\n this.init()\n }\n })\n\n $form.on(\"ajax:error\", (event) => {\n const statusText = event.detail[1]\n const xhr = event.detail[2]\n this.show_error(xhr, statusText)\n })\n }\n\n // Displays an error message\n show_error(xhr, statusText) {\n if (xhr.status === 422) {\n this.dialog_body.html(xhr.responseText)\n this.init()\n return\n }\n\n const { error_body, error_header, error_type } = this.error_messages(\n xhr,\n statusText\n )\n\n const $errorDiv = $(`<alchemy-message type=\"${error_type}\">\n <h1>${error_header}</h1>\n <p>${error_body}</p>\n </alchemy-message>`)\n\n this.dialog_body.html($errorDiv)\n }\n\n // Returns error message based on xhr status\n error_messages(xhr, statusText) {\n let error_body,\n error_header,\n error_type = \"warning\"\n\n switch (xhr.status) {\n case 0:\n error_header = \"The server does not respond.\"\n error_body = \"Please check server and try again.\"\n break\n case 403:\n error_header = \"You are not authorized!\"\n error_body = \"Please close this window.\"\n break\n default:\n error_type = \"error\"\n if (statusText) {\n error_header = statusText\n console.error(xhr.responseText)\n } else {\n error_header = `${xhr.statusText} (${xhr.status})`\n }\n error_body = \"Please check log and try again.\"\n }\n\n return { error_header, error_body, error_type }\n }\n\n // Binds close events on:\n // - Close button\n // - Overlay (if the Dialog is a modal)\n // - ESC Key\n bind_close_events() {\n this.close_button.on(\"click\", () => {\n this.close()\n })\n this.dialog_container.addClass(\"closable\").on(\"click\", (e) => {\n if (e.target !== this.dialog_container.get(0)) {\n return true\n }\n this.close()\n return false\n })\n this.$document.keydown((e) => {\n if (e.which === 27) {\n this.close()\n return false\n } else {\n return true\n }\n })\n }\n\n // Builds the html structure of the Dialog\n build() {\n this.dialog_container = $('<div class=\"alchemy-dialog-container\" />')\n this.dialog = $('<div class=\"alchemy-dialog\" />')\n this.dialog_body = $('<div class=\"alchemy-dialog-body\" />')\n this.dialog_header = $('<div class=\"alchemy-dialog-header\" />')\n this.dialog_title = $('<div class=\"alchemy-dialog-title\" />')\n this.close_button = $(\n '<button class=\"alchemy-dialog-close\"><alchemy-icon name=\"close\"></alchemy-icon></button>'\n )\n this.dialog_title.text(this.options.title)\n this.dialog_header.append(this.dialog_title)\n this.dialog_header.append(this.close_button)\n this.dialog.append(this.dialog_header)\n this.dialog.append(this.dialog_body)\n this.dialog_container.append(this.dialog)\n if (this.options.modal) {\n this.dialog.addClass(\"modal\")\n }\n if (this.options.padding) {\n this.dialog_body.addClass(\"padded\")\n }\n if (this.options.modal) {\n this.overlay = $('<div class=\"alchemy-dialog-overlay\" />')\n this.$body.append(this.overlay)\n }\n this.$body.append(this.dialog_container)\n }\n\n // Sets the correct size of the dialog\n // It normalizes the given size, so that it never acceeds the window size.\n resize() {\n const { width, height } = this.getSize()\n\n this.dialog.css({\n width: width,\n \"min-height\": height,\n overflow: this.options.overflow\n })\n\n if (this.options.overflow === \"hidden\") {\n this.dialog_body.css({\n height: height,\n overflow: \"auto\"\n })\n } else {\n this.dialog_body.css({\n \"min-height\": height,\n overflow: \"visible\"\n })\n }\n }\n\n getSize() {\n const padding = this.options.padding ? 16 : 0\n const doc_width = this.$window.width()\n const doc_height = this.$window.height()\n\n let width = this.width\n let height = this.height\n\n if (width >= doc_width) {\n width = doc_width - padding\n }\n\n if (height >= doc_height) {\n height = doc_height - padding - DEFAULTS.header_height\n }\n\n return { width, height }\n }\n}\n\n// Gets the last dialog instantiated, which is the current one.\nexport function currentDialog() {\n const { length } = currentDialogs\n if (length === 0) {\n return\n }\n return currentDialogs[length - 1]\n}\n\n// Utility function to close the current Dialog\n//\n// You can pass a callback function, that gets triggered after the Dialog gets closed.\n//\nexport function closeCurrentDialog(callback) {\n const dialog = currentDialog()\n if (dialog != null) {\n dialog.options.closed = callback\n return dialog.close()\n }\n}\n\n// Utility function to open a new Dialog\nexport function openDialog(url, options) {\n if (!url) {\n throw \"No url given! Please provide an url.\"\n }\n const dialog = new Dialog(url, options)\n dialog.open()\n}\n","import { createHtmlElement } from \"alchemy_admin/utils/dom_helpers\"\nimport { translate } from \"alchemy_admin/i18n\"\n\nconst getDefaults = () => ({\n // The default size of the dialog\n size: \"300x100\",\n title: translate(\"Please confirm\"),\n ok_label: translate(\"Yes\"),\n cancel_label: translate(\"No\"),\n on_ok() {}\n})\n\nclass ConfirmDialog {\n constructor(message, options = {}) {\n this.message = message\n this.options = { ...getDefaults(), ...options }\n this.#build()\n this.#bindEvents()\n }\n\n open() {\n requestAnimationFrame(() => {\n this.dialog.show()\n })\n }\n\n #build() {\n const width = this.options.size.split(\"x\")[0]\n this.dialog = createHtmlElement(`\n <sl-dialog label=\"${this.options.title}\" style=\"--width: ${width}px\">\n ${this.message}\n <button slot=\"footer\" type=\"reset\" class=\"secondary mx-1 my-0\" autofocus>\n ${this.options.cancel_label}\n </button>\n <button slot=\"footer\" type=\"submit\" class=\"mx-1 my-0\">\n ${this.options.ok_label}\n </button>\n </sl-dialog>\n `)\n document.body.append(this.dialog)\n }\n\n #bindEvents() {\n this.cancelButton.addEventListener(\"click\", (evt) => {\n evt.preventDefault()\n this.options.on_cancel()\n this.dialog.hide()\n })\n this.okButton.addEventListener(\"click\", (evt) => {\n evt.preventDefault()\n this.options.on_ok()\n this.dialog.hide()\n })\n // Prevent the dialog from closing when the user clicks on the overlay\n this.dialog.addEventListener(\"sl-request-close\", (event) => {\n if (event.detail.source === \"overlay\") {\n this.options.on_cancel()\n event.preventDefault()\n }\n })\n // Remove the dialog from the DOM after it has been hidden\n this.dialog.addEventListener(\"sl-after-hide\", () => {\n this.dialog.remove()\n })\n }\n\n get cancelButton() {\n return this.dialog.querySelector(\"button[type=reset]\")\n }\n\n get okButton() {\n return this.dialog.querySelector(\"button[type=submit]\")\n }\n}\n\n/* Opens a confirm dialog\n *\n * @param {string} message - The message that will be displayed to the user\n * @param {Object} [options={}] - Configuration options for the dialog\n * @param {string} [options.title=\"Please confirm\"] - The title of the overlay window\n * @param {string} [options.cancel_label=\"No\"] - The label of the cancel button\n * @param {string} [options.ok_label=\"Yes\"] - The label of the ok button\n *\n * @returns {Promise<void>} A promise that resolves to true when the OK button is clicked and\n * resolves to false when the cancel button is clicked. Works as confirm dialog replacement\n * for Turbo.confirm.\n */\nexport function openConfirmDialog(message, options = {}) {\n return new Promise((resolve) => {\n const dialog = new ConfirmDialog(message, {\n ...options,\n on_ok() {\n resolve(true)\n },\n on_cancel() {\n resolve(false)\n }\n })\n dialog.open()\n })\n}\n","/**\n * To show the \"Please wait\" overlay.\n * Pass false to hide it.\n * @param {boolean} show\n */\nexport default function pleaseWaitOverlay(show = true) {\n document.querySelector(\"alchemy-overlay\").show = !!show\n}\n","import { openConfirmDialog } from \"alchemy_admin/confirm_dialog\"\nimport { translate } from \"alchemy_admin/i18n\"\nimport pleaseWaitOverlay from \"alchemy_admin/please_wait_overlay\"\n\nfunction checkPageDirtyness(element) {\n let callback = () => {}\n\n if ($(element).is(\"form\")) {\n callback = function () {\n const $form = $(\n `<form action=\"${element.action}\" method=\"POST\" style=\"display: none\" />`\n )\n $form.append($(element).find(\"input\"))\n $form.appendTo(\"body\")\n\n pleaseWaitOverlay()\n $form.trigger(\"submit\")\n }\n } else if ($(element).is(\"a\")) {\n callback = () => Turbo.visit(element.pathname)\n }\n\n const isPageDirty =\n document.querySelectorAll(\"alchemy-element-editor.dirty\").length > 0\n\n if (isPageDirty) {\n openConfirmDialog(translate(\"page_dirty_notice\"), {\n title: translate(\"warning\"),\n ok_label: translate(\"ok\"),\n cancel_label: translate(\"cancel\")\n }).then((proceed) => {\n if (proceed) {\n window.onbeforeunload = void 0\n callback()\n }\n })\n return false\n }\n return true\n}\n\nfunction PageLeaveObserver() {\n document.querySelectorAll(\"#main_navi a\").forEach((element) => {\n element.addEventListener(\"click\", (event) => {\n if (!checkPageDirtyness(event.currentTarget)) {\n event.preventDefault()\n }\n })\n })\n}\n\nexport default {\n checkPageDirtyness,\n PageLeaveObserver\n}\n","// Creates a fixed element tab.\nexport function createTab(element_id, label) {\n const fixed_elements = document.getElementById(\"fixed-elements\")\n const panel_name = `fixed-element-${element_id}`\n\n const tab = `<sl-tab slot=\"nav\" panel=\"${panel_name}\">${label}</sl-tab>`\n const panel = `<sl-tab-panel name=\"${panel_name}\" style=\"--padding: 0\" />`\n\n fixed_elements.innerHTML += tab + panel\n\n window.requestAnimationFrame(function () {\n fixed_elements.show(panel_name)\n })\n}\n\nexport function removeTab(element_id) {\n const fixed_elements = document.getElementById(\"fixed-elements\")\n const panel_name = `fixed-element-${element_id}`\n\n fixed_elements.querySelector(`sl-tab[panel=\"${panel_name}\"]`).remove()\n fixed_elements.querySelector(`sl-tab-panel[name=\"${panel_name}\"]`).remove()\n\n fixed_elements.show(\"main-content-elements\")\n}\n","import { createHtmlElement } from \"alchemy_admin/utils/dom_helpers\"\n\nfunction build(message, flashType) {\n const flashNotices = document.getElementById(\"flash_notices\")\n const flashMessage = createHtmlElement(`\n <alchemy-message type=\"${flashType}\" dismissable>\n ${message}\n </alchemy-message>\n `)\n flashNotices.append(flashMessage)\n}\n\nexport function growl(message, style = \"notice\") {\n build(message, style)\n}\n","import { translate } from \"alchemy_admin/i18n\"\nimport { Dialog } from \"alchemy_admin/dialog\"\n\n// Matches a URL fragment (#anchor) at the end of a string.\n// Covers RFC 3986 unreserved characters (ALPHA, DIGIT, \"-\", \".\", \"_\", \"~\")\n// which are the characters valid in URL fragments and common in DOM element IDs.\nconst ANCHOR_REGEX = /#[\\w.~-]+$/\n\n// Represents the link Dialog that appears, if a user clicks the link buttons\n// in TinyMCE or on an Ingredient that has links enabled (e.g. Picture)\n//\nexport class LinkDialog extends Dialog {\n #onCreateLink\n\n constructor(link) {\n const url = new URL(Alchemy.routes.link_admin_pages_path, window.location)\n const parameterMapping = {\n url: link.url,\n selected_tab: link.type,\n link_title: link.title,\n link_target: link.target\n }\n\n // searchParams.set would also add undefined values\n Object.keys(parameterMapping).forEach((key) => {\n if (parameterMapping[key]) {\n url.searchParams.set(key, parameterMapping[key])\n }\n })\n\n super(url.href, {\n size: \"600x320\",\n title: translate(\"Link\")\n })\n }\n\n /**\n * Called from Dialog class after the url was loaded\n */\n replace(data) {\n // let Dialog class handle the content replacement\n super.replace(data)\n this.#attachEvents()\n }\n\n /**\n * make the open method a promise\n * maybe in a future version the whole Dialog will respond with a promise result if the dialog is closing\n * @returns {Promise<unknown>}\n */\n open() {\n super.open()\n return new Promise((resolve) => (this.#onCreateLink = resolve))\n }\n\n /**\n * Attaches click events to forms in the link dialog.\n */\n #attachEvents() {\n // enable the dom selection in internal link tab\n const internalForm = document.querySelector(\n '[data-link-form-type=\"internal\"]'\n )\n const attachmentSelect = document.querySelector(\n '[data-link-form-type=\"file\"] alchemy-attachment-select'\n )\n\n internalForm.addEventListener(\"Alchemy.RemoteSelect.Change\", (e) => {\n this.#updatePage(e.detail.added)\n })\n\n attachmentSelect.addEventListener(\"Alchemy.RemoteSelect.Change\", (e) => {\n const attachment = e.detail.added\n document.getElementById(\"file_link\").value = attachment\n ? attachment.url\n : \"\"\n })\n\n document.querySelectorAll(\"[data-link-form-type]\").forEach((form) => {\n form.addEventListener(\"submit\", (e) => {\n e.preventDefault()\n this.#submitForm(e.target.dataset.linkFormType)\n })\n })\n }\n\n /**\n * update page select and set anchor select\n * @param page\n */\n #updatePage(page = null) {\n const internalLink = document.getElementById(\"internal_link\")\n const domIdSelect = document.querySelector(\n '[data-link-form-type=\"internal\"] alchemy-dom-id-api-select'\n )\n\n internalLink.value = page ? page.url_path : \"\"\n domIdSelect.page = page ? page.id : undefined\n }\n\n /**\n * submit the form itself\n * @param linkType\n */\n #submitForm(linkType) {\n const elementAnchor = document.getElementById(\"element_anchor\")\n let url = document.getElementById(`${linkType}_link`).value\n\n if (linkType === \"internal\" && elementAnchor.value !== \"\") {\n // remove possible fragments on the url and attach the fragment (which contains the #)\n url = url.replace(ANCHOR_REGEX, \"\") + elementAnchor.value\n } else if (linkType === \"external\" && !url.match(Alchemy.link_url_regexp)) {\n // show validation error and prevent link creation\n this.#showValidationError()\n return\n }\n\n // Create the link\n this.#onCreateLink({\n url: url.trim(),\n title: document.getElementById(`${linkType}_link_title`).value,\n target: document.getElementById(`${linkType}_link_target`)?.value,\n type: linkType\n })\n this.close()\n }\n\n /**\n * Shows validation errors\n */\n #showValidationError() {\n const errors = document.getElementById(\"errors\")\n errors.querySelector(\"ul\").innerHTML =\n `<li>${Alchemy.t(\"url_validation_failed\")}</li>`\n errors.style.display = \"block\"\n }\n}\n","import { growl } from \"alchemy_admin/growler\"\nimport { translate } from \"alchemy_admin/i18n\"\n\nclass PreviewWindow extends HTMLIFrameElement {\n #afterLoad\n #reloadIcon\n #loadTimeout\n #previewReadyHandler\n\n constructor() {\n super()\n this.addEventListener(\"load\", this)\n this.#previewReadyHandler = this.#handlePreviewReadyMessage.bind(this)\n }\n\n handleEvent(evt) {\n if (evt.type === \"load\") {\n this.#clearLoadTimeout()\n this.#stopSpinner()\n this.#afterLoad?.call(this, evt)\n }\n }\n\n #handlePreviewReadyMessage(event) {\n if (event.data.message === \"Alchemy.previewReady\") {\n this.#clearLoadTimeout()\n this.#stopSpinner()\n this.#afterLoad?.call(this, event)\n }\n }\n\n connectedCallback() {\n let url = this.url\n\n this.#attachEvents()\n window.addEventListener(\"message\", this.#previewReadyHandler)\n\n if (window.localStorage.getItem(\"alchemy-preview-url\")) {\n url = window.localStorage.getItem(\"alchemy-preview-url\")\n this.previewUrlSelect.value = url\n }\n\n this.refresh(url)\n }\n\n disconnectedCallback() {\n key.unbind(\"alt+r\")\n window.removeEventListener(\"message\", this.#previewReadyHandler)\n }\n\n postMessage(data) {\n this.contentWindow.postMessage(data, \"*\")\n }\n\n resize(width) {\n this.style.width = `${width}px`\n }\n\n refresh(url) {\n this.#startSpinner()\n\n if (url) {\n this.src = url\n } else {\n this.src = this.url\n }\n\n // Set 5s timeout as fallback - if iframe doesn't load, stop spinner anyway\n this.#clearLoadTimeout()\n this.#loadTimeout = setTimeout(() => {\n this.#stopSpinner()\n growl(translate(\"Preview failed to load\"), \"warning\")\n }, 5000)\n\n return new Promise((resolve) => {\n this.#afterLoad = resolve\n })\n }\n\n set isDragged(dragged) {\n this.style.transitionProperty = dragged ? \"none\" : null\n this.style.pointerEvents = dragged ? \"none\" : null\n }\n\n #attachEvents() {\n this.reloadButton?.addEventListener(\"click\", (evt) => {\n evt.preventDefault()\n this.refresh()\n })\n\n key(\"alt+r\", () => this.refresh())\n\n this.sizeSelect.addEventListener(\"change\", (evt) => {\n const select = evt.target\n const width = select.value\n\n if (width === \"\") {\n this.style.width = null\n } else {\n this.resize(width)\n }\n })\n\n this.previewUrlSelect?.addEventListener(\"change\", (evt) => {\n const url = evt.target.value\n window.localStorage.setItem(\"alchemy-preview-url\", url)\n this.refresh(url)\n })\n }\n\n #startSpinner() {\n // Only save the reload icon if we're not already showing a spinner\n if (!this.reloadButton.innerHTML.includes(\"alchemy-spinner\")) {\n this.#reloadIcon = this.reloadButton.innerHTML\n }\n this.reloadButton.innerHTML = `<alchemy-spinner size=\"small\"></alchemy-spinner>`\n }\n\n #stopSpinner() {\n this.reloadButton.innerHTML = this.#reloadIcon\n }\n\n #clearLoadTimeout() {\n if (this.#loadTimeout) {\n clearTimeout(this.#loadTimeout)\n this.#loadTimeout = null\n }\n }\n\n get url() {\n return this.getAttribute(\"url\")\n }\n\n get sizeSelect() {\n return document.querySelector(\"select#preview_size\")\n }\n\n get previewUrlSelect() {\n return document.querySelector(\"select#preview_url\")\n }\n\n get reloadButton() {\n return document.querySelector(\"#reload_preview_button\")\n }\n}\n\ncustomElements.define(\"alchemy-preview-window\", PreviewWindow, {\n extends: \"iframe\"\n})\n\nexport function reloadPreview() {\n const previewWindow = document.getElementById(\"alchemy_preview_window\")\n previewWindow.refresh()\n}\n","export default class IngredientAnchorLink {\n static updateIcon(ingredientId, active = false) {\n const ingredientEditor = document.querySelector(\n `[data-ingredient-id=\"${ingredientId}\"]`\n )\n if (ingredientEditor) {\n const icon = ingredientEditor.querySelector(\n \".edit-ingredient-anchor-link alchemy-icon\"\n )\n icon.setAttribute(\"icon-style\", active ? \"fill\" : \"line\")\n }\n }\n}\n","import { reloadPreview } from \"alchemy_admin/components/preview_window\"\nimport { removeTab } from \"alchemy_admin/fixed_elements\"\nimport { closeCurrentDialog } from \"alchemy_admin/dialog\"\nimport IngredientAnchorLink from \"alchemy_admin/ingredient_anchor_link\"\nimport pleaseWaitOverlay from \"alchemy_admin/please_wait_overlay\"\n\nclass Action extends HTMLElement {\n constructor() {\n super()\n\n // map action names with Javascript functions\n this.actions = {\n // add a intermediate closeCurrentDialog - action\n // this will be gone, if all dialogs are working with a promise and\n // we don't have to implicitly close the dialog\n closeCurrentDialog,\n reloadPreview,\n removeFixedElement: removeTab,\n updateAnchorIcon: IngredientAnchorLink.updateIcon,\n hidePleaseWaitOverlay() {\n pleaseWaitOverlay(false)\n }\n }\n }\n\n connectedCallback() {\n const func = this.actions[this.name]\n\n if (func) {\n func(...this.params)\n } else {\n console.error(`Unknown Alchemy action: ${this.name}`)\n }\n\n this.remove()\n }\n\n get name() {\n return this.getAttribute(\"name\")\n }\n\n get params() {\n if (this.hasAttribute(\"params\")) {\n return JSON.parse(this.getAttribute(\"params\"))\n }\n return []\n }\n}\n\ncustomElements.define(\"alchemy-action\", Action)\n","import { toCamelCase } from \"alchemy_admin/utils/string_conversions\"\n\nexport class AlchemyHTMLElement extends HTMLElement {\n static properties = {}\n\n /**\n * create the list of observed attributes\n * this function is a requirement for the `attributeChangedCallback` - method\n * @returns {string[]}\n * @link https://developer.mozilla.org/en-US/docs/Web/API/Web_Components#reference\n */\n static get observedAttributes() {\n return Object.keys(this.properties)\n }\n\n constructor(options = {}) {\n super()\n\n this.options = options\n this.changeComponent = true\n this.initialContent = this.innerHTML // store the inner content of the component\n }\n\n /**\n * run when the component will be initialized by the Browser\n * this is a default function\n * @link https://developer.mozilla.org/en-US/docs/Web/API/Web_Components#reference\n */\n async connectedCallback() {\n // parse the properties object and register property with the default values\n Object.keys(this.constructor.properties).forEach((name) => {\n // if the options was given via the constructor, they should be prefer (e.g. new <WebComponentName>({title: \"Foo\"}))\n this[name] =\n this.options[name] ?? this.constructor.properties[name].default\n })\n\n // then process the attributes\n this.getAttributeNames().forEach((name) => this._updateFromAttribute(name))\n\n // render the component\n this._updateComponent()\n await this.connected()\n }\n\n /**\n * disconnected callback if the component is removed from the DOM\n * this is currently only a Proxy to the disconnected - callback to use the same callback structure\n * as for the connected - callback\n * @link https://developer.mozilla.org/en-US/docs/Web/API/Web_Components#reference\n */\n disconnectedCallback() {\n this.disconnected()\n }\n\n /**\n * triggered by the browser, if one of the observed attributes is changing\n * @link https://developer.mozilla.org/en-US/docs/Web/API/Web_Components#reference\n */\n attributeChangedCallback(name) {\n this._updateFromAttribute(name)\n this._updateComponent()\n }\n\n /**\n * a connected method to make it easier to overwrite the connection callback\n */\n async connected() {}\n\n /**\n * a disconnected method to make it easier to overwrite the disconnection callback\n */\n disconnected() {}\n\n /**\n * empty method container to allow the child component to put the rendered string into this method\n * @returns {String}\n */\n render() {\n return this.initialContent\n }\n\n /**\n * after render callback\n * the function will be triggered after the DOM was updated\n */\n afterRender() {}\n\n /**\n * Dispatches a custom event with given name\n * @param {string} name The name of the custom event\n * @param {object} detail Optional event details\n */\n dispatchCustomEvent(name, detail = {}) {\n const event = new CustomEvent(`Alchemy.${name}`, { bubbles: true, detail })\n this.dispatchEvent(event)\n }\n\n /**\n * (re)render the component content inside the component container\n * @private\n */\n _updateComponent() {\n if (this.changeComponent) {\n this.innerHTML = this.render()\n this.changeComponent = false\n this.afterRender()\n }\n }\n\n /**\n * update the value from the given attribute\n *\n * @param {string} name\n * @private\n */\n _updateFromAttribute(name) {\n const attributeValue = this.getAttribute(name)\n const propertyName = toCamelCase(name)\n const isBooleanValue =\n attributeValue.length === 0 || attributeValue === \"true\"\n\n const value = isBooleanValue ? true : attributeValue\n\n if (this[propertyName] !== value) {\n this[propertyName] = value\n this.changeComponent = true\n }\n }\n}\n","/**\n * convert dashes and underscore strings into camelCase strings\n * @param {string} str\n * @returns {string}\n */\nexport function toCamelCase(str) {\n return str\n .split(/-|_/)\n .reduce((a, b) => a + b.charAt(0).toUpperCase() + b.slice(1))\n}\n","import { AlchemyHTMLElement } from \"alchemy_admin/components/alchemy_html_element\"\nimport { setupSelectLocale } from \"alchemy_admin/i18n\"\n\nexport function hightlightTerm(name, term) {\n return name.replace(new RegExp(term, \"gi\"), (match) => `<em>${match}</em>`)\n}\n\nexport class RemoteSelect extends AlchemyHTMLElement {\n static properties = {\n allowClear: { default: false },\n selection: { default: undefined },\n placeholder: { default: \"\" },\n queryParams: { default: \"{}\" },\n url: { default: \"\" }\n }\n\n async connected() {\n await setupSelectLocale()\n\n this.input.classList.add(\"alchemy_selectbox\")\n\n $(this.input)\n .select2(this.select2Config)\n .on(\"select2-open\", (evt) => {\n this.onOpen(evt)\n })\n .on(\"change\", (evt) => {\n this.onChange(evt)\n })\n }\n\n /**\n * Optional on change handler called by Select2.\n * @param {Event} event\n */\n onChange(event) {\n this.dispatchCustomEvent(\"RemoteSelect.Change\", {\n removed: event.removed,\n added: event.added\n })\n }\n\n /**\n * Optional on open handler called by Select2.\n * @param {Event} event\n */\n onOpen(event) {\n // add focus to the search input. Select2 is handling the focus on the first opening,\n // but it does not work the second time. One process in select2 is \"stealing\" the focus\n // if the command is not delayed. It is an intermediate solution until we are going to\n // move away from Select2\n setTimeout(() => {\n document.querySelector(\"#select2-drop .select2-input\").focus()\n }, 100)\n }\n\n get input() {\n return this.getElementsByTagName(\"input\")[0]\n }\n\n get select2Config() {\n return {\n placeholder: this.placeholder,\n allowClear: this.allowClear,\n initSelection: (_$el, callback) => {\n if (this.selection) {\n callback(JSON.parse(this.selection))\n }\n },\n ajax: this.ajaxConfig,\n formatSelection: (item) => this._renderResult(item),\n formatResult: (item, _el, query) =>\n this._renderListEntry(item, query.term)\n }\n }\n\n /**\n * Ajax configuration for Select2\n * @returns {object}\n */\n get ajaxConfig() {\n return {\n url: this.url,\n datatype: \"json\",\n quietMillis: 300,\n data: (term, page) => this._searchQuery(term, page),\n results: (response) => this._parseResponse(response)\n }\n }\n\n /**\n * Search query send to server from select2\n * @param {string} term\n * @param {number} page\n * @returns {object}\n * @private\n */\n _searchQuery(term, page) {\n return {\n q: {\n name_cont: term,\n ...JSON.parse(this.queryParams)\n },\n page: page\n }\n }\n\n /**\n * Parses server response into select2 results object\n * @param {object} response\n * @returns {object}\n * @private\n */\n _parseResponse(response) {\n const meta = response.meta\n return {\n results: response.data,\n more: meta.page * meta.per_page < meta.total_count\n }\n }\n\n /**\n * result which is visible if a page was selected\n * @param {object} item\n * @returns {string}\n * @private\n */\n _renderResult() {\n throw new Error(\n \"You need to define a _renderResult function on your sub class!\"\n )\n }\n\n /**\n * html template for each list entry\n * @param {object} item\n * @param {string} term\n * @returns {string}\n * @private\n */\n _renderListEntry() {\n throw new Error(\n \"You need to define a _renderListEntry function on your sub class!\"\n )\n }\n\n /**\n * hightlighted search term\n * @param {string} name\n * @param {string} term\n * @returns {string}\n * @private\n */\n _hightlightTerm(name, term) {\n return hightlightTerm(name, term)\n }\n}\n","import { RemoteSelect } from \"alchemy_admin/components/remote_select\"\n\nclass AttachmentSelect extends RemoteSelect {\n _renderResult(item) {\n return this._renderListEntry(item)\n }\n\n /**\n * html template for each list entry\n * @param {object} page\n * @param {string} term\n * @returns {string}\n * @private\n */\n _renderListEntry(attachment, term) {\n return `\n <div class=\"attachment-select--attachment\">\n <alchemy-icon name=\"${attachment.icon_css_class}\"></alchemy-icon>\n <span class=\"attachment-select--attachment-name\">${this._hightlightTerm(attachment.name, term)}</span>\n </div>\n `\n }\n}\n\ncustomElements.define(\"alchemy-attachment-select\", AttachmentSelect)\n","// Dispatch a submit event on change of input or select elements\n// contained in a form, so that Turbo can submit the form.\nclass AutoSubmit extends HTMLElement {\n connectedCallback() {\n // Still using jQuery here, because select2 does not emit\n // the event from the original select element.\n $(this).on(\"change\", function (event) {\n // We need to dispatch a submit event, so that Turbo that listens\n // to it submits the search form us.\n const submitEvent = new Event(\"submit\", {\n bubbles: true,\n cancelable: true\n })\n event.target.form.dispatchEvent(submitEvent)\n return false\n })\n }\n}\n\ncustomElements.define(\"alchemy-auto-submit\", AutoSubmit)\n","import Spinner from \"alchemy_admin/spinner\"\n\nclass Button extends HTMLButtonElement {\n connectedCallback() {\n if (this.form) {\n this.form.addEventListener(\"submit\", this)\n\n if (this.form.dataset.remote == \"true\") {\n this.form.addEventListener(\"ajax:complete\", this)\n }\n\n this.form.addEventListener(\"turbo:submit-end\", this)\n } else {\n console.warn(\"No form for button found!\", this)\n }\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"submit\":\n const isDisabled = this.getAttribute(\"disabled\") === \"disabled\"\n\n if (isDisabled) {\n event.preventDefault()\n event.stopPropagation()\n } else {\n this.disable()\n }\n break\n case \"ajax:complete\":\n case \"turbo:submit-end\":\n this.enable()\n break\n }\n }\n\n disable() {\n const spinner = new Spinner(\"small\")\n const rect = this.getBoundingClientRect()\n\n this.dataset.initialButtonText = this.innerHTML\n this.setAttribute(\"disabled\", \"disabled\")\n this.setAttribute(\"tabindex\", \"-1\")\n this.classList.add(\"disabled\")\n this.style.width = `${rect.width}px`\n this.style.height = `${rect.height}px`\n this.innerHTML = \"&nbsp;\"\n\n spinner.spin(this)\n }\n\n enable() {\n this.classList.remove(\"disabled\")\n this.removeAttribute(\"disabled\")\n this.removeAttribute(\"tabindex\")\n this.style.width = null\n this.style.height = null\n this.innerHTML = this.dataset.initialButtonText\n }\n}\n\ncustomElements.define(\"alchemy-button\", Button, { extends: \"button\" })\n","/**\n * Show the character counter below input fields and textareas\n */\nimport { AlchemyHTMLElement } from \"alchemy_admin/components/alchemy_html_element\"\nimport { translate } from \"alchemy_admin/i18n\"\n\nclass CharCounter extends AlchemyHTMLElement {\n static properties = {\n maxChars: { default: 60 }\n }\n connected() {\n this.translation = translate(\"allowed_chars\", this.maxChars)\n this.formField = this.getFormField()\n\n if (this.formField) {\n this.createDisplayElement()\n this.countCharacters()\n this.formField.addEventListener(\"keyup\", () => this.countCharacters()) // add arrow function to get a implicit this - binding\n }\n }\n\n getFormField() {\n const formFields = this.querySelectorAll(\"input, textarea\")\n return formFields.length > 0 ? formFields[0] : undefined\n }\n\n createDisplayElement() {\n this.display = document.createElement(\"small\")\n this.display.className = \"alchemy-char-counter\"\n this.formField.after(this.display)\n }\n\n countCharacters() {\n const charLength = this.formField.value.length\n this.display.textContent = `${charLength} ${this.translation}`\n this.display.classList.toggle(\"too-long\", charLength > this.maxChars)\n }\n}\n\ncustomElements.define(\"alchemy-char-counter\", CharCounter)\n","import \"clipboard\"\nimport { growl } from \"alchemy_admin/growler\"\n\nclass ClipboardButton extends HTMLElement {\n constructor() {\n super()\n\n this.innerHTML = `\n <alchemy-icon name=\"clipboard\"></alchemy-icon>\n `\n\n this.clipboard = new ClipboardJS(this, {\n text: () => {\n return this.getAttribute(\"content\")\n }\n })\n\n this.clipboard.on(\"success\", () => {\n growl(this.getAttribute(\"success-text\"))\n })\n }\n\n disconnectedCallback() {\n this.clipboard.destroy()\n }\n}\n\ncustomElements.define(\"alchemy-clipboard-button\", ClipboardButton)\n","const formatItem = (object) => {\n const optionEl = object.element[0]\n const swatch = optionEl.dataset.swatch || optionEl.value\n const customColor = optionEl.value === \"custom_color\"\n const colorIndicator = customColor\n ? `<alchemy-icon name=\"palette\"></alchemy-icon>`\n : `<span class=\"color-indicator\" style=\"--color: ${swatch}\"></span>`\n\n return `\n <div class=\"select-color-option\">\n ${colorIndicator}\n <span>${object.text}</span>\n </div>`\n}\n\nclass ColorSelect extends HTMLElement {\n connectedCallback() {\n if (this.select) {\n this.#initializeSelect2()\n $(this.select).on(\"change\", (event) =>\n this.#toggleColorPicker(event.val === \"custom_color\")\n )\n } else {\n this.colorInput?.addEventListener(\"input\", this)\n this.textInput?.addEventListener(\"input\", this)\n this.#toggleColorPicker(true)\n }\n }\n\n handleEvent(event) {\n switch (event.target) {\n case this.colorInput:\n this.textInput.value = this.colorInput.value\n break\n case this.textInput:\n this.colorInput.value = this.textInput.value\n break\n }\n }\n\n disconnectedCallback() {\n this.colorInput?.removeEventListener(\"input\", this)\n this.textInput?.removeEventListener(\"input\", this)\n }\n\n #initializeSelect2() {\n this.select.classList.add(\"alchemy_selectbox\")\n const options = {\n minimumResultsForSearch: 10,\n formatResult: formatItem,\n formatSelection: formatItem\n }\n $(this.select).select2(options)\n }\n\n #toggleColorPicker(enabled = true) {\n this.colorInput.disabled = !enabled\n }\n\n get colorInput() {\n return this.querySelector(\"input[type='color']\")\n }\n\n get textInput() {\n return this.querySelector(\"input[type='text']\")\n }\n\n get select() {\n return this.querySelector(\"select\")\n }\n}\n\ncustomElements.define(\"alchemy-color-select\", ColorSelect)\n","import { AlchemyHTMLElement } from \"alchemy_admin/components/alchemy_html_element\"\nimport { translate, currentLocale } from \"alchemy_admin/i18n\"\nimport flatpickr from \"flatpickr\"\n\nconst locale = currentLocale()\n\nclass Datepicker extends AlchemyHTMLElement {\n static properties = {\n inputType: { default: \"date\" }\n }\n\n constructor() {\n super()\n this.flatpickr = undefined\n }\n\n // Load the locales for flatpickr before setting it up.\n async connected() {\n // English is the default locale for flatpickr, so we don't need to load it\n if (locale !== \"en\") {\n await import(`flatpickr/${locale}.js`)\n }\n\n this.flatpickr = flatpickr(this.inputField, this.flatpickrOptions)\n }\n\n disconnected() {\n this.flatpickr.destroy()\n }\n\n get flatpickrOptions() {\n const enableTime = /time/.test(this.inputType)\n const options = {\n // alchemy_i18n supports `zh_CN` etc., but flatpickr only has two-letter codes (`zh`)\n locale: locale.slice(0, 2),\n altInput: true,\n altFormat: translate(`formats.${this.inputType}`),\n altInputClass: \"flatpickr-input\",\n enableTime,\n noCalendar: this.inputType === \"time\",\n time_24hr: translate(\"formats.time_24hr\"),\n onValueUpdate(_selectedDates, _dateStr, instance) {\n instance.element\n .closest(\"alchemy-element-editor\")\n ?.setDirty(this.inputField)\n }\n }\n\n if (enableTime) {\n options.dateFormat = \"Z\"\n }\n\n return options\n }\n\n get inputField() {\n return this.querySelector(\"input\")\n }\n}\n\ncustomElements.define(\"alchemy-datepicker\", Datepicker)\n","import { Dialog } from \"alchemy_admin/dialog\"\n\nexport class DialogLink extends HTMLAnchorElement {\n constructor() {\n super()\n this.addEventListener(\"click\", this)\n }\n\n handleEvent(evt) {\n if (!this.disabled) {\n this.openDialog()\n }\n evt.preventDefault()\n }\n\n openDialog() {\n this.dialog = new Dialog(this.getAttribute(\"href\"), this.dialogOptions)\n this.dialog.open()\n }\n\n get dialogOptions() {\n const options = this.dataset.dialogOptions\n ? JSON.parse(this.dataset.dialogOptions)\n : {}\n return options\n }\n\n get disabled() {\n return this.classList.contains(\"disabled\")\n }\n}\n\ncustomElements.define(\"alchemy-dialog-link\", DialogLink, { extends: \"a\" })\n","const JSON_CONTENT_TYPE = \"application/json\"\nconst TURBO_STREAM_CONTENT_TYPE = \"text/vnd.turbo-stream.html\"\n\nfunction isGetRequest(method) {\n return method.toLowerCase() === \"get\"\n}\n\nfunction prepareURL(path, data, method) {\n const url = new URL(window.location.origin + path)\n\n if (data && isGetRequest(method)) {\n url.search = new URLSearchParams(data).toString()\n }\n\n return url.toString()\n}\n\nfunction prepareHeaders(accept) {\n return {\n \"Content-Type\": \"application/json; charset=utf-8\",\n Accept: accept,\n \"X-Requested-With\": \"XMLHttpRequest\",\n \"X-CSRF-Token\": getToken()\n }\n}\n\nfunction prepareOptions(method, data, accept) {\n const headers = prepareHeaders(accept)\n const options = { method, headers }\n\n if (data && !isGetRequest(method)) {\n options.body = JSON.stringify(data)\n }\n\n return options\n}\n\nexport function getToken() {\n const metaTag = document.querySelector('meta[name=\"csrf-token\"]')\n return metaTag.attributes.content.textContent\n}\n\nexport function get(url, params) {\n return ajax(\"GET\", url, params)\n}\n\nexport function patch(url, data, accept) {\n return ajax(\"PATCH\", url, data, accept)\n}\n\nexport function post(url, data, accept = JSON_CONTENT_TYPE) {\n return ajax(\"POST\", url, data, accept)\n}\n\nexport default async function ajax(\n method,\n path,\n data,\n accept = JSON_CONTENT_TYPE\n) {\n const response = await fetch(\n prepareURL(path, data, method),\n prepareOptions(method, data, accept)\n )\n const contentType = response.headers.get(\"content-type\")\n const isJson = contentType?.includes(JSON_CONTENT_TYPE)\n const isTurboStream = contentType?.includes(TURBO_STREAM_CONTENT_TYPE)\n\n let responseData = null\n if (isJson) {\n responseData = await response.json()\n } else if (isTurboStream) {\n responseData = await response.text()\n // Automatically render Turbo Stream if Turbo is available\n if (typeof Turbo !== \"undefined\") {\n Turbo.renderStreamMessage(responseData)\n }\n }\n\n if (response.ok) {\n return { data: responseData, status: response.status }\n } else {\n throw responseData || new Error(\"An error occurred during the transaction\")\n }\n}\n","import { get } from \"alchemy_admin/utils/ajax\"\nimport { translate } from \"alchemy_admin/i18n\"\n\nclass DomIdSelect extends HTMLElement {\n dataItem(hash) {\n return {\n id: `#${hash}`,\n text: `#${hash}`\n }\n }\n\n get selectElement() {\n return this.querySelector('select[is=\"alchemy-select\"]')\n }\n}\n\nclass DomIdApiSelect extends DomIdSelect {\n #pageId = undefined\n\n connectedCallback() {\n this.page = this.getAttribute(\"page\")\n }\n\n async #fetchDomIds() {\n const result = await get(Alchemy.routes.api_ingredients_path, {\n page_id: this.#pageId\n })\n const options = result.data.ingredients\n .filter((ingredient) => ingredient.data?.dom_id)\n .map((ingredient) => this.dataItem(ingredient.data.dom_id))\n const prompt =\n options.length > 0 ? translate(\"None\") : translate(\"No anchors found\")\n\n this.selectElement.setOptions(options, prompt)\n this.selectElement.enable()\n }\n\n #reset() {\n // wait a tick to initialize the alchemy-select\n requestAnimationFrame(() => {\n this.selectElement.disable()\n this.selectElement.setOptions([], translate(\"Select a page first\"))\n })\n }\n\n set page(pageId) {\n this.#pageId = pageId\n pageId ? this.#fetchDomIds() : this.#reset()\n }\n}\n\nclass DomIdPreviewSelect extends DomIdSelect {\n connectedCallback() {\n // wait a tick to let the browser initialize the inner select component\n requestAnimationFrame(() => {\n const frame = document.getElementById(\"alchemy_preview_window\")\n const elements = frame.contentDocument?.querySelectorAll(\"[id]\") || []\n if (elements.length > 0) {\n const options = Array.from(elements).map((element) => {\n return this.dataItem(element.id)\n })\n this.selectElement.setOptions(options, translate(\"None\"))\n }\n })\n }\n}\n\ncustomElements.define(\"alchemy-dom-id-api-select\", DomIdApiSelect)\ncustomElements.define(\"alchemy-dom-id-preview-select\", DomIdPreviewSelect)\n","export class PublishElementButton extends HTMLElement {\n #scheduleButtonVariant\n\n connectedCallback() {\n this.#scheduleButtonVariant = this.scheduleButton.getAttribute(\"variant\")\n this.publishButton.addEventListener(\"click\", this)\n this.dropdown.addEventListener(\"sl-show\", this)\n this.dropdown.addEventListener(\"sl-hide\", this)\n }\n\n disconnectedCallback() {\n this.publishButton.removeEventListener(\"click\", this)\n this.dropdown.removeEventListener(\"sl-show\", this)\n this.dropdown.removeEventListener(\"sl-hide\", this)\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"click\":\n this.publishButton.loading = true\n break\n case \"sl-show\":\n this.scheduleButton.setAttribute(\"variant\", \"primary\")\n break\n case \"sl-hide\":\n this.scheduleButton.setAttribute(\"variant\", this.#scheduleButtonVariant)\n break\n }\n }\n\n get publishButton() {\n return this.querySelector(\"sl-button[type='submit']\")\n }\n\n get dropdown() {\n return this.querySelector(\"sl-dropdown\")\n }\n\n get scheduleButton() {\n return this.querySelector(\"sl-button[slot='trigger']\")\n }\n}\n\ncustomElements.define(\"alchemy-publish-element-button\", PublishElementButton)\n","import ajax from \"alchemy_admin/utils/ajax\"\nimport { removeTab } from \"alchemy_admin/fixed_elements\"\nimport { growl } from \"alchemy_admin/growler\"\nimport { reloadPreview } from \"alchemy_admin/components/preview_window\"\nimport { openConfirmDialog } from \"alchemy_admin/confirm_dialog\"\nimport { dispatchPageDirtyEvent } from \"alchemy_admin/components/element_editor\"\n\nexport class DeleteElementButton extends HTMLElement {\n constructor() {\n super()\n this.button?.addEventListener(\"click\", this)\n }\n\n async handleEvent() {\n const confirmed = await openConfirmDialog(this.message)\n if (confirmed) {\n const response = await ajax(\"DELETE\", this.url)\n this.#removeElement(response.data)\n }\n }\n\n #removeElement(data) {\n const elementEditor = this.closest(\"alchemy-element-editor\")\n elementEditor.addEventListener(\"transitionend\", () => {\n if (elementEditor.fixed) {\n removeTab(elementEditor.elementId)\n }\n elementEditor.remove()\n })\n elementEditor.classList.add(\"dismiss\")\n growl(data.message)\n if (data.pageHasUnpublishedChanges) {\n dispatchPageDirtyEvent(data)\n }\n reloadPreview()\n }\n\n get url() {\n return this.getAttribute(\"href\")\n }\n\n get message() {\n return this.getAttribute(\"message\")\n }\n\n get button() {\n return this.querySelector(\"button\")\n }\n}\n\ncustomElements.define(\"alchemy-delete-element-button\", DeleteElementButton)\n","import IngredientAnchorLink from \"alchemy_admin/ingredient_anchor_link\"\nimport { post } from \"alchemy_admin/utils/ajax\"\nimport { createHtmlElement } from \"alchemy_admin/utils/dom_helpers\"\nimport { growl } from \"alchemy_admin/growler\"\n\nimport \"alchemy_admin/components/element_editor/publish_element_button\"\nimport \"alchemy_admin/components/element_editor/delete_element_button\"\n\nexport function dispatchPageDirtyEvent(data) {\n document.dispatchEvent(\n new CustomEvent(\"alchemy:page-dirty\", {\n detail: { tooltip: data.publishButtonTooltip }\n })\n )\n}\n\nexport class ElementEditor extends HTMLElement {\n constructor() {\n super()\n\n // Add event listeners\n this.addEventListener(\"click\", this)\n // Triggered by child elements\n this.addEventListener(\"alchemy:element-update-title\", this)\n // We use of @rails/ujs for Rails remote forms\n this.addEventListener(\"ajax:complete\", this)\n\n // Dirty observer still needs to be jQuery\n // in order to support select2.\n $(this.form).on(\"change\", this.onChange)\n\n this.header?.addEventListener(\"dblclick\", () => {\n this.toggle()\n })\n this.toggleButton?.addEventListener(\"click\", (evt) => {\n const elementEditor = evt.target.closest(\"alchemy-element-editor\")\n if (elementEditor === this) {\n this.toggle()\n }\n })\n }\n\n connectedCallback() {\n // The placeholder while be being dragged is empty.\n if (this.classList.contains(\"ui-sortable-placeholder\")) {\n return\n }\n\n // When newly created, focus the element and refresh the preview\n if (this.hasAttribute(\"created\")) {\n this.focusElement()\n this.previewWindow?.refresh().then(() => {\n this.focusElementPreview()\n })\n this.removeAttribute(\"created\")\n }\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"click\":\n const elementEditor = event.target.closest(\"alchemy-element-editor\")\n if (elementEditor === this) {\n this.onClickElement()\n }\n break\n case \"ajax:complete\":\n if (event.target === this.body) {\n const xhr = event.detail[0]\n event.stopPropagation()\n this.onSaveElement(xhr)\n }\n break\n case \"alchemy:element-update-title\":\n if (!this.hasEditors && event.target == this.firstChild) {\n this.setTitle(event.detail.title)\n }\n break\n }\n }\n\n onChange(event) {\n const target = event.target\n // SortableJS fires a native change event :/\n // and we do not want to set the element editor dirty\n // when this happens\n if (target.classList.contains(\"nested-elements\")) {\n return\n }\n this.closest(\"alchemy-element-editor\").setDirty(target)\n event.stopPropagation()\n return false\n }\n\n /**\n * Scrolls to and highlights element\n * Expands if collapsed\n * Also chooses the right fixed elements tab, if necessary.\n * Can be triggered through custom event 'FocusElementEditor.Alchemy'\n * Used by the elements on click events in the preview frame.\n */\n async focusElement() {\n // Select tab if necessary\n if (document.querySelector(\"#fixed-elements\")) {\n await this.selectTabForElement()\n }\n // Expand if necessary\n await this.expand()\n this.selectElement(true)\n }\n\n focusElementPreview() {\n this.previewWindow?.postMessage({\n message: \"Alchemy.focusElement\",\n element_id: this.elementId\n })\n }\n\n onClickElement() {\n this.selectElement()\n this.focusElementPreview()\n }\n\n /**\n * Sets the element to saved state\n * Updates title\n * JS event bubbling will also update the parents element quote.\n * Shows error messages if ingredient validations fail\n * @argument {XMLHttpRequest} xhr\n */\n onSaveElement(xhr) {\n const data = JSON.parse(xhr.responseText)\n // Reset errors that might be visible from last save attempt\n this.setClean()\n // If validation failed\n if (xhr.status === 422) {\n const warning = data.warning\n // Create error messages\n // Mark ingredients as failed\n data.ingredientsWithErrors.forEach((ingredient) => {\n const ingredientEditor = this.querySelector(\n `[data-ingredient-id=\"${ingredient.id}\"]`\n )\n const errorDisplay = createHtmlElement(\n `<small class=\"error\">${ingredient.errorMessage}</small>`\n )\n ingredientEditor?.appendChild(errorDisplay)\n ingredientEditor?.classList.add(\"validation_failed\")\n })\n // Show message\n growl(warning, \"warn\")\n this.elementErrors.classList.remove(\"hidden\")\n } else {\n growl(data.notice)\n this.previewWindow?.refresh().then(() => {\n this.focusElementPreview()\n })\n this.updateTitle(data.previewText)\n data.ingredientAnchors.forEach((anchor) => {\n IngredientAnchorLink.updateIcon(anchor.ingredientId, anchor.active)\n })\n if (data.pageHasUnpublishedChanges) {\n dispatchPageDirtyEvent(data)\n }\n }\n }\n\n /**\n * Smoothly scrolls to element\n */\n scrollToElement() {\n // The timeout gives the browser some time to calculate the position\n // of nested elements correctly\n setTimeout(() => {\n this.scrollIntoView({\n behavior: \"smooth\"\n })\n }, 50)\n }\n\n /**\n * Highlight element and optionally scroll into view\n * @param {boolean} scroll smoothly scroll element into view. Default (false)\n */\n selectElement(scroll = false) {\n document\n .querySelectorAll(\"alchemy-element-editor.selected\")\n .forEach((el) => {\n el.classList.remove(\"selected\")\n })\n window.requestAnimationFrame(() => {\n this.classList.add(\"selected\")\n })\n if (scroll) this.scrollToElement()\n }\n\n /**\n * Selects tab for given element\n * Resolves the promise if this is done.\n * @returns {Promise}\n */\n selectTabForElement() {\n return new Promise((resolve, reject) => {\n const tabs = document.querySelector(\"#fixed-elements\")\n const panel = this.closest(\"sl-tab-panel\")\n if (tabs && panel) {\n tabs.show(panel.getAttribute(\"name\"))\n resolve()\n } else {\n reject(new Error(\"No tabs present\"))\n }\n })\n }\n\n /**\n * Sets the element into clean (safed) state\n */\n setClean() {\n this.dirty = false\n window.onbeforeunload = null\n this.elementErrors.classList.add(\"hidden\")\n\n if (this.hasEditors) {\n this.body.querySelectorAll(\".ingredient-editor\").forEach((el) => {\n el.classList.remove(\"dirty\", \"validation_failed\")\n el.querySelectorAll(\"small.error\").forEach((e) => e.remove())\n })\n }\n }\n\n /**\n * Sets the element into dirty (unsafed) state\n * @param {HTMLElement} editor\n */\n setDirty(editor) {\n if (this.hasEditors) {\n this.dirty = true\n\n if (!window.onbeforeunload) {\n window.onbeforeunload = (event) => event.preventDefault()\n }\n\n editor?.closest(\".ingredient-editor\")?.classList.add(\"dirty\")\n }\n }\n\n /**\n * Sets the title quote\n * @param {string} title\n */\n setTitle(title) {\n const quote = this.querySelector(\".element-header .preview_text_quote\")\n quote.textContent = title\n }\n\n /**\n * Expands or collapses element editor\n * If the element is dirty (has unsaved changes) it displays a confirm first.\n */\n async toggle() {\n if (this.collapsed) {\n await this.expand()\n } else {\n await this.collapse()\n }\n }\n\n /**\n * Collapses the element editor and persists the state on the server\n * @returns {Promise}\n */\n collapse() {\n if (this.collapsed || this.compact || this.fixed) {\n return Promise.resolve(\"Element is already collapsed.\")\n }\n\n const spinner = new Alchemy.Spinner(\"small\")\n spinner.spin(this.toggleButton)\n this.toggleIcon?.classList?.add(\"hidden\")\n return post(Alchemy.routes.collapse_admin_element_path(this.elementId))\n .then((response) => {\n const data = response.data\n\n this.collapsed = true\n this.toggleButton?.setAttribute(\"title\", data.title)\n\n // Collapse all nested elements if necessarry\n if (data.nestedElementIds.length) {\n const selector = data.nestedElementIds\n .map((id) => `#element_${id}`)\n .join(\", \")\n this.querySelectorAll(selector).forEach((nestedElement) => {\n nestedElement.collapsed = true\n nestedElement.toggleButton?.setAttribute(\"title\", data.title)\n })\n }\n })\n .catch((error) => {\n growl(error.message, \"error\")\n console.error(error)\n })\n .finally(() => {\n this.toggleIcon?.classList?.remove(\"hidden\")\n spinner.stop()\n })\n }\n\n /**\n * Collapses the element editor and persists the state on the server\n * @* @returns {Promise}\n */\n expand() {\n if (this.expanded && !this.compact) {\n return Promise.resolve(\"Element is already expanded.\")\n }\n\n if (this.compact && this.parentElementEditor) {\n return this.parentElementEditor.expand()\n } else {\n const spinner = new Alchemy.Spinner(\"small\")\n spinner.spin(this.toggleButton)\n this.toggleIcon?.classList.add(\"hidden\")\n\n return new Promise((resolve, reject) => {\n post(Alchemy.routes.expand_admin_element_path(this.elementId))\n .then((response) => {\n const data = response.data\n\n // First expand all parent elements if necessary\n if (data.parentElementIds.length) {\n const selector = data.parentElementIds\n .map((id) => `#element_${id}`)\n .join(\", \")\n document.querySelectorAll(selector).forEach((parentElement) => {\n parentElement.collapsed = false\n parentElement.toggleButton?.setAttribute(\"title\", data.title)\n })\n }\n // Finally expand ourselve\n this.collapsed = false\n this.toggleButton?.setAttribute(\"title\", data.title)\n // Resolve the promise that scrolls to the element very last\n resolve()\n })\n .catch((error) => {\n growl(error.message, \"error\")\n console.error(error)\n reject(error)\n })\n .finally(() => {\n this.toggleIcon?.classList?.remove(\"hidden\")\n spinner.stop()\n })\n })\n }\n }\n\n /**\n * Updates the quote in the element header and dispatches event\n * to parent elements\n * @param {string} title\n */\n updateTitle(title) {\n this.setTitle(title)\n this.dispatchEvent(\n new CustomEvent(\"alchemy:element-update-title\", {\n bubbles: true,\n detail: { title }\n })\n )\n }\n\n /**\n * Sets element published or hidden\n * @param {boolean}\n */\n set published(isPublished) {\n if (isPublished) {\n this.classList.remove(\"element-hidden\")\n } else {\n this.classList.add(\"element-hidden\")\n }\n }\n\n /**\n * Is element published or hidden\n * @returns {boolean}\n */\n get published() {\n return !this.classList.contains(\"hidden\")\n }\n\n /**\n * @returns {boolean}\n */\n get compact() {\n return this.getAttribute(\"compact\") !== null\n }\n\n /**\n * @returns {boolean}\n */\n get fixed() {\n return this.getAttribute(\"fixed\") !== null\n }\n\n /**\n * @param {boolean} value\n */\n set collapsed(value) {\n this.classList.toggle(\"folded\", value)\n this.classList.toggle(\"expanded\", !value)\n this.toggleIcon &&\n (this.toggleIcon.name = value ? \"arrow-left-s\" : \"arrow-down-s\")\n }\n\n /**\n * @returns {boolean}\n */\n get collapsed() {\n return this.classList.contains(\"folded\")\n }\n\n /**\n * @returns {boolean}\n */\n get expanded() {\n return !this.collapsed\n }\n\n /**\n * Toggles the dirty class\n *\n * @param {boolean} value\n */\n set dirty(value) {\n this.classList.toggle(\"dirty\", value)\n }\n\n /**\n * Returns the dirty state of this element\n *\n * @returns {boolean}\n */\n get dirty() {\n return this.classList.contains(\"dirty\")\n }\n\n /**\n * Returns the element header\n *\n * @returns {HTMLElement|undefined}\n */\n get header() {\n return this.querySelector(`.element-header`)\n }\n\n /**\n * Returns the immediate body container of this element if present\n *\n * Makes sure it does not return a nested elements body\n * by scoping the selector to this elements id.\n *\n * @returns {HTMLElement|undefined}\n */\n get body() {\n return this.querySelector(this.bodySelector)\n }\n\n get bodySelector() {\n return `#${this.id} > .element-body`\n }\n\n /**\n * Returns the immediate footer container of this element if present\n *\n * Makes sure it does not return a nested elements footer\n * by scoping the selector to this elements id.\n *\n * @returns {HTMLElement|undefined}\n */\n get footer() {\n return this.querySelector(`#${this.id} > .element-footer`)\n }\n\n /**\n * The collapse/expand toggle button\n *\n * @returns {HTMLButtonElement|undefined}\n */\n get toggleButton() {\n return this.querySelector(\".element-toggle\")\n }\n\n /**\n * The collapse/expand toggle buttons icon\n *\n * @returns {HTMLElement|undefined}\n */\n get toggleIcon() {\n return this.toggleButton?.querySelector(\"alchemy-icon\")\n }\n\n /**\n * The validation messages list container\n *\n * @returns {HTMLElement}\n */\n get elementErrors() {\n return this.body.querySelector(\".element_errors\")\n }\n\n /**\n * The element database id\n *\n * @returns {string}\n */\n get elementId() {\n return this.dataset.elementId\n }\n\n /**\n * The element defintion name\n *\n * @returns {string}\n */\n get elementName() {\n return this.dataset.elementName\n }\n\n /**\n * Does this element have ingredient editor fields?\n *\n * @returns {boolean}\n */\n get hasEditors() {\n return !!this.body?.querySelector(\".element-ingredient-editors\")\n }\n\n /**\n * Does this element have nested elements?\n *\n * @returns {boolean}\n */\n get hasChildren() {\n return !!this.querySelector(\".nested-elements\")\n }\n\n /**\n * The first child element editor if present\n *\n * @returns {HTMLButtonElement|undefined}\n */\n get firstChild() {\n return this.querySelector(\"alchemy-element-editor\")\n }\n\n /**\n * The form element if present\n *\n * @returns {HTMLFormElement|undefined}\n */\n get form() {\n return this.querySelector(\"form.element-body\")\n }\n\n /**\n * The parent element editor if present\n *\n * @returns {ElementEditor|undefined}\n */\n get parentElementEditor() {\n return this.parentElement?.closest(\"alchemy-element-editor\")\n }\n\n get previewWindow() {\n return document.getElementById(\"alchemy_preview_window\")\n }\n}\n\ncustomElements.define(\"alchemy-element-editor\", ElementEditor)\n","import { hightlightTerm } from \"alchemy_admin/components/remote_select\"\n\nconst formatSelection = (option) => {\n return `\n <div class=\"element-select-name\">\n ${option.icon}<span>${option.text}</span>\n </div>\n `\n}\n\nconst formatItem = (icon, text, hint) => {\n const description = hint\n ? `<div class=\"element-select-description\">${hint}</div>`\n : \"\"\n return `\n <div class=\"element-select-item\">\n ${formatSelection({ icon, text })}\n ${description}\n </div>\n `\n}\n\nclass ElementSelect extends HTMLElement {\n constructor() {\n super()\n }\n\n connectedCallback() {\n const results = this.options\n const options = {\n minimumResultsForSearch: 3,\n dropdownAutoWidth: true,\n data() {\n return { results }\n },\n formatResult: (option, _el, search) => {\n let text\n\n if (option.id === \"\") return option.text\n if (search.term !== \"\") {\n text = hightlightTerm(option.text, search.term)\n } else {\n text = option.text\n }\n\n return formatItem(option.icon, text, option.hint)\n },\n formatSelection,\n placeholder: this.placeholder\n }\n $(this.inputField).select2(options)\n }\n\n get options() {\n return JSON.parse(this.getAttribute(\"options\"))\n }\n\n get placeholder() {\n return this.getAttribute(\"placeholder\")\n }\n\n get inputField() {\n return this.querySelector(\"input\")\n }\n}\n\ncustomElements.define(\"alchemy-element-select\", ElementSelect)\n","import { ElementEditor } from \"alchemy_admin/components/element_editor\"\n\nclass ElementsWindow extends HTMLElement {\n #visible = true\n #turboFrame = null\n\n constructor() {\n super()\n this.#attachEvents()\n }\n\n connectedCallback() {\n this.toggleButton?.addEventListener(\"click\", (evt) => {\n evt.preventDefault()\n this.toggle()\n })\n if (window.location.hash) {\n this.focusElementEditor(window.location.hash)\n }\n this.resize()\n }\n\n collapseAllElements() {\n this.querySelectorAll(\n \"alchemy-element-editor:not([compact]):not([fixed])\"\n ).forEach((editor) => editor.collapse())\n }\n\n toggle() {\n this.#visible ? this.hide() : this.show()\n }\n\n show() {\n document.body.classList.add(\"elements-window-visible\")\n this.#visible = true\n this.toggleButton.closest(\"sl-tooltip\").content = Alchemy.t(\"Hide elements\")\n this.toggleButton\n .querySelector(\"alchemy-icon\")\n .setAttribute(\"name\", \"menu-unfold\")\n this.resize()\n }\n\n hide() {\n document.body.classList.remove(\"elements-window-visible\")\n document.body.style.removeProperty(\"--elements-window-width\")\n this.#visible = false\n this.toggleButton.closest(\"sl-tooltip\").content = Alchemy.t(\"Show elements\")\n this.toggleButton\n .querySelector(\"alchemy-icon\")\n .setAttribute(\"name\", \"menu-fold\")\n }\n\n resize(width) {\n if (width === undefined) {\n width = this.widthFromCookie\n }\n\n if (width) {\n document.body.style.setProperty(\"--elements-window-width\", `${width}px`)\n document.cookie = `alchemy-elements-window-width=${width}; SameSite=Lax; Path=/;`\n }\n }\n\n // Focus element editor and element in preview if URL contains hash to element editor.\n // The link is coming from the assignment view when showing assigned files or pictures.\n focusElementEditor(dom_id) {\n const el = document.querySelector(dom_id)\n\n if (el instanceof ElementEditor) {\n el.focusElement() && el.focusElementPreview()\n }\n }\n\n get collapseButton() {\n return this.querySelector(\"#collapse-all-elements-button\")\n }\n\n get toggleButton() {\n return document.querySelector(\"#element_window_button\")\n }\n\n get previewWindow() {\n return document.getElementById(\"alchemy_preview_window\")\n }\n\n get turboFrame() {\n if (!this.#turboFrame) {\n this.#turboFrame = this.closest(\"turbo-frame\")\n }\n return this.#turboFrame\n }\n\n get widthFromCookie() {\n return document.cookie\n .split(\"; \")\n .find((row) => row.startsWith(\"alchemy-elements-window-width=\"))\n ?.split(\"=\")[1]\n }\n\n set isDragged(dragged) {\n this.turboFrame.style.transitionProperty = dragged ? \"none\" : null\n this.turboFrame.style.pointerEvents = dragged ? \"none\" : null\n }\n\n #attachEvents() {\n this.collapseButton?.addEventListener(\"click\", () => {\n this.collapseAllElements()\n })\n window.addEventListener(\"message\", (event) => {\n const data = event.data\n if (data?.message == \"Alchemy.focusElementEditor\") {\n const element = document.getElementById(`element_${data.element_id}`)\n this.show()\n element?.focusElement()\n }\n })\n document.body.addEventListener(\"click\", (evt) => {\n if (!evt.target.closest(\"alchemy-element-editor\")) {\n this.querySelectorAll(\"alchemy-element-editor\").forEach((editor) => {\n editor.classList.remove(\"selected\")\n })\n this.previewWindow?.postMessage({ message: \"Alchemy.blurElements\" })\n }\n })\n }\n}\n\ncustomElements.define(\"alchemy-elements-window\", ElementsWindow)\n","class ElementsWindowHandle extends HTMLElement {\n #dragging = false\n #elementsWindow = null\n #previewWindow = null\n\n constructor() {\n super()\n\n this.addEventListener(\"mousedown\", this)\n window.addEventListener(\"mousemove\", this)\n window.addEventListener(\"mouseup\", this)\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"mousedown\":\n event.stopPropagation()\n this.onMouseDown()\n break\n case \"mouseup\":\n this.onMouseUp()\n break\n case \"mousemove\":\n if (this.#dragging) {\n this.onDrag(event.pageX)\n }\n break\n }\n }\n\n onMouseDown() {\n this.#dragging = true\n this.elementsWindow.isDragged = true\n this.previewWindow.isDragged = true\n this.classList.add(\"is-dragged\")\n }\n\n onMouseUp() {\n this.#dragging = false\n this.elementsWindow.isDragged = false\n this.previewWindow.isDragged = false\n this.classList.remove(\"is-dragged\")\n }\n\n onDrag(pageX) {\n const elementWindowWidth = window.innerWidth - pageX\n this.elementsWindow.resize(elementWindowWidth)\n }\n\n get elementsWindow() {\n if (!this.#elementsWindow) {\n this.#elementsWindow = document.querySelector(\"alchemy-elements-window\")\n }\n return this.#elementsWindow\n }\n\n get previewWindow() {\n if (!this.#previewWindow) {\n this.#previewWindow = document.getElementById(\"alchemy_preview_window\")\n }\n return this.#previewWindow\n }\n}\n\ncustomElements.define(\"alchemy-elements-window-handle\", ElementsWindowHandle)\n","class FileEditor extends HTMLElement {\n constructor() {\n super()\n this.deleteLink = this.querySelector(\".remove_file_link\")\n this.fileIcon = this.querySelector(\".file_icon\")\n this.fileName = this.querySelector(\".file_name\")\n this.formFieldId = this.deleteLink?.dataset.formFieldId\n this.formField = this.querySelector(`#${this.formFieldId}`)\n this.deleteLink?.addEventListener(\"click\", this)\n }\n\n handleEvent(event) {\n if (event.type === \"click\") this.removeFile()\n event.stopPropagation()\n }\n\n removeFile() {\n this.formField.value = \"\"\n this.fileIcon.innerHTML = \"\"\n this.fileName.innerHTML = \"\"\n this.deleteLink?.classList.add(\"hidden\")\n this.closest(\"alchemy-element-editor\").setDirty(this.formField)\n }\n}\n\ncustomElements.define(\"alchemy-file-editor\", FileEditor)\n","const DEFAULT_DEBOUNCE_TIME = 150\n\nclass ListFilter extends HTMLElement {\n #debounceTimer\n\n constructor() {\n super()\n this.#attachEvents()\n }\n\n #attachEvents() {\n if (this.hotkey) {\n key(this.hotkey, () => {\n this.filterField.focus()\n return false\n })\n }\n this.filterField.addEventListener(\"keyup\", () => {\n clearTimeout(this.#debounceTimer)\n this.#debounceTimer = setTimeout(() => {\n const term = this.filterField.value\n this.clearButton.style.visibility = term ? \"visible\" : \"hidden\"\n this.filter(term)\n }, this.debounceTime)\n })\n this.clearButton.addEventListener(\"click\", (e) => {\n e.preventDefault()\n this.clear()\n })\n this.filterField.addEventListener(\"focus\", () =>\n key.setScope(\"list_filter\")\n )\n key(\"esc\", \"list_filter\", () => {\n this.clear()\n this.filterField.blur()\n })\n }\n\n disconnectedCallback() {\n if (this.hotkey) {\n key.unbind(this.hotkey)\n }\n key.unbind(\"esc\", \"list_filter\")\n }\n\n filter(term) {\n if (term === \"\") {\n this.clearButton.style.visibility = \"hidden\"\n }\n\n const matchedItems = []\n const itemsToShow = new Set()\n const lowerTerm = term.toLowerCase()\n\n // First pass: find matching items and mark their ancestors as visible too\n this.items.forEach((item) => {\n const name = item.getAttribute(this.nameAttribute)?.toLowerCase()\n // indexOf is much faster then match()\n if (name.indexOf(lowerTerm) !== -1) {\n matchedItems.push(item)\n itemsToShow.add(item)\n // Mark ancestor items as visible so nested matches stay visible\n let ancestor = item.parentElement?.closest(this.itemsSelector)\n while (ancestor) {\n itemsToShow.add(ancestor)\n ancestor = ancestor.parentElement?.closest(this.itemsSelector)\n }\n }\n })\n\n // Second pass: apply visibility\n this.items.forEach((item) => {\n item.classList.toggle(\"hidden\", !itemsToShow.has(item))\n })\n\n // Scroll into view if only one match\n if (matchedItems.length === 1) {\n matchedItems[0].scrollIntoView({ behavior: \"smooth\", block: \"nearest\" })\n }\n }\n\n clear() {\n this.filterField.value = \"\"\n this.clearButton.style.visibility = \"hidden\"\n this.items.forEach((item) => item.classList.remove(\"hidden\"))\n }\n\n get nameAttribute() {\n return this.getAttribute(\"name-attribute\") || \"name\"\n }\n\n get clearButton() {\n return this.querySelector('button[type=\"button\"]')\n }\n\n get filterField() {\n return this.querySelector('input[type=\"text\"]')\n }\n\n get items() {\n return document.querySelectorAll(this.itemsSelector)\n }\n\n get itemsSelector() {\n return this.getAttribute(\"items-selector\")\n }\n\n get debounceTime() {\n return parseInt(this.getAttribute(\"debounce-time\")) || DEFAULT_DEBOUNCE_TIME\n }\n\n get hotkey() {\n return this.getAttribute(\"hotkey\")\n }\n}\n\ncustomElements.define(\"alchemy-list-filter\", ListFilter)\n","const DISMISS_DELAY = 5000\n\nclass Message extends HTMLElement {\n #message\n\n constructor() {\n super()\n this.#message = this.innerHTML\n if (this.dismissable || this.type === \"error\") {\n this.addEventListener(\"click\", this)\n }\n }\n\n handleEvent(event) {\n if (event.type === \"click\") {\n this.dismiss()\n }\n }\n\n connectedCallback() {\n this.innerHTML = `\n <alchemy-icon name=\"${this.iconName}\"></alchemy-icon>\n ${this.dismissable && this.type === \"error\" ? '<alchemy-icon name=\"close\"></alchemy-icon>' : \"\"}\n ${this.#message}\n `\n if (this.dismissable && this.type !== \"error\") {\n setTimeout(() => {\n this.dismiss()\n }, this.dismissDelay)\n }\n }\n\n dismiss() {\n this.addEventListener(\"transitionend\", () => this.remove())\n this.classList.add(\"dismissed\")\n }\n\n get dismissable() {\n return this.hasAttribute(\"dismissable\")\n }\n\n get icon() {\n return this.getAttribute(\"icon\")\n }\n\n get type() {\n return this.getAttribute(\"type\") || \"notice\"\n }\n\n get dismissDelay() {\n return parseInt(\n this.noticesWrapper?.dataset.autoDismissDelay || DISMISS_DELAY\n )\n }\n\n get iconName() {\n switch (this.icon || this.type) {\n case \"warning\":\n case \"warn\":\n case \"alert\":\n return \"alert\"\n case \"notice\":\n return \"check\"\n case \"info\":\n case \"hint\":\n return \"information\"\n case \"error\":\n return \"bug\"\n default:\n return this.type\n }\n }\n\n get noticesWrapper() {\n return this.closest(\"#flash_notices\")\n }\n}\n\ncustomElements.define(\"alchemy-message\", Message)\n","import { growl } from \"alchemy_admin/growler\"\n\nclass Growl extends HTMLElement {\n connectedCallback() {\n growl(this.message, this.getAttribute(\"type\") || \"notice\")\n this.remove()\n }\n\n get message() {\n return this.getAttribute(\"message\") || this.innerHTML\n }\n}\n\ncustomElements.define(\"alchemy-growl\", Growl)\n","class Icon extends HTMLElement {\n static get observedAttributes() {\n return [\"name\", \"size\", \"icon-style\"]\n }\n\n constructor() {\n super()\n this.spriteUrl = document\n .querySelector('link[rel=\"preload\"][as=\"image\"]')\n .getAttribute(\"href\")\n }\n\n connectedCallback() {\n this.render()\n }\n\n attributeChangedCallback() {\n this.render()\n }\n\n render() {\n const sizeClass = this.size ? ` icon--${this.size}` : \"\"\n this.innerHTML = `<svg class=\"icon${sizeClass}\"><use href=\"${this.spriteUrl}#ri-${this.iconName}${this.style}\" /></svg>`\n }\n\n set name(value) {\n this.setAttribute(\"name\", value)\n }\n\n get iconName() {\n return this.getAttribute(\"name\")\n }\n\n get size() {\n return this.getAttribute(\"size\")\n }\n\n get style() {\n const value = this.getAttribute(\"icon-style\")\n switch (value) {\n case \"none\":\n return \"\"\n case null:\n return \"-line\"\n default:\n return `-${value}`\n }\n }\n}\n\ncustomElements.define(\"alchemy-icon\", Icon)\n","export class IngredientGroup extends HTMLDetailsElement {\n #localStorageKey = \"Alchemy.expanded_ingredient_groups\"\n\n constructor() {\n super()\n\n this.addEventListener(\"toggle\", this)\n\n if (this.isInLocalStorage) {\n this.open = true\n }\n }\n\n /**\n * Toggle visibility of the ingredient fields in this group\n */\n handleEvent() {\n let expanded_ingredient_groups = this.localStorageItem\n\n if (this.open) {\n this.toggleIcon.name = \"arrow-down-s\"\n if (!this.isInLocalStorage) expanded_ingredient_groups.push(this.id)\n } else {\n this.toggleIcon.name = \"arrow-left-s\"\n expanded_ingredient_groups = expanded_ingredient_groups.filter(\n (value) => value !== this.id\n )\n }\n\n localStorage.setItem(\n this.#localStorageKey,\n JSON.stringify(expanded_ingredient_groups)\n )\n }\n\n get isInLocalStorage() {\n return this.localStorageItem.includes(this.id)\n }\n\n get localStorageItem() {\n const item = localStorage.getItem(this.#localStorageKey)\n\n if (!item) return []\n\n try {\n return JSON.parse(item)\n } catch (error) {\n console.error(error)\n return []\n }\n }\n\n get toggleIcon() {\n return this.querySelector(\"alchemy-icon\")\n }\n}\n\ncustomElements.define(\"alchemy-ingredient-group\", IngredientGroup, {\n extends: \"details\"\n})\n","class LinkButton extends HTMLButtonElement {\n constructor() {\n super()\n this.addEventListener(\"click\", this)\n this.classList.add(\"icon_button\")\n // Prevent accidental form submits if this component is wrapped inside a form\n this.setAttribute(\"type\", \"button\")\n this.innerHTML = '<alchemy-icon name=\"link\" icon-style=\"m\"></alchemy-icon>'\n }\n\n handleEvent(event) {\n const dialog = new Alchemy.LinkDialog({\n url: this.linkUrl,\n title: this.linkTitle,\n target: this.linkTarget,\n type: this.linkClass\n })\n dialog.open().then((link) => this.setLink(link))\n event.preventDefault()\n }\n\n setLink(link) {\n if (link.url === \"\") {\n this.classList.remove(\"linked\")\n this.dispatchEvent(new CustomEvent(\"alchemy:unlink\", { bubbles: true }))\n } else {\n this.classList.add(\"linked\")\n this.dispatchEvent(\n new CustomEvent(\"alchemy:link\", {\n bubbles: true,\n detail: link\n })\n )\n }\n }\n\n get linkUrl() {\n return this.linkButtons.linkUrlField.value\n }\n\n get linkTitle() {\n return this.linkButtons.linkTitleField.value\n }\n\n get linkTarget() {\n return this.linkButtons.linkTargetField.value\n }\n\n get linkClass() {\n return this.linkButtons.linkClassField.value\n }\n\n get linkButtons() {\n return this.closest(\"alchemy-link-buttons\")\n }\n}\n\ncustomElements.define(\"alchemy-link-button\", LinkButton, { extends: \"button\" })\n","class UnlinkButton extends HTMLButtonElement {\n constructor() {\n super()\n this.addEventListener(\"click\", this)\n this.classList.add(\"icon_button\")\n // Prevent accidental form submits if this component is wrapped inside a form\n this.setAttribute(\"type\", \"button\")\n this.linked = this.linked\n this.innerHTML =\n '<alchemy-icon name=\"link-unlink\" icon-style=\"m\"></alchemy-icon>'\n }\n\n handleEvent(event) {\n if (this.linked) {\n this.linked = false\n this.blur()\n this.dispatchEvent(new CustomEvent(\"alchemy:unlink\", { bubbles: true }))\n }\n event.preventDefault()\n }\n\n set linked(isLinked) {\n if (isLinked) {\n this.classList.replace(\"disabled\", \"linked\")\n this.removeAttribute(\"tabindex\")\n } else {\n this.classList.replace(\"linked\", \"disabled\")\n this.setAttribute(\"tabindex\", \"-1\")\n }\n }\n\n get linked() {\n return this.classList.contains(\"linked\")\n }\n}\n\ncustomElements.define(\"alchemy-unlink-button\", UnlinkButton, {\n extends: \"button\"\n})\n","import \"alchemy_admin/components/link_buttons/link_button\"\nimport \"alchemy_admin/components/link_buttons/unlink_button\"\n\nclass LinkButtons extends HTMLElement {\n constructor() {\n super()\n this.addEventListener(\"alchemy:link\", this)\n this.addEventListener(\"alchemy:unlink\", this)\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"alchemy:link\":\n this.setLink(event.detail)\n break\n case \"alchemy:unlink\":\n this.removeLink()\n }\n event.stopPropagation()\n }\n\n setLink(data) {\n this.linkUrlField.value = data.url\n this.linkUrlField.dispatchEvent(new Event(\"change\"))\n this.linkTitleField.value = data.title\n this.linkClassField.value = data.type\n this.linkTargetField.value = data.target\n\n this.unlinkButton.linked = true\n this.setElementDirty()\n }\n\n removeLink() {\n this.linkUrlField.value = \"\"\n this.linkUrlField.dispatchEvent(new Event(\"change\"))\n this.linkTitleField.value = \"\"\n this.linkClassField.value = \"\"\n this.linkTargetField.value = \"\"\n\n this.linkButton.classList.remove(\"linked\")\n this.unlinkButton.linked = false\n\n this.setElementDirty()\n }\n\n setElementDirty() {\n this.elementEditor.setDirty(this)\n }\n\n get linkButton() {\n return this.querySelector('[is=\"alchemy-link-button\"]')\n }\n\n get unlinkButton() {\n return this.querySelector('[is=\"alchemy-unlink-button\"]')\n }\n\n get ingredientEditor() {\n const ingredientId = this.dataset.ingredientId\n return this.parentElement.closest(`[data-ingredient-id='${ingredientId}']`)\n }\n\n get elementEditor() {\n return this.closest(\"alchemy-element-editor\")\n }\n\n get linkUrlField() {\n return this.ingredientEditor.querySelector(\"[data-link-value]\")\n }\n\n get linkTitleField() {\n return this.ingredientEditor.querySelector(\"[data-link-title]\")\n }\n\n get linkTargetField() {\n return this.ingredientEditor.querySelector(\"[data-link-target]\")\n }\n\n get linkClassField() {\n return this.ingredientEditor.querySelector(\"[data-link-class]\")\n }\n}\n\ncustomElements.define(\"alchemy-link-buttons\", LinkButtons)\n","export function formatFileSize(bytes) {\n let exponent = bytes === 0 ? 0 : Math.floor(Math.log(bytes) / Math.log(1024))\n\n // prevent format higher than GB\n if (exponent > 3) {\n exponent = 3\n }\n\n let value = (bytes / Math.pow(1024, exponent)).toFixed(2)\n return value + \" \" + [\"B\", \"kB\", \"MB\", \"GB\"][exponent]\n}\n","import { RemoteSelect } from \"alchemy_admin/components/remote_select\"\n\nclass NodeSelect extends RemoteSelect {\n _searchQuery(term, page) {\n return {\n filter: {\n name_or_page_name_cont: term,\n ...JSON.parse(this.queryParams)\n },\n page: page\n }\n }\n\n _renderResult(item) {\n return this._renderListEntry(item)\n }\n\n /**\n * html template for each list entry\n * @param {object} node\n * @param {string} term\n * @returns {string}\n * @private\n */\n _renderListEntry(node, term) {\n const ancestors = node.ancestors.map((a) => a.name)\n const seperator = `<alchemy-icon name=\"arrow-right-s\"></alchemy-icon>`\n\n return `\n <div class=\"node-select--node\">\n <alchemy-icon name=\"menu-2\"></alchemy-icon>\n <div class=\"node-select--node-display_name\">\n <span class=\"node-select--node-ancestors\">\n ${ancestors.length > 0 ? ancestors.join(seperator) + seperator : \"\"}\n </span>\n <span class=\"node-select--node-name\">\n ${this._hightlightTerm(node.name, term)}\n </span>\n </div>\n <div class=\"node-select--node-url\">\n ${node.url || \"\"}\n </div>\n </div>\n `\n }\n}\n\ncustomElements.define(\"alchemy-node-select\", NodeSelect)\n","import { AlchemyHTMLElement } from \"alchemy_admin/components/alchemy_html_element\"\nimport { formatFileSize } from \"alchemy_admin/utils/format\"\nimport { translate } from \"alchemy_admin/i18n\"\nimport { growl } from \"alchemy_admin/growler\"\n\nexport class FileUpload extends AlchemyHTMLElement {\n constructor() {\n super()\n\n this.file = null\n this.request = null\n\n this.progressEventLoaded = 0\n this.progressEventTotal = 0\n this.className = \"in-progress\"\n this.valid = true\n this.value = 0\n }\n\n /**\n * Initialize the component with file and request\n * @param {File} file\n * @param {XMLHttpRequest} request\n */\n initialize(file, request) {\n this.file = file\n this.request = request\n this.progressEventTotal = file ? file.size : 0\n\n this._validateFile()\n this._addRequestEventListener()\n }\n\n render() {\n return `\n <sl-progress-bar value=\"${this.value}\"></sl-progress-bar>\n <div class=\"description\">\n <span class=\"file-name\">${this.file?.name}</span>\n <span class=\"loaded-size\">${this.loadedSize}</span>\n <span class=\"error-message\">${this.errorMessage}</span>\n </div>\n <sl-tooltip content=\"${translate(\"Abort upload\")}\">\n <button class=\"icon_button\" aria-label=\"${translate(\"Abort upload\")}\">\n <alchemy-icon name=\"close\"></alchemy-icon>\n </button>\n </sl-tooltip>\n `\n }\n\n afterRender() {\n this.querySelector(\"button\").addEventListener(\"click\", () => this.cancel())\n\n if (this.file?.type.includes(\"image\")) {\n const reader = new FileReader()\n reader.readAsDataURL(this.file)\n reader.addEventListener(\"load\", () => {\n const image = new Image()\n image.src = reader.result\n this.prepend(image)\n })\n }\n }\n\n /**\n * cancel the upload\n */\n cancel() {\n if (!this.finished) {\n this.status = \"canceled\"\n this.request?.abort()\n this.dispatchCustomEvent(\"FileUpload.Change\")\n }\n }\n\n /**\n * validate given file with the `Alchemy.uploader_defaults` - configuration\n * @private\n */\n _validateFile() {\n const config = Alchemy.uploader_defaults\n const maxFileSize = config.file_size_limit * Math.pow(1024, 2) // in Byte\n let errorMessage = undefined\n\n if (this.file?.size > maxFileSize) {\n errorMessage = translate(\"Uploaded bytes exceed file size\")\n }\n\n const allowedFiletypes = this.file?.type.includes(\"image\")\n ? config.allowed_filetypes.alchemy_pictures\n : config.allowed_filetypes.alchemy_attachments\n\n const isFileFormatSupported =\n allowedFiletypes.includes(\"*\") ||\n allowedFiletypes.includes(\n this.file?.type.replace(/^\\w+\\/(\\w+)(\\+\\w+)?/i, \"$1\")\n )\n\n if (!isFileFormatSupported) {\n errorMessage = translate(\"File type not allowed\")\n }\n\n if (errorMessage) {\n this.valid = false\n this.errorMessage = errorMessage\n }\n }\n\n /**\n * register event listeners to react on request changes\n * @private\n */\n _addRequestEventListener() {\n // prevent errors if the component will be called without a request - object\n if (!this.request) {\n return\n }\n\n // update the progress bar and currently loaded size information\n this.request.upload.onprogress = (progressEvent) => {\n this.progressEvent = progressEvent\n }\n\n // triggers, when the upload is done\n this.request.onload = () => {\n if (this.request.status < 400) {\n this.status = \"successful\"\n growl(this.responseMessage)\n } else {\n this.status = \"failed\"\n this.errorMessage = this.responseMessage\n }\n this.dispatchCustomEvent(\"FileUpload.Change\")\n }\n\n // catch request errors\n this.request.onerror = () => {\n this.errorMessage = translate(\"An error occurred during the transaction\")\n }\n }\n\n /**\n * @returns {boolean}\n */\n get active() {\n return this.valid && this.status !== \"canceled\"\n }\n\n /**\n * @returns {string}\n */\n get errorMessage() {\n return this._errorMessage || \"\"\n }\n\n /**\n * @param {string} message\n */\n set errorMessage(message) {\n this._errorMessage = message\n const errorMessageContainer = this.querySelector(\".error-message\")\n if (errorMessageContainer) {\n errorMessageContainer.textContent = message\n }\n growl(message, \"error\")\n }\n\n /**\n * @returns {boolean}\n */\n get finished() {\n return [\"canceled\", \"successful\", \"failed\"].includes(this.status)\n }\n\n /**\n * format the loaded and total size and present that as a string\n * @returns {string}\n */\n get loadedSize() {\n return `${formatFileSize(this.progressEventLoaded)} / ${formatFileSize(\n this.progressEventTotal\n )}`\n }\n\n /**\n * @returns {HTMLProgressElement|undefined}\n */\n get progressElement() {\n return this.querySelector(\"sl-progress-bar\")\n }\n\n /**\n * @param {ProgressEvent} progressEvent\n */\n set progressEvent(progressEvent) {\n this.progressEventLoaded = progressEvent.loaded\n this.progressEventTotal = progressEvent.total\n\n this.value = Math.round((progressEvent.loaded / progressEvent.total) * 100)\n this.querySelector(\".loaded-size\").textContent = this.loadedSize\n }\n\n /**\n * @returns {string}\n */\n get responseMessage() {\n try {\n const response = JSON.parse(this.request.responseText)\n return response[\"message\"]\n } catch (error) {\n return `${this.request.status}: ${this.request.statusText}`\n }\n }\n\n /**\n * @returns {string}\n */\n get status() {\n return this._status\n }\n\n /**\n * @param {string} status\n */\n set status(status) {\n this._status = status\n this.className = status\n\n this.progressElement?.toggleAttribute(\n \"indeterminate\",\n status === \"upload-finished\"\n )\n }\n\n /**\n * @returns {boolean}\n */\n get valid() {\n return this._valid\n }\n\n /**\n * @param {boolean} isValid\n */\n set valid(isValid) {\n this._valid = isValid\n this.classList.toggle(\"invalid\", !isValid)\n }\n\n /**\n * get the progress value of the current file\n * @returns {number}\n */\n get value() {\n return this._value\n }\n\n /**\n * @param {number} value\n */\n set value(value) {\n this._value = value\n if (this.progressElement) {\n this.progressElement.value = value\n }\n\n if (value === 100) {\n this.status = \"upload-finished\"\n }\n\n this.dispatchCustomEvent(\"FileUpload.Change\")\n }\n}\n\ncustomElements.define(\"alchemy-file-upload\", FileUpload)\n","import { AlchemyHTMLElement } from \"alchemy_admin/components/alchemy_html_element\"\nimport { FileUpload } from \"alchemy_admin/components/uploader/file_upload\"\nimport { formatFileSize } from \"alchemy_admin/utils/format\"\nimport { translate } from \"alchemy_admin/i18n\"\n\nexport class Progress extends AlchemyHTMLElement {\n #visible = false\n\n constructor() {\n super()\n this.buttonLabel = translate(\"Cancel all uploads\")\n this.fileUploads = []\n this.fileCount = 0\n this.className = \"in-progress\"\n this.visible = true\n this.handleFileChange = () => this._updateView()\n }\n\n /**\n * Initialize the component with file uploads\n * @param {FileUpload[]} fileUploads\n */\n initialize(fileUploads = []) {\n this.fileUploads = fileUploads\n this.fileCount = fileUploads.length\n }\n\n /**\n * append file progress - components for each file\n */\n afterRender() {\n this.actionButton = this.querySelector(\"button\")\n this.actionButton.addEventListener(\"click\", () => {\n if (this.finished) {\n this.onComplete(this.status)\n } else {\n this.cancel()\n }\n })\n\n this.fileUploads.forEach((fileUpload) => {\n this.querySelector(\".single-uploads\").append(fileUpload)\n })\n }\n\n /**\n * cancel requests in all remaining uploads\n */\n cancel() {\n this._activeUploads().forEach((upload) => {\n upload.cancel()\n })\n this._setupCloseButton()\n }\n\n /**\n * update view and register change event\n */\n connected() {\n this._updateView()\n this.addEventListener(\"Alchemy.FileUpload.Change\", this.handleFileChange)\n }\n\n /**\n * deregister file upload change - event\n */\n disconnected() {\n this.removeEventListener(\"Alchemy.FileUpload.Change\", this.handleFileChange)\n }\n\n /**\n * a complete hook to allow the uploader to react and trigger an event\n * it would be possible to trigger the event here, but the dispatching would happen\n * in the scope of that component and can't be cached o uploader - component level\n */\n onComplete(_status) {}\n\n render() {\n return `\n <sl-progress-bar value=\"0\"></sl-progress-bar>\n <div class=\"overall-progress-value\">\n <span class=\"value-text\"></span>\n\n <sl-tooltip content=\"${this.buttonLabel}\">\n <button class=\"icon_button\" aria-label=\"${this.buttonLabel}\">\n <alchemy-icon name=\"close\"></alchemy-icon>\n </button>\n </sl-tooltip>\n </div>\n <div class=\"single-uploads\" style=\"--progress-columns: ${\n this.fileCount > 3 ? 3 : this.fileCount\n }\"></div>\n <div class=\"overall-upload-value value-text\"></div>\n `\n }\n\n /**\n * get all active upload components\n * @returns {FileUpload[]}\n * @private\n */\n _activeUploads() {\n return this.fileUploads.filter((upload) => upload.active)\n }\n\n /**\n * replace cancel button to be the close button\n * @private\n */\n _setupCloseButton() {\n this.buttonLabel = translate(\"Close\")\n this.actionButton.ariaLabel = this.buttonLabel\n this.actionButton.parentElement.content = this.buttonLabel // update tooltip content\n }\n\n /**\n * @param {string} field\n * @returns {number}\n * @private\n */\n _sumFileProgresses(field) {\n return this._activeUploads().reduce(\n (accumulator, upload) => upload[field] + accumulator,\n 0\n )\n }\n\n /**\n * don't render the whole element new, because it would prevent selecting buttons\n * @private\n */\n _updateView() {\n const status = this.status\n this.className = status\n\n // update progress bar\n this.progressElement.value = this.totalProgress\n this.progressElement.toggleAttribute(\n \"indeterminate\",\n status === \"upload-finished\"\n )\n\n // show progress in file size and percentage\n this.querySelector(`.overall-progress-value > span`).textContent =\n this.overallProgressValue\n this.querySelector(`.overall-upload-value`).textContent =\n this.overallUploadSize\n\n if (this.finished) {\n this._setupCloseButton()\n this.onComplete(status)\n } else {\n this.visible = true\n }\n }\n\n /**\n * @returns {boolean}\n */\n get finished() {\n return this._activeUploads().every((entry) => entry.finished)\n }\n\n /**\n * @returns {string}\n */\n get overallUploadSize() {\n const uploadedFileCount = this._activeUploads().filter(\n (fileProgress) => fileProgress.value >= 100\n ).length\n const overallProgressValue = `${\n this.totalProgress\n }% (${uploadedFileCount} / ${this._activeUploads().length})`\n\n return `${formatFileSize(\n this._sumFileProgresses(\"progressEventLoaded\")\n )} / ${formatFileSize(this._sumFileProgresses(\"progressEventTotal\"))}`\n }\n\n /**\n * @returns {string}\n */\n get overallProgressValue() {\n const uploadedFileCount = this._activeUploads().filter(\n (fileProgress) => fileProgress.value >= 100\n ).length\n return `${this.totalProgress}% (${uploadedFileCount} / ${\n this._activeUploads().length\n })`\n }\n\n /**\n * @returns {HTMLProgressElement|undefined}\n */\n get progressElement() {\n return this.querySelector(\"sl-progress-bar\")\n }\n\n /**\n * get status of file progresses and accumulate the overall status\n * @returns {string}\n */\n get status() {\n const uploadsStatuses = this._activeUploads().map(\n (upload) => upload.className\n )\n\n // mark as failed, if any upload failed\n if (uploadsStatuses.includes(\"failed\")) {\n return \"failed\"\n }\n\n // no active upload means that every upload was canceled\n if (uploadsStatuses.length === 0) {\n return \"canceled\"\n }\n\n // all uploads are successful or upload-finished or in-progress\n if (uploadsStatuses.every((entry) => entry === uploadsStatuses[0])) {\n return uploadsStatuses[0]\n }\n\n return \"in-progress\"\n }\n\n /**\n * @returns {number}\n */\n get totalProgress() {\n const totalSize = this._activeUploads().reduce(\n (accumulator, upload) => accumulator + upload.file.size,\n 0\n )\n let totalProgress = Math.ceil(\n this._activeUploads().reduce((accumulator, upload) => {\n const weight = upload.file.size / totalSize\n return upload.value * weight + accumulator\n }, 0)\n )\n // prevent rounding errors\n if (totalProgress > 100) {\n totalProgress = 100\n }\n return totalProgress\n }\n\n /**\n * @returns {boolean}\n */\n get visible() {\n return this.#visible\n }\n\n /**\n * @param {boolean} visible\n */\n set visible(visible) {\n this.classList.toggle(\"visible\", visible)\n this.#visible = visible\n }\n}\n\ncustomElements.define(\"alchemy-upload-progress\", Progress)\n","/**\n * @typedef {object} PersistedFile\n * @property {string} name\n * @property {number} size\n */\nimport { AlchemyHTMLElement } from \"alchemy_admin/components/alchemy_html_element\"\nimport { Progress } from \"alchemy_admin/components/uploader/progress\"\nimport { FileUpload } from \"alchemy_admin/components/uploader/file_upload\"\nimport { translate } from \"alchemy_admin/i18n\"\nimport { getToken } from \"alchemy_admin/utils/ajax\"\n\nexport class Uploader extends AlchemyHTMLElement {\n static properties = {\n dropzone: { default: false }\n }\n\n connected() {\n this.fileInput.addEventListener(\"change\", (event) => {\n this._uploadFiles(Array.from(event.target.files))\n })\n if (this.dropzone) {\n this._dragAndDropBehavior()\n }\n this.addEventListener(\"Alchemy.upload.successful\", this)\n }\n\n handleEvent(evt) {\n switch (evt.type) {\n case \"Alchemy.upload.successful\":\n this._handleUploadComplete()\n break\n }\n }\n\n _handleUploadComplete() {\n setTimeout(() => {\n const url = this.redirectUrl\n const turboFrame = this.closest(\"turbo-frame\")\n this.uploadProgress.visible = false\n\n if (!url) return\n\n if (turboFrame) {\n turboFrame.setAttribute(\"src\", url)\n turboFrame.reload()\n } else {\n Turbo.visit(url)\n }\n }, 750)\n }\n\n /**\n * add dragover class to indicate, if the file is draggable\n * @private\n */\n _dragAndDropBehavior() {\n const dropzoneElement = document.querySelector(this.dropzone)\n let isDraggedOver = false\n\n const toggleDropzoneClass = (enabled) => {\n if (isDraggedOver !== enabled) {\n isDraggedOver = enabled\n dropzoneElement.classList.toggle(\"dragover\")\n }\n }\n\n dropzoneElement.addEventListener(\"dragleave\", () =>\n toggleDropzoneClass(false)\n )\n dropzoneElement.addEventListener(\"drop\", async (event) => {\n event.preventDefault()\n toggleDropzoneClass(false)\n\n const files = [...event.dataTransfer.items].map((item) =>\n item.getAsFile()\n )\n\n this._uploadFiles(files)\n })\n\n dropzoneElement.addEventListener(\"dragover\", (event) => {\n event.preventDefault() // dragover has to be disabled to use the custom drop event\n toggleDropzoneClass(true)\n })\n }\n\n /**\n * @param {File[]} files\n * @private\n */\n _uploadFiles(files) {\n // prepare file progress bars and server request\n let fileUploadCount = 0\n\n const fileUploads = files.map((file) => {\n const request = new XMLHttpRequest()\n const fileUpload = new FileUpload()\n fileUpload.initialize(file, request)\n\n if (Alchemy.uploader_defaults.upload_limit - 1 < fileUploadCount) {\n fileUpload.valid = false\n fileUpload.errorMessage = translate(\"Maximum number of files exceeded\")\n } else if (fileUpload.valid) {\n fileUploadCount++\n this._submitFile(request, file)\n }\n\n return fileUpload\n })\n\n this._createProgress(fileUploads)\n }\n\n /**\n * @param {XMLHttpRequest} request\n * @param {File} file\n * @private\n */\n _submitFile(request, file) {\n const form = this.querySelector(\"form\")\n const formData = new FormData(form)\n formData.set(this.fileInput.name, file)\n request.open(\"POST\", form.action)\n request.setRequestHeader(\"X-CSRF-Token\", getToken())\n request.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\")\n request.setRequestHeader(\"Accept\", \"application/json\")\n request.send(formData)\n }\n\n /**\n * create (and maybe remove the old) progress bar - component\n * @param {FileUpload[]} fileUploads\n * @private\n */\n _createProgress(fileUploads) {\n if (this.uploadProgress) {\n this.uploadProgress.cancel()\n document.body.removeChild(this.uploadProgress)\n }\n this.uploadProgress = new Progress()\n this.uploadProgress.initialize(fileUploads)\n this.uploadProgress.onComplete = (status) => {\n this.dispatchCustomEvent(`upload.${status}`)\n }\n\n document.body.append(this.uploadProgress)\n }\n\n /**\n * @returns {HTMLInputElement}\n */\n get fileInput() {\n return this.querySelector(\"input[type='file']\")\n }\n\n get redirectUrl() {\n return this.getAttribute(\"redirect-url\")\n }\n}\n\ncustomElements.define(\"alchemy-uploader\", Uploader)\n","import { AlchemyHTMLElement } from \"alchemy_admin/components/alchemy_html_element\"\n\nclass Overlay extends AlchemyHTMLElement {\n render() {\n return `\n <alchemy-spinner></alchemy-spinner>\n <div id=\"overlay_text_box\">\n <span id=\"overlay_text\">${this.getAttribute(\"text\")}</span>\n </div>\n `\n }\n\n set show(value) {\n this.classList.toggle(\"visible\", value)\n }\n}\n\ncustomElements.define(\"alchemy-overlay\", Overlay)\n","import { patch } from \"alchemy_admin/utils/ajax\"\nimport { growl } from \"alchemy_admin/growler\"\nimport Spinner from \"alchemy_admin/spinner\"\n\nconst BUTTON = \"BUTTON\"\nconst SPAN = \"SPAN\"\n\n/**\n * Custom element for page nodes in the sitemap tree\n * Handles folding/unfolding of page children\n */\nexport class AlchemyPageNode extends HTMLElement {\n connectedCallback() {\n this.pageId = this.getAttribute(\"page-id\")\n this.folded = this.hasAttribute(\"folded\")\n\n this.folderButton?.addEventListener(\"click\", this)\n }\n\n disconnectedCallback() {\n this.folderButton?.removeEventListener(\"click\", this)\n }\n\n async handleEvent(event) {\n if (event.type === \"click\") {\n await this.handleFolderClick(event)\n }\n }\n\n async handleFolderClick(event) {\n event.preventDefault()\n event.stopPropagation()\n\n const folderButton = event.currentTarget\n folderButton.innerHTML = \"\"\n const spinner = new Spinner(\"small\")\n spinner.spin(folderButton)\n\n try {\n await patch(\n Alchemy.routes.fold_admin_page_path(this.pageId),\n null,\n \"text/vnd.turbo-stream.html\"\n )\n\n this.folded = !this.folded\n this.toggleAttribute(\"folded\", this.folded)\n this.toggleChildren()\n this.updateFolderIcon()\n } catch (error) {\n growl(error.message || error, \"error\")\n this.updateFolderIcon()\n } finally {\n spinner.stop()\n }\n }\n\n toggleChildren() {\n const childrenContainer = this.querySelector(\n `#page_${this.pageId}_children`\n )\n if (childrenContainer) {\n childrenContainer.classList.toggle(\"hidden\", this.folded)\n }\n }\n\n updateFolderIcon() {\n if (this.folderButton) {\n const iconName = this.folded ? \"arrow-right-s\" : \"arrow-down-s\"\n this.folderButton.innerHTML = `<alchemy-icon name=\"${iconName}\"></alchemy-icon>`\n }\n }\n\n /**\n * Updates the folder button state based on whether the node has children\n * Converts between button and span as needed\n */\n updateFolderButton() {\n const folderElement = this.querySelector(\".page_folder\")\n if (!folderElement) return\n\n const shouldShowButton = this.hasChildren || this.folded\n\n if (shouldShowButton && folderElement.tagName === SPAN) {\n // Convert span to button with icon\n const iconName = this.folded ? \"arrow-right-s\" : \"arrow-down-s\"\n folderElement.outerHTML = `<button class=\"page_folder icon_button\">\n <alchemy-icon name=\"${iconName}\"></alchemy-icon>\n </button>`\n\n // Re-attach event listener to the new button element\n this.folderButton?.addEventListener(\"click\", this)\n } else if (!shouldShowButton && folderElement.tagName === BUTTON) {\n // Convert button to empty span (no children and not folded)\n folderElement.outerHTML = '<span class=\"page_folder\"></span>'\n } else if (shouldShowButton && folderElement.tagName === BUTTON) {\n // Button exists, just update the icon direction\n this.updateFolderIcon()\n }\n }\n\n get hasChildren() {\n const childrenContainer = this.querySelector(\n `#page_${this.pageId}_children`\n )\n if (!childrenContainer) return false\n\n return (\n childrenContainer.querySelectorAll(\":scope > alchemy-page-node\").length >\n 0\n )\n }\n\n get folderButton() {\n return this.querySelector(\"button.page_folder\")\n }\n}\n\ncustomElements.define(\"alchemy-page-node\", AlchemyPageNode)\n","// Handles the page publication date fields\nexport class PagePublicationFields extends HTMLElement {\n connectedCallback() {\n const public_on_picker = this.querySelector(\n \"alchemy-datepicker:has(#page_public_on)\"\n )\n const public_until_picker = this.querySelector(\n \"alchemy-datepicker:has(#page_public_until)\"\n )\n const publication_date_fields = this.querySelector(\n \".page-publication-date-fields\"\n )\n const public_field = this.querySelector(\"#page_public\")\n\n if (!public_field) return\n\n public_field.addEventListener(\"click\", function (evt) {\n const checkbox = evt.target\n const now = new Date()\n\n if (checkbox.checked) {\n publication_date_fields.classList.remove(\"hidden\")\n public_on_picker.flatpickr.setDate(now)\n } else {\n publication_date_fields.classList.add(\"hidden\")\n public_on_picker.flatpickr.clear()\n }\n public_until_picker.flatpickr?.clear()\n })\n }\n}\n\ncustomElements.define(\"alchemy-page-publication-fields\", PagePublicationFields)\n","import { RemoteSelect } from \"alchemy_admin/components/remote_select\"\n\nclass PageSelect extends RemoteSelect {\n get pageId() {\n return this.selection ? JSON.parse(this.selection)[\"id\"] : undefined\n }\n\n _searchQuery(term, page) {\n return {\n q: {\n name_cont: term,\n ...JSON.parse(this.queryParams)\n },\n page: page\n }\n }\n\n _parseResponse(response) {\n const meta = response.meta\n return {\n results: response.pages,\n more: meta.page * meta.per_page < meta.total_count\n }\n }\n\n /**\n * result which is visible if a page was selected\n * @param {object} page\n * @returns {string}\n * @private\n */\n _renderResult(page) {\n return page.text || page.name\n }\n\n /**\n * html template for each list entry\n * @param {object} page\n * @param {string} term\n * @returns {string}\n * @private\n */\n _renderListEntry(page, term) {\n return `\n <div class=\"page-select--page\">\n <div class=\"page-select--top\">\n <alchemy-icon name=\"file-3\"></alchemy-icon>\n <span class=\"page-select--page-name\">${this._hightlightTerm(page.name, term)}</span>\n <span class=\"page-select--site-name\">${page.site.name}</span>\n </div>\n <div class=\"page-select--bottom\">\n <span class=\"page-select--page-urlname\">${page.url_path}</span>\n <span class=\"page-select--language-code\">${page.language_code}</span>\n </div>\n </div>\n `\n }\n}\n\ncustomElements.define(\"alchemy-page-select\", PageSelect)\n","class PictureDescriptionSelect extends HTMLElement {\n constructor() {\n super()\n this.addEventListener(\"change\", this)\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"change\":\n this.onChange()\n break\n }\n }\n\n onChange() {\n const url = new URL(this.getAttribute(\"url\"))\n const select = this.querySelector(\"select\")\n url.searchParams.set(\"language_id\", select.value)\n Turbo.visit(url, { frame: \"picture_descriptions\" })\n }\n}\n\ncustomElements.define(\n \"alchemy-picture-description-select\",\n PictureDescriptionSelect\n)\n","import debounce from \"alchemy_admin/utils/debounce\"\nimport max from \"alchemy_admin/utils/max\"\nimport { get } from \"alchemy_admin/utils/ajax\"\nimport { growl } from \"alchemy_admin/growler\"\n\nconst UPDATE_DELAY = 125\nconst IMAGE_PLACEHOLDER = '<alchemy-icon name=\"image\" size=\"xl\"></alchemy-icon>'\nconst THUMBNAIL_SIZE = \"160x120\"\n\nexport class PictureEditor extends HTMLElement {\n constructor() {\n super()\n\n this.cropFromField = this.querySelector(\"[data-crop-from]\")\n this.cropSizeField = this.querySelector(\"[data-crop-size]\")\n this.pictureIdField = this.querySelector(\"[data-picture-id]\")\n this.targetSizeField = this.querySelector(\"[data-target-size]\")\n this.imageCropperField = this.querySelector(\"[data-image-cropper]\")\n this.image = this.querySelector(\"img\")\n this.pictureThumbnail = this.querySelector(\"alchemy-picture-thumbnail\")\n this.deleteButton = this.querySelector(\".picture_tool.delete\")\n this.cropLink = this.querySelector(\".crop_link\")\n\n this.targetSize = this.targetSizeField.dataset.targetSize\n this.pictureId = this.pictureIdField.value\n\n // The mutation observer is observing multiple fields that all get updated\n // simultaneously. We only want to update the image once, so we debounce.\n this.update = debounce(() => {\n this.updateImage()\n this.updateCropLink()\n }, UPDATE_DELAY)\n\n this.deleteButton?.addEventListener(\"click\", this.removeImage.bind(this))\n }\n\n connectedCallback() {\n this.observer = new MutationObserver(this.mutationCallback.bind(this))\n\n this.observer.observe(this.cropFromField, { attributes: true })\n this.observer.observe(this.cropSizeField, { attributes: true })\n this.observer.observe(this.pictureIdField, { attributes: true })\n }\n\n disconnectedCallback() {\n this.observer.disconnect()\n }\n\n mutationCallback(mutationsList) {\n for (const mutation of mutationsList) {\n if (\"pictureId\" in mutation.target.dataset) {\n this.cropFromField.value = \"\"\n this.cropSizeField.value = \"\"\n this.pictureId = mutation.target.value\n }\n this.update()\n }\n }\n\n updateImage() {\n if (!this.pictureId) return\n\n this.pictureThumbnail.loading = true\n get(Alchemy.routes.url_admin_picture_path(this.pictureId), {\n crop: this.imageCropperEnabled,\n crop_from: this.cropFrom,\n crop_size: this.cropSize,\n flatten: true,\n size: THUMBNAIL_SIZE\n })\n .then(({ data }) => {\n this.pictureThumbnail.src = data.url\n this.pictureThumbnail.image.alt = data.alt\n this.pictureThumbnail.image.title = data.title\n this.setElementDirty()\n })\n .catch((error) => {\n console.error(error.message || error)\n growl(error.message || error, \"error\")\n })\n }\n\n removeImage() {\n this.pictureThumbnail.innerHTML = IMAGE_PLACEHOLDER\n this.pictureIdField.value = \"\"\n this.image = null\n this.cropLink.classList.add(\"disabled\")\n this.setElementDirty()\n }\n\n setElementDirty() {\n this.closest(\".element-editor\").setDirty(this)\n }\n\n updateCropLink() {\n if (!this.pictureId || !this.imageCropperEnabled) return\n\n this.cropLink.classList.remove(\"disabled\")\n\n if (this.cropLink.href.match(/(picture_id=)\\d+/)) {\n this.cropLink.href = this.cropLink.href.replace(\n /(picture_id=)\\d+/,\n \"$1\" + this.pictureId\n )\n } else {\n this.cropLink.href = this.cropLink.href + `&picture_id=${this.pictureId}`\n }\n }\n\n get cropFrom() {\n if (this.cropFromField.value === \"\") {\n return this.defaultCropFrom.join(\"x\")\n }\n return this.cropFromField.value\n }\n\n get cropSize() {\n if (this.cropSizeField.value === \"\") {\n return this.defaultCropSize.join(\"x\")\n }\n return this.cropSizeField.value\n }\n\n get defaultCropSize() {\n if (!this.imageCropperEnabled) return []\n\n const mask = this.targetSize.split(\"x\").map((n) => parseInt(n))\n const zoom = max(\n mask[0] / this.imageFileWidth,\n mask[1] / this.imageFileHeight\n )\n\n return [Math.round(mask[0] / zoom), Math.round(mask[1] / zoom)]\n }\n\n get defaultCropFrom() {\n if (!this.imageCropperEnabled) return []\n\n const dimensions = this.defaultCropSize\n\n return [\n Math.round((this.imageFileWidth - dimensions[0]) / 2),\n Math.round((this.imageFileHeight - dimensions[1]) / 2)\n ]\n }\n\n get imageFileWidth() {\n return parseInt(this.pictureIdField.dataset.imageFileWidth)\n }\n\n get imageFileHeight() {\n return parseInt(this.pictureIdField.dataset.imageFileHeight)\n }\n\n get imageCropperEnabled() {\n return this.targetSizeField.dataset.imageCropper === \"true\"\n }\n}\n\ncustomElements.define(\"alchemy-picture-editor\", PictureEditor)\n","export default function (func, delay) {\n let timeout\n\n return function (...args) {\n const that = this\n\n clearTimeout(timeout)\n timeout = setTimeout(() => func.apply(that, args), delay)\n }\n}\n","export default function (a, b) {\n return a >= b ? a : b\n}\n","// Shows spinner while loading images and\n// fades the image after its been loaded\n\nimport Spinner from \"alchemy_admin/spinner\"\n\nexport default class PictureThumbnail extends HTMLElement {\n constructor() {\n super()\n\n this.classList.add(\"thumbnail_background\")\n this.spinner = new Spinner(\"small\")\n\n if (this.src) {\n this.start()\n }\n }\n\n handleEvent(evt) {\n switch (evt.type) {\n case \"load\":\n this.#onLoaded()\n break\n case \"error\":\n this.#onError(evt)\n break\n default:\n break\n }\n }\n\n connectedCallback() {\n this.#setImage()\n }\n\n disconnectedCallback() {\n this.image?.removeEventListener(\"load\", this)\n this.image?.removeEventListener(\"error\", this)\n this.stop()\n }\n\n createImage(src = this.src, alt = this.name) {\n this.image = new Image()\n this.image.src = src\n if (alt) {\n this.image.alt = alt\n }\n }\n\n start(src) {\n this.createImage(src)\n this.image.addEventListener(\"load\", this)\n this.image.addEventListener(\"error\", this)\n this.load()\n }\n\n load() {\n if (this.image?.complete) {\n return\n }\n this.setAttribute(\"loading\", \"loading\")\n this.innerHTML = \"\"\n this.spinner.spin(this)\n }\n\n stop() {\n this.classList.remove(\"loading\")\n this.spinner.stop()\n }\n\n #onLoaded() {\n this.spinner.stop()\n this.removeAttribute(\"loading\")\n }\n\n #onError(evt) {\n const message = `Could not load ${this.image.src}`\n const hoist = this.closest(\".ingredient-editor\")\n this.spinner.stop()\n this.innerHTML = `\n <sl-tooltip content=\"${message}\" ${hoist ? \"hoist\" : \"\"}>\n <alchemy-icon name=\"alert\" class=\"error\"></alchemy-icon>\n </sl-tooltip>\n `\n console.error(message, evt)\n }\n\n #setImage() {\n if (this.image?.complete) {\n this.replaceChildren(this.image)\n } else if (this.image) {\n this.append(this.image)\n }\n }\n\n set loading(value) {\n value ? this.load() : this.stop()\n }\n\n set src(src) {\n this.start(src)\n this.#setImage()\n }\n\n get name() {\n return this.getAttribute(\"name\")\n }\n\n get src() {\n return this.getAttribute(\"src\")\n }\n}\n\ncustomElements.define(\"alchemy-picture-thumbnail\", PictureThumbnail)\n","class PublishPageButton extends HTMLElement {\n constructor() {\n super()\n this.addEventListener(\"submit\", this)\n }\n\n connectedCallback() {\n document.addEventListener(\"alchemy:page-dirty\", this)\n }\n\n disconnectedCallback() {\n document.removeEventListener(\"alchemy:page-dirty\", this)\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"alchemy:page-dirty\":\n this.markDirty(event.detail)\n break\n case \"submit\":\n this.button.loading = true\n break\n }\n }\n\n markDirty(detail) {\n this.button.variant = \"primary\"\n this.button.disabled = false\n this.tooltip.content = detail.tooltip\n }\n\n get button() {\n return this.querySelector(\"sl-button\")\n }\n\n get tooltip() {\n return this.querySelector(\"sl-tooltip\")\n }\n}\n\ncustomElements.define(\"alchemy-publish-page-button\", PublishPageButton)\n","class Select extends HTMLSelectElement {\n #select2Element\n\n connectedCallback() {\n this.classList.add(\"alchemy_selectbox\")\n\n this.#select2Element = $(this).select2({\n minimumResultsForSearch: 5,\n dropdownAutoWidth: true,\n allowClear: !!this.allowClear\n })\n\n // For single selects, remove the close button if allowClear is not set\n // For multiple selects, always keep the close buttons\n if (!this.allowClear && !this.multiple) {\n this.#select2Element\n .prev(\".select2-container\")\n .find(\".select2-search-choice-close\")\n .remove()\n }\n }\n\n enable() {\n this.removeAttribute(\"disabled\")\n this.#updateSelect2()\n }\n\n disable() {\n this.setAttribute(\"disabled\", \"disabled\")\n this.#updateSelect2()\n }\n\n setOptions(data, prompt = undefined) {\n let selectedValue = this.value\n\n // reset the old options and insert the placeholder(s) first\n this.innerHTML = \"\"\n if (prompt) {\n this.add(new Option(prompt, \"\"))\n }\n\n // add the new options to the select\n data.forEach((item) => {\n this.add(new Option(item.text, item.id, false, item.id === selectedValue))\n })\n\n this.#updateSelect2()\n }\n\n /**\n * inform Select2 to update\n */\n #updateSelect2() {\n this.#select2Element.trigger(\"change\")\n }\n\n get allowClear() {\n return this.dataset.hasOwnProperty(\"allowClear\") || this.multiple\n }\n}\n\ncustomElements.define(\"alchemy-select\", Select, { extends: \"select\" })\n","import Sortable from \"sortablejs\"\nimport { growl } from \"alchemy_admin/growler\"\nimport { patch } from \"alchemy_admin/utils/ajax\"\nimport { translate } from \"alchemy_admin/i18n\"\nimport pleaseWaitOverlay from \"alchemy_admin/please_wait_overlay\"\n\n/**\n * Custom element for the sitemap container\n * Handles search/filter functionality and drag-and-drop sorting\n */\nexport class AlchemySitemap extends HTMLElement {\n connectedCallback() {\n this.searchInput = document.querySelector(\".search_input_field\")\n this.clearButton = document.querySelector(\"#search_field_clear\")\n this.resultCounter = document.querySelector(\"#page_filter_result\")\n\n this.setupSearch()\n\n // Wait for child custom elements to be defined before setting up sortables\n requestAnimationFrame(() => {\n this.setupSortables()\n })\n\n // Set up MutationObserver to re-initialize sortables when children containers are added\n this.observer = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n mutation.addedNodes.forEach((node) => {\n if (node.nodeType !== Node.ELEMENT_NODE) return\n\n // If the added node itself is a children container, initialize it\n if (node.classList?.contains(\"children\")) {\n this.setupSortable(node)\n }\n\n // Also check for children containers nested within the added node\n // This handles cases where a parent element with nested children is added at once\n node\n .querySelectorAll(\".children\")\n .forEach((el) => this.setupSortable(el))\n })\n })\n })\n\n // Observe the sitemap for added nodes\n this.observer.observe(this, {\n childList: true,\n subtree: true\n })\n }\n\n disconnectedCallback() {\n this.teardownSearch()\n this.observer?.disconnect()\n }\n\n setupSearch() {\n this.searchInput?.addEventListener(\"input\", this)\n this.clearButton?.addEventListener(\"click\", this)\n }\n\n teardownSearch() {\n this.searchInput?.removeEventListener(\"input\", this)\n this.clearButton?.removeEventListener(\"click\", this)\n }\n\n handleEvent(event) {\n if (event.type === \"input\" && event.target === this.searchInput) {\n this.handleSearch(event)\n } else if (event.type === \"click\" && event.target === this.clearButton) {\n this.handleClearSearch(event)\n }\n }\n\n handleSearch(event) {\n const term = event.target.value.toLowerCase().trim()\n\n if (term === \"\") {\n this.clearFilter()\n return\n }\n\n this.filterPages(term)\n }\n\n filterPages(term) {\n const allPages = this.querySelectorAll(\".sitemap_page\")\n let matchCount = 0\n let firstMatch = null\n\n allPages.forEach((pageElement) => {\n const pageName = pageElement.getAttribute(\"name\") || \"\"\n\n if (pageName.toLowerCase().includes(term)) {\n pageElement.classList.add(\"highlight\")\n pageElement.classList.remove(\"no-match\")\n matchCount++\n if (!firstMatch) firstMatch = pageElement\n } else {\n pageElement.classList.remove(\"highlight\")\n pageElement.classList.add(\"no-match\")\n }\n })\n\n // Update result counter\n\n if (matchCount === 1) {\n this.resultCounter.textContent = `1 ${translate(\"page_found\")}`\n this.resultCounter.style.display = \"block\"\n } else if (matchCount > 1) {\n this.resultCounter.textContent = `${matchCount} ${translate(\"pages_found\")}`\n this.resultCounter.style.display = \"block\"\n } else {\n this.resultCounter.style.display = \"none\"\n }\n\n // Scroll first match into view\n if (firstMatch) {\n firstMatch.scrollIntoView({ behavior: \"smooth\", block: \"center\" })\n }\n }\n\n clearFilter() {\n const allPages = this.querySelectorAll(\".sitemap_page\")\n allPages.forEach((pageElement) => {\n pageElement.classList.remove(\"highlight\", \"no-match\")\n })\n\n this.resultCounter.style.display = \"none\"\n }\n\n handleClearSearch(event) {\n event.preventDefault()\n this.searchInput.value = \"\"\n this.clearFilter()\n }\n\n setupSortable(container) {\n new Sortable(container, {\n group: \"pages\",\n animation: 150,\n fallbackOnBody: true,\n swapThreshold: 0.65,\n handle: \".page-icon.handle\",\n draggable: \"alchemy-page-node\",\n onEnd: (evt) => this.handleSort(evt)\n })\n }\n\n setupSortables() {\n const sortables = this.querySelectorAll(\".children\")\n sortables.forEach((el) => this.setupSortable(el))\n }\n\n async handleSort(evt) {\n // Only proceed if actually moved to different position/container\n if (evt.from === evt.to && evt.oldIndex === evt.newIndex) {\n return\n }\n\n // evt.item is the <alchemy-page-node> element being dragged\n const pageNode = evt.item\n const pageId = pageNode.pageId\n const url = Alchemy.routes.move_admin_page_path(pageId)\n const data = {\n target_parent_id: evt.to.dataset.parentId,\n new_position: evt.newIndex\n }\n\n pleaseWaitOverlay(true)\n\n try {\n const response = await patch(url, data)\n const pageData = await response.data\n\n // Update the URL path of the moved page\n const pageEl = pageNode.querySelector(`#page_${pageId}`)\n if (pageEl) {\n const urlPathEl = pageEl.querySelector(\".sitemap_url\")\n if (urlPathEl && pageData.url_path) {\n urlPathEl.textContent = pageData.url_path\n }\n }\n\n // Update folder icons for affected parent pages\n this.updateFolderIcons(evt.from, evt.to)\n\n growl(translate(\"Successfully moved page\"))\n } catch (error) {\n growl(error.message || error, \"error\")\n // Revert the DOM change by reloading on error\n window.location.reload()\n } finally {\n pleaseWaitOverlay(false)\n }\n }\n\n updateFolderIcons(fromContainer, toContainer) {\n // Update folder icon for source parent (might now have no children)\n const fromParent = fromContainer.closest(\"alchemy-page-node\")\n fromParent?.updateFolderButton()\n\n // Update folder icon for destination parent (now definitely has children)\n if (fromContainer !== toContainer) {\n const toParent = toContainer.closest(\"alchemy-page-node\")\n toParent?.updateFolderButton()\n }\n }\n}\n\ncustomElements.define(\"alchemy-sitemap\", AlchemySitemap)\n","import Sortable from \"sortablejs\"\nimport { growl } from \"alchemy_admin/growler\"\nimport { post } from \"alchemy_admin/utils/ajax\"\nimport { reloadPreview } from \"alchemy_admin/components/preview_window\"\nimport { dispatchPageDirtyEvent } from \"alchemy_admin/components/element_editor\"\n\nconst SORTABLE_OPTIONS = {\n draggable: \".element-editor\",\n handle: \".element-handle.draggable\",\n ghostClass: \"dragged\",\n animation: 150,\n swapThreshold: 0.65,\n easing: \"cubic-bezier(1, 0, 0, 1)\"\n}\n\nfunction onStart(event) {\n const name = event.item.dataset.elementName\n document\n .querySelectorAll(`[data-droppable-elements~=\"${name}\"]`)\n .forEach((dropzone) => dropzone.classList.add(\"droppable-elements\"))\n}\n\nfunction onSort(event) {\n const item = event.item\n const parentElement = event.to.parentElement.closest(\".element-editor\")\n const params = {\n element_id: item.dataset.elementId,\n position: event.newIndex + 1\n }\n\n if (parentElement) {\n params.parent_element_id = parentElement.dataset.elementId\n }\n\n // Only send the request if the item was moved to a different container\n // or sorted in the same list. Not on the old list in order to avoid incrementing\n // the position of the other elements.\n if (event.target === event.to) {\n post(Alchemy.routes.order_admin_elements_path, params).then((response) => {\n const data = response.data\n growl(data.message)\n if (data.pageHasUnpublishedChanges) {\n dispatchPageDirtyEvent(data)\n }\n reloadPreview()\n item.updateTitle(data.preview_text)\n })\n }\n}\n\nfunction onEnd() {\n const dropzones = document.querySelectorAll(\"[data-droppable-elements]\")\n dropzones.forEach((dropzone) =>\n dropzone.classList.remove(\"droppable-elements\")\n )\n}\n\nclass SortableElements extends HTMLElement {\n connectedCallback() {\n const group = {\n name: this.dataset.elementName,\n put(to, _from, item) {\n return to.el.dataset.droppableElements\n .split(\" \")\n .includes(item.dataset.elementName)\n }\n }\n new Sortable(this, {\n ...SORTABLE_OPTIONS,\n onStart,\n onSort,\n onEnd,\n group\n })\n }\n}\n\ncustomElements.define(\"alchemy-sortable-elements\", SortableElements)\n","import { AlchemyHTMLElement } from \"alchemy_admin/components/alchemy_html_element\"\n\nclass Spinner extends AlchemyHTMLElement {\n static properties = {\n size: { default: \"medium\" },\n color: { default: \"currentColor\" }\n }\n\n render() {\n this.className = `spinner spinner--${this.size}`\n\n return `\n <svg width=\"100%\" viewBox=\"0 0 28 28\" style=\"--spinner-color: ${this.color}\">\n <path\n class=\"hex1\"\n d=\"M5.938,18.07l-5.878-5.9l2.154-8.058l8.024-2.161l5.87,5.9l-2.144,8.058L5.938,18.07z\"\n />\n <path\n class=\"hex2\"\n d=\"M19.686,20.785l-4.731-4.754l1.725-6.487l6.468-1.742l4.733,4.754l-1.734,6.487L19.686,20.785z\"\n />\n <path\n class=\"hex3\"\n d=\"M11.708,26.294l-3.47-3.485l1.276-4.758l4.74-1.276l3.468,3.485l-1.265,4.758L11.708,26.294z\"\n />\n </svg>\n `\n }\n}\n\ncustomElements.define(\"alchemy-spinner\", Spinner)\n","import { setupSelectLocale } from \"alchemy_admin/i18n\"\n\nclass TagsAutocomplete extends HTMLElement {\n async connectedCallback() {\n await setupSelectLocale()\n\n this.classList.add(\"autocomplete_tag_list\")\n $(this.input).select2(this.select2Config)\n }\n\n get input() {\n return this.getElementsByTagName(\"input\")[0]\n }\n\n get select2Config() {\n return {\n tags: true,\n tokenSeparators: [\",\"],\n openOnEnter: false,\n minimumInputLength: 1,\n createSearchChoice: this.#createSearchChoice,\n ajax: {\n url: this.getAttribute(\"url\"),\n dataType: \"json\",\n data: (term) => {\n return { term }\n },\n results: (data) => {\n return { results: data }\n }\n },\n initSelection: this.#initSelection\n }\n }\n\n #createSearchChoice(term, data) {\n if (\n $(data).filter(function () {\n return this.text.localeCompare(term) === 0\n }).length === 0\n ) {\n return {\n id: term,\n text: term\n }\n }\n }\n\n #initSelection(element, callback) {\n const data = []\n $(element.val().split(\",\")).each(function () {\n data.push({\n id: this.trim(),\n text: this\n })\n })\n callback(data)\n }\n}\n\ncustomElements.define(\"alchemy-tags-autocomplete\", TagsAutocomplete)\n","import \"tinymce\"\nimport { AlchemyHTMLElement } from \"alchemy_admin/components/alchemy_html_element\"\nimport { currentLocale } from \"alchemy_admin/i18n\"\n\nconst DARK_THEME = \"alchemy-dark\"\nconst LIGHT_THEME = \"alchemy\"\n\nclass Tinymce extends AlchemyHTMLElement {\n #min_height = null\n\n /**\n * the observer will initialize Tinymce if the textarea becomes visible\n */\n connected() {\n this.className = \"tinymce_container\"\n\n const observerCallback = (entries, observer) => {\n entries.forEach((entry) => {\n if (entry.intersectionRatio > 0) {\n this._initTinymceEditor()\n // disable observer after the Tinymce was initialized\n observer.unobserve(entry.target)\n }\n })\n }\n\n const options = {\n root: document.getElementById(\"element_area\"),\n rootMargin: \"0px\",\n threshold: [0.05]\n }\n\n this.tinymceIntersectionObserver = new IntersectionObserver(\n observerCallback,\n options\n )\n this.tinymceIntersectionObserver.observe(this)\n\n // Set up theme change listener\n this._setupThemeChangeListener()\n }\n\n /**\n * disconnect intersection observer and remove Tinymce editor if the web components get destroyed\n */\n disconnected() {\n if (this.tinymceIntersectionObserver !== null) {\n this.tinymceIntersectionObserver.disconnect()\n }\n\n // Remove theme change listener\n this._removeThemeChangeListener()\n\n tinymce.get(this.editorId)?.remove(this.editorId)\n }\n\n render() {\n return `\n ${this.initialContent}\n <alchemy-spinner size=\"small\"></alchemy-spinner>\n `\n }\n\n /**\n * hide the textarea until TinyMCE is ready to show the editor\n */\n afterRender() {\n this.style.minHeight = `${this.minHeight}px`\n this.editor.style.display = \"none\"\n }\n\n /**\n * initialize Richtext area after the Intersection observer triggered\n * @private\n */\n _initTinymceEditor() {\n tinymce.init(this.configuration).then((editors) => {\n editors.forEach((editor) => this._setupEditor(editor))\n })\n }\n\n /**\n * Setup editor after initialization\n * @param {Object} editor - The TinyMCE editor instance\n * @private\n */\n _setupEditor(editor) {\n // mark the editor container as visible\n // without these correction the editor remains hidden\n // after a drag and drop action\n editor.show()\n\n // remove the spinner after the Tinymce initialized (only on first init)\n const spinner = this.getElementsByTagName(\"alchemy-spinner\")[0]\n if (spinner) {\n spinner.remove()\n }\n\n // event listener to mark the editor as dirty\n if (this.elementEditor) {\n editor.on(\"dirty\", (evt) => {\n this.elementEditor.setDirty(evt.target.editorContainer)\n })\n editor.on(\"click\", () => this.elementEditor.onClickElement(false))\n }\n }\n\n /**\n * Set up listener for OS theme changes\n * @private\n */\n _setupThemeChangeListener() {\n this.darkModeMediaQuery = window.matchMedia(\"(prefers-color-scheme: dark)\")\n this.themeChangeHandler = (event) => this._handleThemeChange(event)\n this.darkModeMediaQuery.addEventListener(\"change\", this.themeChangeHandler)\n }\n\n /**\n * Remove theme change listener\n * @private\n */\n _removeThemeChangeListener() {\n if (this.darkModeMediaQuery && this.themeChangeHandler) {\n this.darkModeMediaQuery.removeEventListener(\n \"change\",\n this.themeChangeHandler\n )\n }\n }\n\n /**\n * Handle OS theme change and update TinyMCE skin\n * @param {MediaQueryListEvent} event - The media query change event\n * @private\n */\n _handleThemeChange(event) {\n const editor = tinymce.get(this.editorId)\n if (editor) {\n const skin = event.matches ? DARK_THEME : LIGHT_THEME\n const content_css = event.matches ? DARK_THEME : LIGHT_THEME\n\n // Update the skin by reinitializing the editor with new configuration\n editor.remove()\n tinymce\n .init({\n content_css,\n ...this.configuration,\n skin\n })\n .then((editors) => {\n editors.forEach((editor) => this._setupEditor(editor))\n })\n }\n }\n\n get configuration() {\n const customConfig = {}\n\n // read the attributes on the component and add them as custom configuration\n this.getAttributeNames().forEach((attributeName) => {\n if (![\"class\", \"id\", \"is\", \"name\", \"style\"].includes(attributeName)) {\n const config = this.getAttribute(attributeName)\n const key = attributeName.replaceAll(\"-\", \"_\")\n\n // Handle boolean HTML attributes (e.g., readonly=\"readonly\" or readonly=\"\")\n if (config === attributeName || config === \"\") {\n customConfig[key] = true\n } else {\n try {\n customConfig[key] = JSON.parse(config)\n } catch (e) {\n // also string values as parameter\n customConfig[key] = config\n }\n }\n }\n })\n\n const config = {\n content_css: this.preferredTheme,\n ...Alchemy.TinymceDefaults,\n ...customConfig,\n language: currentLocale(),\n selector: `#${this.editorId}`,\n skin: this.preferredTheme\n }\n\n // Tinymce has a height of 400px by default\n // if the element has a min_height set, we use this value for the height as well\n // so we do not need to set both values in the element configuration\n config.height = config.min_height\n\n return config\n }\n\n get preferredTheme() {\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n ? DARK_THEME\n : LIGHT_THEME\n }\n\n get editorId() {\n return this.editor.id\n }\n\n get editor() {\n return this.getElementsByTagName(\"textarea\")[0]\n }\n\n get elementEditor() {\n return document\n .getElementById(this.editorId)\n .closest(\"alchemy-element-editor\")\n }\n\n get minHeight() {\n return this.#min_height || this.configuration.min_height\n }\n\n set minHeight(value) {\n this.#min_height = value\n }\n}\n\ncustomElements.define(\"alchemy-tinymce\", Tinymce)\n","import Spinner from \"alchemy_admin/spinner\"\n\nclass UpdateCheck extends HTMLElement {\n async connectedCallback() {\n const spinner = new Spinner(\"small\")\n spinner.spin(this)\n\n try {\n const response = await fetch(this.url, { credentials: \"include\" })\n const responseJSON = await response.json()\n\n if (response.ok) {\n this.showStatus(responseJSON)\n } else {\n this.showError(response)\n }\n } catch (error) {\n this.showError(error)\n } finally {\n spinner.stop()\n }\n }\n\n get url() {\n return this.getAttribute(\"url\")\n }\n\n showStatus(responseJSON) {\n if (responseJSON[\"status\"] == \"true\") {\n this.querySelector(\".update_available\").classList.remove(\"hidden\")\n } else {\n this.querySelector(\".up_to_date\").classList.remove(\"hidden\")\n }\n }\n\n showError(error) {\n this.querySelector(\".error\").classList.remove(\"hidden\")\n console.error(\"[alchemy] Error fetching update status\", error)\n }\n}\n\ncustomElements.define(\"alchemy-update-check\", UpdateCheck)\n","(()=>{var n=Handlebars.template;(Handlebars.templates=Handlebars.templates||{})[\"node_folder.hbs\"]=n({0:function(n,e,l,a,r){return\"right\"},1:function(n,e,l,a,r){return\"down\"},compiler:[8,\">= 4.3.0\"],main:function(n,e,l,a,r){var o,t=n.lambda,d=n.escapeExpression,u=n.lookupProperty||function(n,e){if(Object.prototype.hasOwnProperty.call(n,e))return n[e]};return'<a class=\"node_folder\" data-record-id=\"'+d(t(null!=(o=null!=e?u(e,\"node\"):e)?u(o,\"id\"):o,e))+'\" data-record-type=\"'+d(t(null!=(o=null!=e?u(e,\"node\"):e)?u(o,\"type\"):o,e))+'\">\\n <alchemy-icon name=\"arrow-'+(null!=(o=u(l,\"if\").call(null!=e?e:n.nullContext||{},null!=(o=null!=e?u(e,\"node\"):e)?u(o,\"folded\"):o,{name:\"if\",hash:{},fn:n.program(0,r,0),inverse:n.program(1,r,0),data:r,loc:{start:{line:2,column:28},end:{line:2,column:72}}}))?o:\"\")+'-s\"></alchemy-icon>\\n</a>\\n'},useData:!0})})();","import { registerIconLibrary, setDefaultAnimation } from \"shoelace\"\n\n// Change the default animation for all tooltips\nsetDefaultAnimation(\"tooltip.show\", {\n keyframes: [\n { transform: \"translateY(10px)\", opacity: \"0\" },\n { transform: \"translateY(0)\", opacity: \"1\" }\n ],\n options: {\n duration: 100\n }\n})\n\nsetDefaultAnimation(\"tooltip.hide\", {\n keyframes: [\n { transform: \"translateY(0)\", opacity: \"1\" },\n { transform: \"translateY(10px)\", opacity: \"0\" }\n ],\n options: {\n duration: 100\n }\n})\n\n// Change the default animation for all dialogs\nsetDefaultAnimation(\"dialog.show\", {\n keyframes: [\n { transform: \"scale(0.98)\", opacity: \"0\" },\n { transform: \"scale(1)\", opacity: \"1\" }\n ],\n options: {\n duration: 150\n }\n})\n\nsetDefaultAnimation(\"dialog.hide\", {\n keyframes: [\n { transform: \"scale(1)\", opacity: \"1\" },\n { transform: \"scale(0.98)\", opacity: \"0\" }\n ],\n options: {\n duration: 150\n }\n})\n\nconst spriteUrl = document\n .querySelector('link[rel=\"preload\"][as=\"image\"]')\n .getAttribute(\"href\")\n\nconst iconMap = {\n \"x-lg\": \"close\",\n caret: \"arrow-down-s\"\n}\n\nconst options = {\n resolver: (name) => `${spriteUrl}#ri-${iconMap[name] || name}-line`,\n mutator: (svg) => {\n svg.setAttribute(\"fill\", \"currentColor\")\n svg.setAttribute(\"viewBox\", \"0 0 24 24\")\n },\n spriteSheet: true\n}\n\nregisterIconLibrary(\"default\", options)\nregisterIconLibrary(\"system\", options)\n","export function on(eventName, baseSelector, targetSelector, callback) {\n document.querySelectorAll(baseSelector).forEach((baseNode) => {\n baseNode.addEventListener(eventName, (evt) => {\n const targets = Array.from(baseNode.querySelectorAll(targetSelector))\n let currentNode = evt.target\n\n while (currentNode !== baseNode) {\n if (targets.includes(currentNode)) {\n callback.call(currentNode, evt)\n return\n }\n currentNode = currentNode.parentElement\n }\n })\n })\n}\n","import Cropper from \"cropperjs\"\n\nexport default class ImageCropper {\n #initialized = false\n #cropper = null\n #cropFromField = null\n #cropSizeField = null\n\n constructor(image, settings) {\n this.image = image\n this.defaultBox = settings.default_box\n this.aspectRatio = settings.ratio\n this.#cropFromField = document.getElementById(\n settings.crop_from_form_field_id\n )\n this.#cropSizeField = document.getElementById(\n settings.crop_size_form_field_id\n )\n this.elementId = settings.element_id\n this.dialog = Alchemy.currentDialog()\n if (this.dialog) {\n this.dialog.options.closed = () => this.destroy()\n this.bind()\n }\n this.init()\n }\n\n get cropperOptions() {\n return {\n aspectRatio: this.aspectRatio,\n viewMode: 1,\n zoomable: false,\n checkCrossOrigin: false, // Prevent CORS issues\n checkOrientation: false, // Prevent loading the image via AJAX which can cause CORS issues\n data: this.box,\n cropend: () => {\n const data = this.#cropper.getData(true)\n this.update(data)\n }\n }\n }\n\n get cropFrom() {\n if (this.#cropFromField?.value) {\n return this.#cropFromField.value.split(\"x\").map((v) => parseInt(v))\n }\n }\n\n get cropSize() {\n if (this.#cropSizeField?.value) {\n return this.#cropSizeField.value.split(\"x\").map((v) => parseInt(v))\n }\n }\n\n get box() {\n if (this.cropFrom && this.cropSize) {\n return {\n x: this.cropFrom[0],\n y: this.cropFrom[1],\n width: this.cropSize[0],\n height: this.cropSize[1]\n }\n } else {\n return this.defaultBoxSize\n }\n }\n\n get defaultBoxSize() {\n return {\n x: this.defaultBox[0],\n y: this.defaultBox[1],\n width: this.defaultBox[2],\n height: this.defaultBox[3]\n }\n }\n\n init() {\n if (!this.#initialized) {\n this.#cropper = new Cropper(this.image, this.cropperOptions)\n this.#initialized = true\n }\n }\n\n update(coords) {\n this.#cropFromField.value = `${coords.x}x${coords.y}`\n this.#cropFromField.dispatchEvent(new Event(\"change\"))\n this.#cropSizeField.value = `${coords.width}x${coords.height}`\n this.#cropSizeField.dispatchEvent(new Event(\"change\"))\n }\n\n reset() {\n this.#cropper.setData(this.defaultBoxSize)\n this.update(this.defaultBoxSize)\n }\n\n destroy() {\n if (this.#cropper) {\n this.#cropper.destroy()\n }\n this.#initialized = false\n return true\n }\n\n bind() {\n this.dialog.dialog_body.find('button[type=\"submit\"]').on(\"click\", () => {\n const elementEditor = document.querySelector(\n `[data-element-id='${this.elementId}']`\n )\n elementEditor.setDirty()\n this.dialog.close()\n return false\n })\n this.dialog.dialog_body.find('button[type=\"reset\"]').on(\"click\", () => {\n this.reset()\n return false\n })\n }\n}\n","import { Dialog } from \"alchemy_admin/dialog\"\n\nexport default class ImageOverlay extends Dialog {\n constructor(url, options = {}) {\n super(url, options)\n }\n\n init() {\n $(\".zoomed-picture-background\").on(\"click\", (e) => {\n e.stopPropagation()\n if (e.target.nodeName === \"IMG\") {\n return\n }\n this.close()\n return false\n })\n $(\".picture-overlay-handle\").on(\"click\", (e) => {\n this.dialog.toggleClass(\"hide-form\")\n return false\n })\n this.$previous = $(\".previous-picture\")\n this.$next = $(\".next-picture\")\n this.#initKeyboardNavigation()\n super.init()\n }\n\n previous() {\n if (this.$previous[0] != null) {\n this.$previous[0].click()\n }\n }\n\n next() {\n if (this.$next[0] != null) {\n this.$next[0].click()\n }\n }\n\n build() {\n this.dialog_container = $('<div class=\"alchemy-image-overlay-container\" />')\n this.dialog = $('<div class=\"alchemy-image-overlay-dialog\" />')\n this.dialog_body = $('<div class=\"alchemy-image-overlay-body\" />')\n this.close_button = $(`<a class=\"alchemy-image-overlay-close\">\n <alchemy-icon name=\"close\" size=\"xl\"></alchemy-icon>\n </a>`)\n this.dialog.append(this.close_button)\n this.dialog.append(this.dialog_body)\n this.dialog_container.append(this.dialog)\n this.overlay = $('<div class=\"alchemy-image-overlay\" />')\n this.$body.append(this.overlay)\n this.$body.append(this.dialog_container)\n }\n\n #initKeyboardNavigation() {\n this.$document.keydown((e) => {\n if (e.target.nodeName === \"INPUT\" || e.target.nodeName === \"TEXTAREA\") {\n return true\n }\n switch (e.which) {\n case 37:\n this.previous()\n return false\n case 39:\n this.next()\n return false\n default:\n return true\n }\n })\n }\n}\n","import { on } from \"alchemy_admin/utils/events\"\nimport { openDialog } from \"alchemy_admin/dialog\"\n\nfunction toggleCheckboxes(state) {\n document\n .querySelectorAll(\".picture_tool.select input[type='checkbox']\")\n .forEach((checkbox) => {\n checkbox.checked = state\n checkbox.closest(\".picture_thumbnail\").classList.toggle(\"active\", state)\n })\n}\n\nfunction checkedInputs() {\n return document.querySelectorAll(\"#picture_archive input:checked\")\n}\n\nfunction editMultiplePicturesUrl(href) {\n const url = new URL(href)\n\n checkedInputs().forEach((entry) =>\n url.searchParams.append(entry.name, entry.value)\n )\n\n return url.toString()\n}\n\n/**\n * Multiple picture select handler for the picture archive.\n */\nexport default function PictureSelector() {\n const selectAllButton = document.querySelector(\"#select_all_pictures\")\n const selectedItemTools = document.querySelector(\".selected_item_tools\")\n\n on(\"click\", \".toolbar_buttons\", \"a#select_all_pictures\", (event) => {\n event.preventDefault()\n\n selectAllButton.classList.toggle(\"active\")\n\n const state = selectAllButton.classList.contains(\"active\")\n\n toggleCheckboxes(state)\n\n selectedItemTools.classList.toggle(\"hidden\", !state)\n })\n\n // make the item toolbar visible and show the checkbox also if it is not hovered anymore\n on(\"change\", \".picture_tool.select\", \"input\", (event) => {\n selectedItemTools.classList.toggle(\"hidden\", checkedInputs().length === 0)\n\n const parentElementClassList = event.target.parentElement.classList\n const checked = event.target.checked\n\n parentElementClassList.toggle(\"visible\", checked)\n })\n\n // open the edit view in a dialog modal\n on(\"click\", \".selected_item_tools\", \"a#edit_multiple_pictures\", (event) => {\n event.preventDefault()\n\n const url = editMultiplePicturesUrl(event.target.href)\n\n openDialog(url, {\n title: event.target.title,\n size: \"400x295\"\n })\n })\n}\n","import Sortable from \"sortablejs\"\nimport { patch } from \"alchemy_admin/utils/ajax\"\nimport { on } from \"alchemy_admin/utils/events\"\nimport { growl } from \"alchemy_admin/growler\"\n\nfunction displayNodeFolders() {\n document.querySelectorAll(\"li.menu-item\").forEach((el) => {\n const leftIconArea = el.querySelector(\".nodes_tree-left_images\")\n const list = el.querySelector(\".children\")\n const node = {\n folded: el.dataset.folded === \"true\",\n id: el.dataset.id,\n type: el.dataset.type\n }\n\n if (list.children.length > 0 || node.folded) {\n leftIconArea.innerHTML = Handlebars.templates[\"node_folder.hbs\"]({\n node: node\n })\n } else {\n leftIconArea.innerHTML = \"&nbsp;\"\n }\n })\n}\n\nfunction onFinishDragging(evt) {\n const url = Alchemy.routes[evt.item.dataset.type].move_api_path(\n evt.item.dataset.id\n )\n const data = {\n target_parent_id: evt.to.dataset.recordId,\n new_position: evt.newIndex\n }\n\n patch(url, data)\n .then(() => {\n const message = Alchemy.t(\"Successfully moved menu item\")\n growl(message)\n displayNodeFolders()\n })\n .catch((error) => {\n growl(error.message || error, \"error\")\n })\n}\n\nfunction handleNodeFolders() {\n on(\"click\", \".nodes_tree\", \".node_folder\", function () {\n const nodeId = this.dataset.recordId\n const menu_item = this.closest(\"li.menu-item\")\n const url =\n Alchemy.routes[this.dataset.recordType].toggle_folded_api_path(nodeId)\n const list = menu_item.querySelector(\".children\")\n\n patch(url)\n .then(() => {\n list.classList.toggle(\"folded\")\n menu_item.dataset.folded =\n menu_item.dataset.folded == \"true\" ? \"false\" : \"true\"\n displayNodeFolders()\n })\n .catch((error) => {\n growl(error.message || error)\n })\n })\n}\n\nexport default function NodeTree() {\n handleNodeFolders()\n displayNodeFolders()\n\n document.querySelectorAll(\".nodes_tree ul.children\").forEach((el) => {\n new Sortable(el, {\n group: \"nodes\",\n animation: 150,\n fallbackOnBody: true,\n swapThreshold: 0.65,\n handle: \".node_name\",\n invertSwap: true,\n onEnd: onFinishDragging\n })\n })\n}\n","// We still use jQuery in some places (ie. select2)\nimport \"handlebars\"\nimport \"jquery\"\nimport \"@ungap/custom-elements\"\nimport { Turbo } from \"@hotwired/turbo-rails\"\nimport \"select2\"\n\nimport Rails from \"@rails/ujs\"\n\nimport { translate } from \"alchemy_admin/i18n\"\nimport { currentDialog, closeCurrentDialog } from \"alchemy_admin/dialog\"\nimport Dirty from \"alchemy_admin/dirty\"\nimport * as FixedElements from \"alchemy_admin/fixed_elements\"\nimport { growl } from \"alchemy_admin/growler\"\nimport Initializer from \"alchemy_admin/initializer\"\nimport { LinkDialog } from \"alchemy_admin/link_dialog\"\nimport pleaseWaitOverlay from \"alchemy_admin/please_wait_overlay\"\nimport Spinner from \"alchemy_admin/spinner\"\nimport { reloadPreview } from \"alchemy_admin/components/preview_window\"\nimport { openConfirmDialog } from \"alchemy_admin/confirm_dialog\"\n\n// Web Components\nimport \"alchemy_admin/components\"\n\n// Handlebars Templates\nimport \"alchemy_admin/templates/compiled\"\n\n// Shoelace Setup\nimport \"alchemy_admin/shoelace_theme\"\n\n// Global Alchemy object\nif (typeof window.Alchemy === \"undefined\") {\n window.Alchemy = {}\n}\n\n// Enhance the global Alchemy object with imported features\nObject.assign(Alchemy, {\n closeCurrentDialog,\n currentDialog,\n ...Dirty,\n t: translate, // Global utility method for translating a given string\n FixedElements,\n growl,\n LinkDialog,\n pleaseWaitOverlay,\n Spinner,\n reloadPreview\n})\n\nRails.start()\nTurbo.config.forms.confirm = openConfirmDialog\ndocument.addEventListener(\"turbo:load\", Initializer)\n\n// Public API for extensions\nexport { RemoteSelect } from \"alchemy_admin/components/remote_select\"\nexport { on } from \"alchemy_admin/utils/events\"\n\n// Page-specific modules - bundled to avoid dual-loading\nexport { default as ImageCropper } from \"alchemy_admin/image_cropper\"\nexport { default as ImageOverlay } from \"alchemy_admin/image_overlay\"\nexport { default as pictureSelector } from \"alchemy_admin/picture_selector\"\nexport { default as NodeTree } from \"alchemy_admin/node_tree\"\n","import Hotkeys from \"alchemy_admin/hotkeys\"\nimport pleaseWaitOverlay from \"alchemy_admin/please_wait_overlay\"\n\nexport default function Initializer() {\n // We obviously have javascript enabled.\n document.documentElement.classList.remove(\"no-js\")\n\n // Initialize hotkeys.\n Hotkeys()\n\n // Add observer for please wait overlay.\n document.querySelectorAll(\".please_wait\").forEach((element) => {\n element.addEventListener(\"click\", pleaseWaitOverlay)\n })\n\n // Hack for enabling tab focus for <a>'s styled as button.\n document.querySelectorAll(\"a.button\").forEach((button) => {\n button.setAttribute(\"tabindex\", 0)\n })\n\n // Override the filter of keymaster.js so we can blur the fields on esc key.\n key.filter = function (event) {\n let tagName = (event.target || event.srcElement).tagName\n return (\n key.isPressed(\"esc\") ||\n !(tagName === \"INPUT\" || tagName === \"SELECT\" || tagName === \"TEXTAREA\")\n )\n }\n}\n"],"names":["KEY_SEPARATOR","getTranslation","key","locale","currentLocale","translations","Alchemy","test","keys","split","group","nestedTranslation","console","warn","document","documentElement","lang","translate","replacement","undefined","translation","replace","async","setupSelectLocale","import","$","extend","fn","select2","defaults","locales","bindedHotkeys","showHelp","evt","target","is","String","fromCharCode","which","openDialog","title","t","size","Hotkeys","scope","jQuery","removeEventListener","addEventListener","forEach","hotkey","unbind","search_fields","querySelectorAll","search_fields_clear","setScope","el","focus","focusVisible","push","click","blur","dataset","alchemyHotkey","createHtmlElement","text","element","createElement","innerHTML","content","children","Spinner$1","constructor","color","this","spinner","spin","parent","body","append","stop","remove","currentDialogs","DEFAULTS","header_height","padding","modal","overflow","ready","closed","Dialog","url","options","$document","$window","window","$body","width","parseInt","height","build","resize","open","dialog","trigger","bind_close_events","requestAnimationFrame","dialog_container","addClass","overlay","load","close","off","removeClass","on","pop","show_spinner","get","data","fail","xhr","show_error","reload","dialog_body","empty","remove_spinner","hide","html","init","dispatchEvent","CustomEvent","bubbles","detail","show","Spinner","watch_remote_forms","$form","event","getResponseHeader","match","responseText","statusText","status","error_body","error_header","error_type","error_messages","$errorDiv","error","close_button","e","keydown","dialog_header","dialog_title","getSize","css","doc_width","doc_height","currentDialog","length","closeCurrentDialog","callback","ConfirmDialog","message","ok_label","cancel_label","on_ok","bindEvents","cancelButton","preventDefault","on_cancel","okButton","source","querySelector","openConfirmDialog","Promise","resolve","pleaseWaitOverlay","checkPageDirtyness","action","find","appendTo","Turbo","visit","pathname","then","proceed","onbeforeunload","Dirty","PageLeaveObserver","currentTarget","removeTab","element_id","fixed_elements","getElementById","panel_name","label","tab","panel","growl","style","flashType","flashNotices","flashMessage","ANCHOR_REGEX","PreviewWindow","HTMLIFrameElement","afterLoad","reloadIcon","loadTimeout","previewReadyHandler","super","handlePreviewReadyMessage","bind","handleEvent","type","clearLoadTimeout","stopSpinner","call","connectedCallback","attachEvents","localStorage","getItem","previewUrlSelect","value","refresh","disconnectedCallback","postMessage","contentWindow","startSpinner","src","setTimeout","isDragged","dragged","transitionProperty","pointerEvents","reloadButton","sizeSelect","setItem","includes","clearTimeout","getAttribute","reloadPreview","customElements","define","extends","IngredientAnchorLink","updateIcon","ingredientId","active","ingredientEditor","setAttribute","Action","HTMLElement","actions","removeFixedElement","updateAnchorIcon","hidePleaseWaitOverlay","func","name","params","hasAttribute","JSON","parse","AlchemyHTMLElement","static","observedAttributes","Object","properties","changeComponent","initialContent","default","getAttributeNames","_updateFromAttribute","_updateComponent","connected","disconnected","attributeChangedCallback","render","afterRender","dispatchCustomEvent","attributeValue","propertyName","reduce","a","b","charAt","toUpperCase","slice","hightlightTerm","term","RegExp","RemoteSelect","allowClear","selection","placeholder","queryParams","input","classList","add","select2Config","onOpen","onChange","removed","added","getElementsByTagName","initSelection","_$el","ajax","ajaxConfig","formatSelection","item","_renderResult","formatResult","_el","query","_renderListEntry","datatype","quietMillis","page","_searchQuery","results","response","_parseResponse","q","name_cont","meta","more","per_page","total_count","Error","_hightlightTerm","attachment","icon_css_class","AutoSubmit","submitEvent","Event","cancelable","form","Button","HTMLButtonElement","remote","stopPropagation","disable","enable","rect","getBoundingClientRect","initialButtonText","removeAttribute","maxChars","formField","getFormField","createDisplayElement","countCharacters","formFields","display","className","after","charLength","textContent","toggle","ClipboardButton","clipboard","ClipboardJS","destroy","formatItem","object","optionEl","swatch","ColorSelect","select","initializeSelect2","toggleColorPicker","val","colorInput","textInput","minimumResultsForSearch","enabled","disabled","inputType","flatpickr","inputField","flatpickrOptions","enableTime","altInput","altFormat","altInputClass","noCalendar","time_24hr","onValueUpdate","_selectedDates","_dateStr","instance","closest","setDirty","dateFormat","DialogLink","HTMLAnchorElement","dialogOptions","contains","JSON_CONTENT_TYPE","TURBO_STREAM_CONTENT_TYPE","isGetRequest","method","toLowerCase","prepareOptions","accept","headers","Accept","getToken","prepareHeaders","stringify","attributes","patch","post","path","fetch","URL","location","origin","search","URLSearchParams","toString","prepareURL","contentType","isJson","isTurboStream","responseData","json","renderStreamMessage","ok","DomIdSelect","dataItem","hash","id","selectElement","pageId","fetchDomIds","routes","api_ingredients_path","page_id","ingredients","filter","ingredient","dom_id","map","prompt","setOptions","reset","frame","elements","contentDocument","Array","from","PublishElementButton","scheduleButtonVariant","scheduleButton","publishButton","dropdown","loading","DeleteElementButton","button","removeElement","elementEditor","fixed","elementId","pageHasUnpublishedChanges","dispatchPageDirtyEvent","tooltip","publishButtonTooltip","ElementEditor","header","toggleButton","focusElement","previewWindow","focusElementPreview","onClickElement","onSaveElement","hasEditors","firstChild","setTitle","selectTabForElement","expand","setClean","warning","ingredientsWithErrors","errorDisplay","errorMessage","appendChild","elementErrors","notice","updateTitle","previewText","ingredientAnchors","anchor","scrollToElement","scrollIntoView","behavior","scroll","reject","tabs","dirty","editor","collapsed","collapse","compact","toggleIcon","collapse_admin_element_path","nestedElementIds","selector","join","nestedElement","catch","finally","expanded","parentElementEditor","expand_admin_element_path","parentElementIds","parentElement","published","isPublished","bodySelector","footer","elementName","hasChildren","option","icon","ElementSelect","dropdownAutoWidth","hint","description","ElementsWindow","visible","turboFrame","focusElementEditor","collapseAllElements","removeProperty","widthFromCookie","setProperty","cookie","collapseButton","row","startsWith","ElementsWindowHandle","dragging","elementsWindow","onMouseDown","onMouseUp","onDrag","pageX","elementWindowWidth","innerWidth","FileEditor","deleteLink","fileIcon","fileName","formFieldId","removeFile","ListFilter","debounceTimer","filterField","clearButton","visibility","debounceTime","clear","matchedItems","itemsToShow","Set","lowerTerm","items","nameAttribute","indexOf","ancestor","itemsSelector","has","block","Message","dismissable","dismiss","iconName","dismissDelay","noticesWrapper","autoDismissDelay","Growl","Icon","spriteUrl","sizeClass","IngredientGroup","HTMLDetailsElement","localStorageKey","isInLocalStorage","expanded_ingredient_groups","localStorageItem","LinkButton","LinkDialog","linkUrl","linkTitle","linkTarget","linkClass","link","setLink","linkButtons","linkUrlField","linkTitleField","linkTargetField","linkClassField","UnlinkButton","linked","isLinked","LinkButtons","removeLink","unlinkButton","setElementDirty","linkButton","formatFileSize","bytes","exponent","Math","floor","log","pow","toFixed","name_or_page_name_cont","node","ancestors","seperator","FileUpload","file","request","progressEventLoaded","progressEventTotal","valid","initialize","_validateFile","_addRequestEventListener","loadedSize","cancel","reader","FileReader","readAsDataURL","image","Image","result","prepend","finished","abort","config","uploader_defaults","maxFileSize","file_size_limit","allowedFiletypes","allowed_filetypes","alchemy_pictures","alchemy_attachments","upload","onprogress","progressEvent","onload","responseMessage","onerror","_errorMessage","errorMessageContainer","progressElement","loaded","total","round","_status","toggleAttribute","_valid","isValid","_value","Progress","buttonLabel","fileUploads","fileCount","handleFileChange","_updateView","actionButton","onComplete","fileUpload","_activeUploads","_setupCloseButton","ariaLabel","_sumFileProgresses","field","accumulator","totalProgress","overallProgressValue","overallUploadSize","every","entry","fileProgress","uploadedFileCount","uploadsStatuses","totalSize","ceil","weight","dropzone","fileInput","_uploadFiles","files","_dragAndDropBehavior","_handleUploadComplete","redirectUrl","uploadProgress","dropzoneElement","isDraggedOver","toggleDropzoneClass","dataTransfer","getAsFile","fileUploadCount","XMLHttpRequest","upload_limit","_submitFile","_createProgress","formData","FormData","set","setRequestHeader","send","removeChild","BUTTON","AlchemyPageNode","folded","folderButton","handleFolderClick","fold_admin_page_path","toggleChildren","updateFolderIcon","childrenContainer","updateFolderButton","folderElement","shouldShowButton","tagName","outerHTML","PagePublicationFields","public_on_picker","public_until_picker","publication_date_fields","public_field","checkbox","now","Date","checked","setDate","pages","site","url_path","language_code","PictureDescriptionSelect","searchParams","PictureEditor","cropFromField","cropSizeField","pictureIdField","targetSizeField","imageCropperField","pictureThumbnail","deleteButton","cropLink","targetSize","pictureId","update","delay","timeout","args","that","apply","debounce","updateImage","updateCropLink","removeImage","observer","MutationObserver","mutationCallback","observe","disconnect","mutationsList","mutation","url_admin_picture_path","crop","imageCropperEnabled","crop_from","cropFrom","crop_size","cropSize","flatten","alt","href","defaultCropFrom","defaultCropSize","mask","n","zoom","imageFileWidth","imageFileHeight","dimensions","imageCropper","PictureThumbnail","start","onLoaded","onError","setImage","createImage","complete","hoist","replaceChildren","PublishPageButton","markDirty","variant","Select","HTMLSelectElement","select2Element","multiple","prev","updateSelect2","selectedValue","Option","hasOwnProperty","AlchemySitemap","searchInput","resultCounter","setupSearch","setupSortables","mutations","addedNodes","nodeType","Node","ELEMENT_NODE","setupSortable","childList","subtree","teardownSearch","handleSearch","handleClearSearch","trim","filterPages","clearFilter","allPages","matchCount","firstMatch","pageElement","container","Sortable","animation","fallbackOnBody","swapThreshold","handle","draggable","onEnd","handleSort","to","oldIndex","newIndex","pageNode","move_admin_page_path","target_parent_id","parentId","new_position","pageData","pageEl","urlPathEl","updateFolderIcons","fromContainer","toContainer","fromParent","toParent","SORTABLE_OPTIONS","ghostClass","easing","onStart","onSort","position","parent_element_id","order_admin_elements_path","preview_text","SortableElements","put","_from","droppableElements","TagsAutocomplete","tags","tokenSeparators","openOnEnter","minimumInputLength","createSearchChoice","dataType","localeCompare","each","DARK_THEME","LIGHT_THEME","min_height","root","rootMargin","threshold","tinymceIntersectionObserver","IntersectionObserver","entries","intersectionRatio","_initTinymceEditor","unobserve","_setupThemeChangeListener","_removeThemeChangeListener","tinymce","editorId","minHeight","configuration","editors","_setupEditor","editorContainer","darkModeMediaQuery","matchMedia","themeChangeHandler","_handleThemeChange","skin","matches","content_css","customConfig","attributeName","replaceAll","preferredTheme","TinymceDefaults","language","UpdateCheck","credentials","responseJSON","showStatus","showError","Handlebars","template","templates","l","r","compiler","main","o","lambda","d","escapeExpression","u","lookupProperty","prototype","nullContext","program","inverse","loc","line","column","end","useData","setDefaultAnimation","keyframes","transform","opacity","duration","iconMap","caret","resolver","mutator","svg","spriteSheet","eventName","baseSelector","targetSelector","baseNode","targets","currentNode","registerIconLibrary","ImageCropper","initialized","cropper","settings","defaultBox","default_box","aspectRatio","ratio","crop_from_form_field_id","crop_size_form_field_id","cropperOptions","viewMode","zoomable","checkCrossOrigin","checkOrientation","box","cropend","getData","v","x","y","defaultBoxSize","Cropper","coords","setData","ImageOverlay","nodeName","toggleClass","$previous","$next","initKeyboardNavigation","previous","next","checkedInputs","PictureSelector","selectAllButton","selectedItemTools","state","toggleCheckboxes","parentElementClassList","editMultiplePicturesUrl","displayNodeFolders","leftIconArea","list","onFinishDragging","move_api_path","recordId","NodeTree","nodeId","menu_item","recordType","toggle_folded_api_path","invertSwap","assign","FixedElements","onCreateLink","link_admin_pages_path","parameterMapping","selected_tab","link_title","link_target","internalForm","attachmentSelect","updatePage","submitForm","linkFormType","internalLink","domIdSelect","linkType","elementAnchor","link_url_regexp","showValidationError","errors","Rails","forms","confirm","srcElement","isPressed"],"mappings":"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"}
3
4
  =======
4
5
  {"version":3,"file":"alchemy_admin.min.js","sources":["../../../javascript/alchemy_admin/i18n.js","../../../javascript/alchemy_admin/hotkeys.js","../../../javascript/alchemy_admin/utils/dom_helpers.js","../../../javascript/alchemy_admin/spinner.js","../../../javascript/alchemy_admin/dialog.js","../../../javascript/alchemy_admin/confirm_dialog.js","../../../javascript/alchemy_admin/please_wait_overlay.js","../../../javascript/alchemy_admin/dirty.js","../../../javascript/alchemy_admin/fixed_elements.js","../../../javascript/alchemy_admin/growler.js","../../../javascript/alchemy_admin/link_dialog.js","../../../javascript/alchemy_admin/components/preview_window.js","../../../javascript/alchemy_admin/ingredient_anchor_link.js","../../../javascript/alchemy_admin/components/action.js","../../../javascript/alchemy_admin/components/remote_select.js","../../../javascript/alchemy_admin/components/attachment_select.js","../../../javascript/alchemy_admin/components/auto_submit.js","../../../javascript/alchemy_admin/components/button.js","../../../javascript/alchemy_admin/components/char_counter.js","../../../javascript/alchemy_admin/components/clipboard_button.js","../../../javascript/alchemy_admin/components/color_select.js","../../../javascript/alchemy_admin/components/datepicker.js","../../../javascript/alchemy_admin/components/dialog_link.js","../../../javascript/alchemy_admin/utils/ajax.js","../../../javascript/alchemy_admin/components/dom_id_select.js","../../../javascript/alchemy_admin/components/element_editor/publish_element_button.js","../../../javascript/alchemy_admin/components/element_editor/delete_element_button.js","../../../javascript/alchemy_admin/components/element_editor.js","../../../javascript/alchemy_admin/components/element_select.js","../../../javascript/alchemy_admin/components/elements_window.js","../../../javascript/alchemy_admin/components/elements_window_handle.js","../../../javascript/alchemy_admin/components/file_editor.js","../../../javascript/alchemy_admin/components/list_filter.js","../../../javascript/alchemy_admin/components/message.js","../../../javascript/alchemy_admin/components/growl.js","../../../javascript/alchemy_admin/components/icon.js","../../../javascript/alchemy_admin/components/ingredient_group.js","../../../javascript/alchemy_admin/components/link_buttons/link_button.js","../../../javascript/alchemy_admin/components/link_buttons/unlink_button.js","../../../javascript/alchemy_admin/components/link_buttons.js","../../../javascript/alchemy_admin/utils/format.js","../../../javascript/alchemy_admin/components/node_select.js","../../../javascript/alchemy_admin/components/uploader/file_upload.js","../../../javascript/alchemy_admin/components/uploader/progress.js","../../../javascript/alchemy_admin/components/uploader.js","../../../javascript/alchemy_admin/components/overlay.js","../../../javascript/alchemy_admin/components/page_node.js","../../../javascript/alchemy_admin/components/page_publication_fields.js","../../../javascript/alchemy_admin/components/page_select.js","../../../javascript/alchemy_admin/components/picture_description_select.js","../../../javascript/alchemy_admin/components/picture_editor.js","../../../javascript/alchemy_admin/utils/debounce.js","../../../javascript/alchemy_admin/utils/max.js","../../../javascript/alchemy_admin/components/picture_thumbnail.js","../../../javascript/alchemy_admin/components/publish_page_button.js","../../../javascript/alchemy_admin/components/select.js","../../../javascript/alchemy_admin/components/sitemap.js","../../../javascript/alchemy_admin/components/sortable_elements.js","../../../javascript/alchemy_admin/components/spinner.js","../../../javascript/alchemy_admin/components/tags_autocomplete.js","../../../javascript/alchemy_admin/components/tinymce.js","../../../javascript/alchemy_admin/components/update_check.js","../../../javascript/alchemy_admin/templates/compiled.js","../../../javascript/alchemy_admin/shoelace_theme.js","../../../javascript/alchemy_admin/utils/events.js","../../../javascript/alchemy_admin/image_cropper.js","../../../javascript/alchemy_admin/image_overlay.js","../../../javascript/alchemy_admin/picture_selector.js","../../../javascript/alchemy_admin/node_tree.js","../../../javascript/alchemy_admin.js","../../../javascript/alchemy_admin/initializer.js"],"sourcesContent":["const KEY_SEPARATOR = /\\./\n\nfunction nestedTranslation(translations, key) {\n const keys = key.split(KEY_SEPARATOR)\n const group = translations[keys[0]]\n if (group) {\n return group[keys[1]] || key\n }\n return key\n}\n\nfunction getTranslation(key) {\n const locale = currentLocale()\n const translations = Alchemy.translations\n\n if (!translations) {\n console.warn(`Translations for locale ${locale} not found!`)\n return key\n }\n\n if (KEY_SEPARATOR.test(key)) {\n return nestedTranslation(translations, key)\n }\n return translations[key] || key\n}\n\nexport function currentLocale() {\n if (document.documentElement.lang) {\n return document.documentElement.lang\n }\n return \"en\"\n}\n\nexport function translate(key, replacement = undefined) {\n let translation = getTranslation(key)\n\n if (replacement) {\n return translation.replace(/%\\{.+\\}/, replacement)\n }\n return translation\n}\n\nexport async function setupSelectLocale() {\n const locale = currentLocale()\n if (locale === \"en\") return\n\n await import(`select2/${locale}.js`)\n $.extend($.fn.select2.defaults, $.fn.select2.locales[locale])\n}\n","import \"keymaster\"\nimport { openDialog } from \"alchemy_admin/dialog\"\n\nconst bindedHotkeys = []\n\nfunction showHelp(evt) {\n if (\n !$(evt.target).is(\"input, textarea\") &&\n String.fromCharCode(evt.which) === \"?\"\n ) {\n openDialog(\"/admin/help\", {\n title: Alchemy.t(\"help\"),\n size: \"400x492\"\n })\n return false\n } else {\n return true\n }\n}\n\nexport default function (scope = document) {\n // The scope can be a jQuery object because we still use jQuery in alchemy_admin/dialog.js.\n if (scope instanceof jQuery) {\n scope = scope[0]\n }\n\n // Unbind all previously registered hotkeys if we are not inside a dialog.\n if (scope === document) {\n document.removeEventListener(\"keypress\", showHelp)\n document.addEventListener(\"keypress\", showHelp)\n bindedHotkeys.forEach((hotkey) => key.unbind(hotkey))\n }\n\n // Binds keyboard shortcuts to search fields.\n const search_fields = scope.querySelectorAll(\".search_input_field\")\n const search_fields_clear = scope.querySelectorAll(\n \".search_field_clear, .js_filter_field_clear\"\n )\n key(\"alt+f\", function () {\n key.setScope(\"search\")\n search_fields.forEach((el) => el.focus({ focusVisible: true }))\n return false\n })\n bindedHotkeys.push(\"alt+f\")\n key(\"esc\", \"search\", function () {\n search_fields_clear.forEach((el) => el.click())\n search_fields.forEach((el) => el.blur())\n })\n bindedHotkeys.push(\"esc\")\n\n // Binds click events to buttons with hotkeys.\n //\n // Simply add a data-alchemy-hotkey attribute to your link.\n // If a hotkey is triggered by user, the click event of the element gets triggerd.\n //\n scope.querySelectorAll(\"[data-alchemy-hotkey]\").forEach(function (el) {\n const hotkey = el.dataset.alchemyHotkey\n key(hotkey, () => el.click())\n bindedHotkeys.push(hotkey)\n })\n}\n","/**\n * create a HTML element\n * @param {string} text\n * @returns {HTMLElement}\n */\nexport function createHtmlElement(text) {\n const element = document.createElement(\"template\")\n element.innerHTML = text\n return element.content.children[0]\n}\n\n/**\n * wrap element with wrappingElement\n * @param {HTMLElement} element\n * @param {HTMLElement} wrappingElement\n */\nexport function wrap(element, wrappingElement) {\n element.replaceWith(wrappingElement)\n wrappingElement.appendChild(element)\n}\n","import { createHtmlElement } from \"alchemy_admin/utils/dom_helpers\"\n\nexport default class Spinner {\n constructor(size, color = \"currentColor\") {\n this.size = size\n this.color = color\n this.spinner = undefined\n }\n\n /**\n * @returns {HTMLElement|undefined}\n */\n get el() {\n return this.spinner\n }\n /**\n * @param {HTMLElement|undefined} parent\n */\n spin(parent) {\n if (typeof parent === \"undefined\") {\n parent = document.body\n }\n this.spinner = createHtmlElement(\n `<alchemy-spinner size=\"${this.size}\" color=\"${this.color}\"></alchemy-spinner>`\n )\n parent.append(this.spinner)\n return this\n }\n\n stop() {\n if (this.spinner) {\n this.spinner.remove()\n this.spinner = undefined\n }\n }\n}\n","import Hotkeys from \"alchemy_admin/hotkeys\"\nimport Spinner from \"alchemy_admin/spinner\"\n\n// Collection of all current dialog instances\nconst currentDialogs = []\n\nconst DEFAULTS = {\n header_height: 36,\n size: \"400x300\",\n padding: true,\n title: \"\",\n modal: true,\n overflow: \"visible\",\n ready: () => {},\n closed: () => {}\n}\n\nexport class Dialog {\n // Arguments:\n // - url: The url to load the content from via ajax\n // - options: A object holding options\n // - size: The maximum size of the Dialog\n // - title: The title of the Dialog\n constructor(url, options = {}) {\n this.url = url\n this.options = { ...DEFAULTS, ...options }\n this.$document = $(document)\n this.$window = $(window)\n this.$body = $(\"body\")\n const size = this.options.size.split(\"x\")\n this.width = parseInt(size[0], 10)\n this.height = parseInt(size[1], 10)\n this.build()\n this.resize()\n }\n\n // Opens the Dialog and loads the content via ajax.\n open() {\n this.dialog.trigger(\"Alchemy.DialogOpen\")\n this.bind_close_events()\n window.requestAnimationFrame(() => {\n this.dialog_container.addClass(\"open\")\n if (this.overlay != null) {\n return this.overlay.addClass(\"open\")\n }\n })\n this.$body.addClass(\"prevent-scrolling\")\n currentDialogs.push(this)\n this.load()\n }\n\n // Closes the Dialog and removes it from the DOM\n close() {\n this.dialog.trigger(\"DialogClose.Alchemy\")\n this.$document.off(\"keydown\")\n this.dialog_container.removeClass(\"open\")\n if (this.overlay != null) {\n this.overlay.removeClass(\"open\")\n }\n this.$document.on(\n \"webkitTransitionEnd transitionend oTransitionEnd\",\n () => {\n this.$document.off(\"webkitTransitionEnd transitionend oTransitionEnd\")\n this.dialog_container.remove()\n if (this.overlay != null) {\n this.overlay.remove()\n }\n this.$body.removeClass(\"prevent-scrolling\")\n currentDialogs.pop(this)\n if (this.options.closed != null) {\n return this.options.closed()\n }\n }\n )\n return true\n }\n\n // Loads the content via ajax and replaces the Dialog body with server response.\n load() {\n this.show_spinner()\n $.get(this.url, (data) => {\n this.replace(data)\n }).fail((xhr) => {\n this.show_error(xhr)\n })\n }\n\n // Reloads the Dialog content\n reload() {\n this.dialog_body.empty()\n this.load()\n }\n\n // Replaces the dialog body with given content and initializes it.\n replace(data) {\n this.remove_spinner()\n this.dialog_body.hide()\n this.dialog_body.html(data)\n this.init()\n this.dialog[0].dispatchEvent(\n new CustomEvent(\"DialogReady.Alchemy\", {\n bubbles: true,\n detail: {\n body: this.dialog_body[0]\n }\n })\n )\n if (this.options.ready != null) {\n this.options.ready(this.dialog_body)\n }\n this.dialog_body.show()\n }\n\n // Adds a spinner into Dialog body\n show_spinner() {\n this.spinner = new Spinner(\"medium\")\n this.spinner.spin(this.dialog_body[0])\n }\n\n // Removes the spinner from Dialog body\n remove_spinner() {\n this.spinner.stop()\n }\n\n // Initializes the Dialog body\n init() {\n Hotkeys(this.dialog_body)\n this.watch_remote_forms()\n }\n\n // Watches ajax requests inside of dialog body and replaces the content accordingly\n watch_remote_forms() {\n const $form = $('[data-remote=\"true\"]', this.dialog_body)\n\n $form.on(\"ajax:success\", (event) => {\n const xhr = event.detail[2]\n const content_type = xhr.getResponseHeader(\"Content-Type\")\n if (content_type.match(/javascript/)) {\n return\n } else {\n this.dialog_body.html(xhr.responseText)\n this.init()\n }\n })\n\n $form.on(\"ajax:error\", (event) => {\n const statusText = event.detail[1]\n const xhr = event.detail[2]\n this.show_error(xhr, statusText)\n })\n }\n\n // Displays an error message\n show_error(xhr, statusText) {\n if (xhr.status === 422) {\n this.dialog_body.html(xhr.responseText)\n this.init()\n return\n }\n\n const { error_body, error_header, error_type } = this.error_messages(\n xhr,\n statusText\n )\n\n const $errorDiv = $(`<alchemy-message type=\"${error_type}\">\n <h1>${error_header}</h1>\n <p>${error_body}</p>\n </alchemy-message>`)\n\n this.dialog_body.html($errorDiv)\n }\n\n // Returns error message based on xhr status\n error_messages(xhr, statusText) {\n let error_body,\n error_header,\n error_type = \"warning\"\n\n switch (xhr.status) {\n case 0:\n error_header = \"The server does not respond.\"\n error_body = \"Please check server and try again.\"\n break\n case 403:\n error_header = \"You are not authorized!\"\n error_body = \"Please close this window.\"\n break\n default:\n error_type = \"error\"\n if (statusText) {\n error_header = statusText\n console.error(xhr.responseText)\n } else {\n error_header = `${xhr.statusText} (${xhr.status})`\n }\n error_body = \"Please check log and try again.\"\n }\n\n return { error_header, error_body, error_type }\n }\n\n // Binds close events on:\n // - Close button\n // - Overlay (if the Dialog is a modal)\n // - ESC Key\n bind_close_events() {\n this.close_button.on(\"click\", () => {\n this.close()\n })\n this.dialog_container.addClass(\"closable\").on(\"click\", (e) => {\n if (e.target !== this.dialog_container.get(0)) {\n return true\n }\n this.close()\n return false\n })\n this.$document.keydown((e) => {\n if (e.which === 27) {\n this.close()\n return false\n } else {\n return true\n }\n })\n }\n\n // Builds the html structure of the Dialog\n build() {\n this.dialog_container = $('<div class=\"alchemy-dialog-container\" />')\n this.dialog = $('<div class=\"alchemy-dialog\" />')\n this.dialog_body = $('<div class=\"alchemy-dialog-body\" />')\n this.dialog_header = $('<div class=\"alchemy-dialog-header\" />')\n this.dialog_title = $('<div class=\"alchemy-dialog-title\" />')\n this.close_button = $(\n '<button class=\"alchemy-dialog-close\"><alchemy-icon name=\"close\"></alchemy-icon></button>'\n )\n this.dialog_title.text(this.options.title)\n this.dialog_header.append(this.dialog_title)\n this.dialog_header.append(this.close_button)\n this.dialog.append(this.dialog_header)\n this.dialog.append(this.dialog_body)\n this.dialog_container.append(this.dialog)\n if (this.options.modal) {\n this.dialog.addClass(\"modal\")\n }\n if (this.options.padding) {\n this.dialog_body.addClass(\"padded\")\n }\n if (this.options.modal) {\n this.overlay = $('<div class=\"alchemy-dialog-overlay\" />')\n this.$body.append(this.overlay)\n }\n this.$body.append(this.dialog_container)\n }\n\n // Sets the correct size of the dialog\n // It normalizes the given size, so that it never acceeds the window size.\n resize() {\n const { width, height } = this.getSize()\n\n this.dialog.css({\n width: width,\n \"min-height\": height,\n overflow: this.options.overflow\n })\n\n if (this.options.overflow === \"hidden\") {\n this.dialog_body.css({\n height: height,\n overflow: \"auto\"\n })\n } else {\n this.dialog_body.css({\n \"min-height\": height,\n overflow: \"visible\"\n })\n }\n }\n\n getSize() {\n const padding = this.options.padding ? 16 : 0\n const doc_width = this.$window.width()\n const doc_height = this.$window.height()\n\n let width = this.width\n let height = this.height\n\n if (width >= doc_width) {\n width = doc_width - padding\n }\n\n if (height >= doc_height) {\n height = doc_height - padding - DEFAULTS.header_height\n }\n\n return { width, height }\n }\n}\n\n// Gets the last dialog instantiated, which is the current one.\nexport function currentDialog() {\n const { length } = currentDialogs\n if (length === 0) {\n return\n }\n return currentDialogs[length - 1]\n}\n\n// Utility function to close the current Dialog\n//\n// You can pass a callback function, that gets triggered after the Dialog gets closed.\n//\nexport function closeCurrentDialog(callback) {\n const dialog = currentDialog()\n if (dialog != null) {\n dialog.options.closed = callback\n return dialog.close()\n }\n}\n\n// Utility function to open a new Dialog\nexport function openDialog(url, options) {\n if (!url) {\n throw \"No url given! Please provide an url.\"\n }\n const dialog = new Dialog(url, options)\n dialog.open()\n}\n","import { createHtmlElement } from \"alchemy_admin/utils/dom_helpers\"\nimport { translate } from \"alchemy_admin/i18n\"\n\nconst getDefaults = () => ({\n // The default size of the dialog\n size: \"300x100\",\n title: translate(\"Please confirm\"),\n ok_label: translate(\"Yes\"),\n cancel_label: translate(\"No\"),\n on_ok() {}\n})\n\nclass ConfirmDialog {\n constructor(message, options = {}) {\n this.message = message\n this.options = { ...getDefaults(), ...options }\n this.#build()\n this.#bindEvents()\n }\n\n open() {\n requestAnimationFrame(() => {\n this.dialog.show()\n })\n }\n\n #build() {\n const width = this.options.size.split(\"x\")[0]\n this.dialog = createHtmlElement(`\n <sl-dialog label=\"${this.options.title}\" style=\"--width: ${width}px\">\n ${this.message}\n <button slot=\"footer\" type=\"reset\" class=\"secondary mx-1 my-0\" autofocus>\n ${this.options.cancel_label}\n </button>\n <button slot=\"footer\" type=\"submit\" class=\"mx-1 my-0\">\n ${this.options.ok_label}\n </button>\n </sl-dialog>\n `)\n document.body.append(this.dialog)\n }\n\n #bindEvents() {\n this.cancelButton.addEventListener(\"click\", (evt) => {\n evt.preventDefault()\n this.options.on_cancel()\n this.dialog.hide()\n })\n this.okButton.addEventListener(\"click\", (evt) => {\n evt.preventDefault()\n this.options.on_ok()\n this.dialog.hide()\n })\n // Prevent the dialog from closing when the user clicks on the overlay\n this.dialog.addEventListener(\"sl-request-close\", (event) => {\n if (event.detail.source === \"overlay\") {\n this.options.on_cancel()\n event.preventDefault()\n }\n })\n // Remove the dialog from the DOM after it has been hidden\n this.dialog.addEventListener(\"sl-after-hide\", () => {\n this.dialog.remove()\n })\n }\n\n get cancelButton() {\n return this.dialog.querySelector(\"button[type=reset]\")\n }\n\n get okButton() {\n return this.dialog.querySelector(\"button[type=submit]\")\n }\n}\n\n/* Opens a confirm dialog\n *\n * @param {string} message - The message that will be displayed to the user\n * @param {Object} [options={}] - Configuration options for the dialog\n * @param {string} [options.title=\"Please confirm\"] - The title of the overlay window\n * @param {string} [options.cancel_label=\"No\"] - The label of the cancel button\n * @param {string} [options.ok_label=\"Yes\"] - The label of the ok button\n *\n * @returns {Promise<void>} A promise that resolves to true when the OK button is clicked and\n * resolves to false when the cancel button is clicked. Works as confirm dialog replacement\n * for Turbo.confirm.\n */\nexport function openConfirmDialog(message, options = {}) {\n return new Promise((resolve) => {\n const dialog = new ConfirmDialog(message, {\n ...options,\n on_ok() {\n resolve(true)\n },\n on_cancel() {\n resolve(false)\n }\n })\n dialog.open()\n })\n}\n","/**\n * To show the \"Please wait\" overlay.\n * Pass false to hide it.\n * @param {boolean} show\n */\nexport default function pleaseWaitOverlay(show = true) {\n document.querySelector(\"alchemy-overlay\").show = !!show\n}\n","import { openConfirmDialog } from \"alchemy_admin/confirm_dialog\"\nimport { translate } from \"alchemy_admin/i18n\"\nimport pleaseWaitOverlay from \"alchemy_admin/please_wait_overlay\"\n\nfunction checkPageDirtyness(element) {\n let callback = () => {}\n\n if ($(element).is(\"form\")) {\n callback = function () {\n const $form = $(\n `<form action=\"${element.action}\" method=\"POST\" style=\"display: none\" />`\n )\n $form.append($(element).find(\"input\"))\n $form.appendTo(\"body\")\n\n pleaseWaitOverlay()\n $form.trigger(\"submit\")\n }\n } else if ($(element).is(\"a\")) {\n callback = () => Turbo.visit(element.pathname)\n }\n\n const isPageDirty =\n document.querySelectorAll(\"alchemy-element-editor.dirty\").length > 0\n\n if (isPageDirty) {\n openConfirmDialog(translate(\"page_dirty_notice\"), {\n title: translate(\"warning\"),\n ok_label: translate(\"ok\"),\n cancel_label: translate(\"cancel\")\n }).then((proceed) => {\n if (proceed) {\n window.onbeforeunload = void 0\n callback()\n }\n })\n return false\n }\n return true\n}\n\nfunction PageLeaveObserver() {\n document.querySelectorAll(\"#main_navi a\").forEach((element) => {\n element.addEventListener(\"click\", (event) => {\n if (!checkPageDirtyness(event.currentTarget)) {\n event.preventDefault()\n }\n })\n })\n}\n\nexport default {\n checkPageDirtyness,\n PageLeaveObserver\n}\n","// Creates a fixed element tab.\nexport function createTab(element_id, label) {\n const fixed_elements = document.getElementById(\"fixed-elements\")\n const panel_name = `fixed-element-${element_id}`\n\n const tab = `<sl-tab slot=\"nav\" panel=\"${panel_name}\">${label}</sl-tab>`\n const panel = `<sl-tab-panel name=\"${panel_name}\" style=\"--padding: 0\" />`\n\n fixed_elements.innerHTML += tab + panel\n\n window.requestAnimationFrame(function () {\n fixed_elements.show(panel_name)\n })\n}\n\nexport function removeTab(element_id) {\n const fixed_elements = document.getElementById(\"fixed-elements\")\n const panel_name = `fixed-element-${element_id}`\n\n fixed_elements.querySelector(`sl-tab[panel=\"${panel_name}\"]`).remove()\n fixed_elements.querySelector(`sl-tab-panel[name=\"${panel_name}\"]`).remove()\n\n fixed_elements.show(\"main-content-elements\")\n}\n","import { createHtmlElement } from \"alchemy_admin/utils/dom_helpers\"\n\nfunction build(message, flashType) {\n const flashNotices = document.getElementById(\"flash_notices\")\n const flashMessage = createHtmlElement(`\n <alchemy-message type=\"${flashType}\" dismissable>\n ${message}\n </alchemy-message>\n `)\n flashNotices.append(flashMessage)\n}\n\nexport function growl(message, style = \"notice\") {\n build(message, style)\n}\n","import { translate } from \"alchemy_admin/i18n\"\nimport { Dialog } from \"alchemy_admin/dialog\"\n\n// Matches a URL fragment (#anchor) at the end of a string.\n// Covers RFC 3986 unreserved characters (ALPHA, DIGIT, \"-\", \".\", \"_\", \"~\")\n// which are the characters valid in URL fragments and common in DOM element IDs.\nconst ANCHOR_REGEX = /#[\\w.~-]+$/\n\n// Represents the link Dialog that appears, if a user clicks the link buttons\n// in TinyMCE or on an Ingredient that has links enabled (e.g. Picture)\n//\nexport class LinkDialog extends Dialog {\n #onCreateLink\n\n constructor(link) {\n const url = new URL(Alchemy.routes.link_admin_pages_path, window.location)\n const parameterMapping = {\n url: link.url,\n selected_tab: link.type,\n link_title: link.title,\n link_target: link.target\n }\n\n // searchParams.set would also add undefined values\n Object.keys(parameterMapping).forEach((key) => {\n if (parameterMapping[key]) {\n url.searchParams.set(key, parameterMapping[key])\n }\n })\n\n super(url.href, {\n size: \"600x320\",\n title: translate(\"Link\")\n })\n }\n\n /**\n * Called from Dialog class after the url was loaded\n */\n replace(data) {\n // let Dialog class handle the content replacement\n super.replace(data)\n this.#attachEvents()\n }\n\n /**\n * make the open method a promise\n * maybe in a future version the whole Dialog will respond with a promise result if the dialog is closing\n * @returns {Promise<unknown>}\n */\n open() {\n super.open()\n return new Promise((resolve) => (this.#onCreateLink = resolve))\n }\n\n /**\n * Attaches click events to forms in the link dialog.\n */\n #attachEvents() {\n // enable the dom selection in internal link tab\n const internalForm = document.querySelector(\n '[data-link-form-type=\"internal\"]'\n )\n const attachmentSelect = document.querySelector(\n '[data-link-form-type=\"file\"] alchemy-attachment-select'\n )\n\n internalForm.addEventListener(\"Alchemy.RemoteSelect.Change\", (e) => {\n this.#updatePage(e.detail.added)\n })\n\n attachmentSelect.addEventListener(\"Alchemy.RemoteSelect.Change\", (e) => {\n const attachment = e.detail.added\n document.getElementById(\"file_link\").value = attachment\n ? attachment.url\n : \"\"\n })\n\n document.querySelectorAll(\"[data-link-form-type]\").forEach((form) => {\n form.addEventListener(\"submit\", (e) => {\n e.preventDefault()\n this.#submitForm(e.target.dataset.linkFormType)\n })\n })\n }\n\n /**\n * update page select and set anchor select\n * @param page\n */\n #updatePage(page = null) {\n const internalLink = document.getElementById(\"internal_link\")\n const domIdSelect = document.querySelector(\n '[data-link-form-type=\"internal\"] alchemy-dom-id-api-select'\n )\n\n internalLink.value = page ? page.url_path : \"\"\n domIdSelect.page = page ? page.id : undefined\n }\n\n /**\n * submit the form itself\n * @param linkType\n */\n #submitForm(linkType) {\n const elementAnchor = document.getElementById(\"element_anchor\")\n let url = document.getElementById(`${linkType}_link`).value\n\n if (linkType === \"internal\" && elementAnchor.value !== \"\") {\n // remove possible fragments on the url and attach the fragment (which contains the #)\n url = url.replace(ANCHOR_REGEX, \"\") + elementAnchor.value\n } else if (linkType === \"external\" && !url.match(Alchemy.link_url_regexp)) {\n // show validation error and prevent link creation\n this.#showValidationError()\n return\n }\n\n // Create the link\n this.#onCreateLink({\n url: url.trim(),\n title: document.getElementById(`${linkType}_link_title`).value,\n target: document.getElementById(`${linkType}_link_target`)?.value,\n type: linkType\n })\n this.close()\n }\n\n /**\n * Shows validation errors\n */\n #showValidationError() {\n const errors = document.getElementById(\"errors\")\n errors.querySelector(\"ul\").innerHTML =\n `<li>${Alchemy.t(\"url_validation_failed\")}</li>`\n errors.style.display = \"block\"\n }\n}\n","import { growl } from \"alchemy_admin/growler\"\nimport { translate } from \"alchemy_admin/i18n\"\n\nclass PreviewWindow extends HTMLIFrameElement {\n #afterLoad\n #reloadIcon\n #loadTimeout\n\n handleEvent(evt) {\n if (evt.type === \"load\") {\n this.#clearLoadTimeout()\n this.#stopSpinner()\n this.#afterLoad?.call(this, evt)\n }\n }\n\n #onPreviewReady = (event) => {\n if (event.data.message === \"Alchemy.previewReady\") {\n this.#clearLoadTimeout()\n this.#stopSpinner()\n this.#afterLoad?.call(this, event)\n }\n }\n\n connectedCallback() {\n let url = this.url\n\n this.addEventListener(\"load\", this)\n this.#attachEvents()\n window.addEventListener(\"message\", this.#onPreviewReady)\n\n if (window.localStorage.getItem(\"alchemy-preview-url\")) {\n url = window.localStorage.getItem(\"alchemy-preview-url\")\n this.previewUrlSelect.value = url\n }\n\n this.refresh(url)\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"load\", this)\n key.unbind(\"alt+r\")\n window.removeEventListener(\"message\", this.#onPreviewReady)\n }\n\n postMessage(data) {\n this.contentWindow.postMessage(data, \"*\")\n }\n\n resize(width) {\n this.style.width = `${width}px`\n }\n\n refresh(url) {\n this.#startSpinner()\n\n if (url) {\n this.src = url\n } else {\n this.src = this.url\n }\n\n // Set 5s timeout as fallback - if iframe doesn't load, stop spinner anyway\n this.#clearLoadTimeout()\n this.#loadTimeout = setTimeout(() => {\n this.#stopSpinner()\n growl(translate(\"Preview failed to load\"), \"warning\")\n }, 5000)\n\n return new Promise((resolve) => {\n this.#afterLoad = resolve\n })\n }\n\n set isDragged(dragged) {\n this.style.transitionProperty = dragged ? \"none\" : null\n this.style.pointerEvents = dragged ? \"none\" : null\n }\n\n #attachEvents() {\n this.reloadButton?.addEventListener(\"click\", (evt) => {\n evt.preventDefault()\n this.refresh()\n })\n\n key(\"alt+r\", () => this.refresh())\n\n this.sizeSelect.addEventListener(\"change\", (evt) => {\n const select = evt.target\n const width = select.value\n\n if (width === \"\") {\n this.style.width = null\n } else {\n this.resize(width)\n }\n })\n\n this.previewUrlSelect?.addEventListener(\"change\", (evt) => {\n const url = evt.target.value\n window.localStorage.setItem(\"alchemy-preview-url\", url)\n this.refresh(url)\n })\n }\n\n #startSpinner() {\n // Only save the reload icon if we're not already showing a spinner\n if (!this.reloadButton.innerHTML.includes(\"alchemy-spinner\")) {\n this.#reloadIcon = this.reloadButton.innerHTML\n }\n this.reloadButton.innerHTML = `<alchemy-spinner size=\"small\"></alchemy-spinner>`\n }\n\n #stopSpinner() {\n this.reloadButton.innerHTML = this.#reloadIcon\n }\n\n #clearLoadTimeout() {\n if (this.#loadTimeout) {\n clearTimeout(this.#loadTimeout)\n this.#loadTimeout = null\n }\n }\n\n get url() {\n return this.getAttribute(\"url\")\n }\n\n get sizeSelect() {\n return document.querySelector(\"select#preview_size\")\n }\n\n get previewUrlSelect() {\n return document.querySelector(\"select#preview_url\")\n }\n\n get reloadButton() {\n return document.querySelector(\"#reload_preview_button\")\n }\n}\n\ncustomElements.define(\"alchemy-preview-window\", PreviewWindow, {\n extends: \"iframe\"\n})\n\nexport function reloadPreview() {\n const previewWindow = document.getElementById(\"alchemy_preview_window\")\n previewWindow.refresh()\n}\n","export default class IngredientAnchorLink {\n static updateIcon(ingredientId, active = false) {\n const ingredientEditor = document.querySelector(\n `[data-ingredient-id=\"${ingredientId}\"]`\n )\n if (ingredientEditor) {\n const icon = ingredientEditor.querySelector(\n \".edit-ingredient-anchor-link alchemy-icon\"\n )\n icon.setAttribute(\"icon-style\", active ? \"fill\" : \"line\")\n }\n }\n}\n","import { reloadPreview } from \"alchemy_admin/components/preview_window\"\nimport { removeTab } from \"alchemy_admin/fixed_elements\"\nimport { closeCurrentDialog } from \"alchemy_admin/dialog\"\nimport IngredientAnchorLink from \"alchemy_admin/ingredient_anchor_link\"\nimport pleaseWaitOverlay from \"alchemy_admin/please_wait_overlay\"\n\nclass Action extends HTMLElement {\n constructor() {\n super()\n\n // map action names with Javascript functions\n this.actions = {\n // add a intermediate closeCurrentDialog - action\n // this will be gone, if all dialogs are working with a promise and\n // we don't have to implicitly close the dialog\n closeCurrentDialog,\n reloadPreview,\n removeFixedElement: removeTab,\n updateAnchorIcon: IngredientAnchorLink.updateIcon,\n hidePleaseWaitOverlay() {\n pleaseWaitOverlay(false)\n }\n }\n }\n\n connectedCallback() {\n const func = this.actions[this.name]\n\n if (func) {\n func(...this.params)\n } else {\n console.error(`Unknown Alchemy action: ${this.name}`)\n }\n\n this.remove()\n }\n\n get name() {\n return this.getAttribute(\"name\")\n }\n\n get params() {\n if (this.hasAttribute(\"params\")) {\n return JSON.parse(this.getAttribute(\"params\"))\n }\n return []\n }\n}\n\ncustomElements.define(\"alchemy-action\", Action)\n","import { setupSelectLocale } from \"alchemy_admin/i18n\"\n\nexport function hightlightTerm(name, term) {\n return name.replace(new RegExp(term, \"gi\"), (match) => `<em>${match}</em>`)\n}\n\nexport class RemoteSelect extends HTMLElement {\n #select2 = null\n\n async connectedCallback() {\n await setupSelectLocale()\n // Bail out if the element was disconnected while the locale was loading.\n // Otherwise Select2 would leak onto a detached input.\n if (!this.isConnected) return\n\n this.input.classList.add(\"alchemy_selectbox\")\n\n this.#select2 = $(this.input)\n .select2(this.select2Config)\n .on(\"select2-open\", this.#onOpen)\n .on(\"change\", this.#onChange)\n }\n\n disconnectedCallback() {\n if (this.#select2) {\n this.#select2.off(\"select2-open\", this.#onOpen)\n this.#select2.off(\"change\", this.#onChange)\n this.#select2.select2(\"destroy\")\n this.#select2 = null\n }\n }\n\n #onOpen = (evt) => this.onOpen(evt)\n #onChange = (evt) => this.onChange(evt)\n\n /**\n * Optional on change handler called by Select2.\n * @param {Event} event\n */\n onChange(event) {\n // Update selection attribute so re-attaching the select2 component to\n // the same input (e.g. after dragndrop) does not reset the selection.\n if (event.added) {\n this.setAttribute(\"selection\", JSON.stringify(event.added))\n }\n this.dispatchCustomEvent(\"RemoteSelect.Change\", {\n removed: event.removed,\n added: event.added\n })\n }\n\n /**\n * Optional on open handler called by Select2.\n * @param {Event} event\n */\n onOpen(event) {\n // add focus to the search input. Select2 is handling the focus on the first opening,\n // but it does not work the second time. One process in select2 is \"stealing\" the focus\n // if the command is not delayed. It is an intermediate solution until we are going to\n // move away from Select2\n setTimeout(() => {\n document.querySelector(\"#select2-drop .select2-input\").focus()\n }, 100)\n }\n\n /**\n * Dispatches a custom event with given name, namespaced under `Alchemy.`.\n * Subclasses may call this to emit their own events.\n * @param {string} name The name of the custom event\n * @param {object} detail Optional event details\n */\n dispatchCustomEvent(name, detail = {}) {\n this.dispatchEvent(\n new CustomEvent(`Alchemy.${name}`, { bubbles: true, detail })\n )\n }\n\n get allowClear() {\n return this.hasAttribute(\"allow-clear\")\n }\n\n get selection() {\n return this.getAttribute(\"selection\")\n }\n\n get placeholder() {\n return this.getAttribute(\"placeholder\") ?? \"\"\n }\n\n get queryParams() {\n return this.getAttribute(\"query-params\") ?? \"{}\"\n }\n\n get url() {\n return this.getAttribute(\"url\") ?? \"\"\n }\n\n get input() {\n return this.getElementsByTagName(\"input\")[0]\n }\n\n get select2Config() {\n return {\n placeholder: this.placeholder,\n allowClear: this.allowClear,\n initSelection: (_$el, callback) => {\n if (this.selection) {\n callback(JSON.parse(this.selection))\n }\n },\n ajax: this.ajaxConfig,\n formatSelection: (item) => this._renderResult(item),\n formatResult: (item, _el, query) =>\n this._renderListEntry(item, query.term)\n }\n }\n\n /**\n * Ajax configuration for Select2\n * @returns {object}\n */\n get ajaxConfig() {\n return {\n url: this.url,\n datatype: \"json\",\n quietMillis: 300,\n data: (term, page) => this._searchQuery(term, page),\n results: (response) => this._parseResponse(response)\n }\n }\n\n /**\n * Search query send to server from select2\n * @param {string} term\n * @param {number} page\n * @returns {object}\n * @private\n */\n _searchQuery(term, page) {\n return {\n q: {\n name_cont: term,\n ...JSON.parse(this.queryParams)\n },\n page: page\n }\n }\n\n /**\n * Parses server response into select2 results object\n * @param {object} response\n * @returns {object}\n * @private\n */\n _parseResponse(response) {\n const meta = response.meta\n return {\n results: response.data,\n more: meta.page * meta.per_page < meta.total_count\n }\n }\n\n /**\n * result which is visible if a page was selected\n * @param {object} item\n * @returns {string}\n * @private\n */\n _renderResult() {\n throw new Error(\n \"You need to define a _renderResult function on your sub class!\"\n )\n }\n\n /**\n * html template for each list entry\n * @param {object} item\n * @param {string} term\n * @returns {string}\n * @private\n */\n _renderListEntry() {\n throw new Error(\n \"You need to define a _renderListEntry function on your sub class!\"\n )\n }\n\n /**\n * hightlighted search term\n * @param {string} name\n * @param {string} term\n * @returns {string}\n * @private\n */\n _hightlightTerm(name, term) {\n return hightlightTerm(name, term)\n }\n}\n","import { RemoteSelect } from \"alchemy_admin/components/remote_select\"\n\nclass AttachmentSelect extends RemoteSelect {\n _renderResult(item) {\n return this._renderListEntry(item)\n }\n\n /**\n * html template for each list entry\n * @param {object} page\n * @param {string} term\n * @returns {string}\n * @private\n */\n _renderListEntry(attachment, term) {\n return `\n <div class=\"attachment-select--attachment\">\n <alchemy-icon name=\"${attachment.icon_css_class}\"></alchemy-icon>\n <span class=\"attachment-select--attachment-name\">${this._hightlightTerm(attachment.name, term)}</span>\n </div>\n `\n }\n}\n\ncustomElements.define(\"alchemy-attachment-select\", AttachmentSelect)\n","// Dispatch a submit event on change of input or select elements\n// contained in a form, so that Turbo can submit the form.\nclass AutoSubmit extends HTMLElement {\n connectedCallback() {\n // Still using jQuery here, because select2 does not emit\n // the event from the original select element.\n $(this).on(\"change\", this.#onChange)\n }\n\n disconnectedCallback() {\n $(this).off(\"change\", this.#onChange)\n }\n\n #onChange = (event) => {\n // We need to dispatch a submit event, so that Turbo that listens\n // to it submits the search form us.\n const submitEvent = new Event(\"submit\", {\n bubbles: true,\n cancelable: true\n })\n event.target.form.dispatchEvent(submitEvent)\n return false\n }\n}\n\ncustomElements.define(\"alchemy-auto-submit\", AutoSubmit)\n","import Spinner from \"alchemy_admin/spinner\"\n\nclass Button extends HTMLButtonElement {\n connectedCallback() {\n if (this.form) {\n this.form.addEventListener(\"submit\", this)\n\n if (this.form.dataset.remote == \"true\") {\n this.form.addEventListener(\"ajax:complete\", this)\n }\n\n this.form.addEventListener(\"turbo:submit-end\", this)\n } else {\n console.warn(\"No form for button found!\", this)\n }\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"submit\":\n const isDisabled = this.getAttribute(\"disabled\") === \"disabled\"\n\n if (isDisabled) {\n event.preventDefault()\n event.stopPropagation()\n } else {\n this.disable()\n }\n break\n case \"ajax:complete\":\n case \"turbo:submit-end\":\n this.enable()\n break\n }\n }\n\n disable() {\n const spinner = new Spinner(\"small\")\n const rect = this.getBoundingClientRect()\n\n this.dataset.initialButtonText = this.innerHTML\n this.setAttribute(\"disabled\", \"disabled\")\n this.setAttribute(\"tabindex\", \"-1\")\n this.classList.add(\"disabled\")\n this.style.width = `${rect.width}px`\n this.style.height = `${rect.height}px`\n this.innerHTML = \"&nbsp;\"\n\n spinner.spin(this)\n }\n\n enable() {\n this.classList.remove(\"disabled\")\n this.removeAttribute(\"disabled\")\n this.removeAttribute(\"tabindex\")\n this.style.width = null\n this.style.height = null\n this.innerHTML = this.dataset.initialButtonText\n }\n}\n\ncustomElements.define(\"alchemy-button\", Button, { extends: \"button\" })\n","/**\n * Show the character counter below input fields and textareas\n */\nimport { translate } from \"alchemy_admin/i18n\"\n\nclass CharCounter extends HTMLElement {\n connectedCallback() {\n this.translation = translate(\"allowed_chars\", this.maxChars)\n this.formField = this.getFormField()\n\n if (this.formField) {\n this.createDisplayElement()\n this.countCharacters()\n this.formField.addEventListener(\"keyup\", this)\n }\n }\n\n disconnectedCallback() {\n this.formField?.removeEventListener(\"keyup\", this)\n }\n\n handleEvent(event) {\n if (event.type === \"keyup\") this.countCharacters()\n }\n\n getFormField() {\n const formFields = this.querySelectorAll(\"input, textarea\")\n return formFields.length > 0 ? formFields[0] : undefined\n }\n\n createDisplayElement() {\n this.display = this.querySelector(\":scope > .alchemy-char-counter\")\n if (this.display) return\n this.display = document.createElement(\"small\")\n this.display.className = \"alchemy-char-counter\"\n this.formField.after(this.display)\n }\n\n countCharacters() {\n const charLength = this.formField.value.length\n this.display.textContent = `${charLength} ${this.translation}`\n this.display.classList.toggle(\"too-long\", charLength > this.maxChars)\n }\n\n get maxChars() {\n return this.getAttribute(\"max-chars\") ?? 60\n }\n}\n\ncustomElements.define(\"alchemy-char-counter\", CharCounter)\n","import \"clipboard\"\nimport { growl } from \"alchemy_admin/growler\"\n\nclass ClipboardButton extends HTMLElement {\n connectedCallback() {\n this.innerHTML = '<alchemy-icon name=\"clipboard\"></alchemy-icon>'\n\n this.clipboard = new ClipboardJS(this, {\n text: () => {\n return this.getAttribute(\"content\")\n }\n })\n\n this.clipboard.on(\"success\", () => {\n growl(this.getAttribute(\"success-text\"))\n })\n }\n\n disconnectedCallback() {\n this.clipboard.destroy()\n }\n}\n\ncustomElements.define(\"alchemy-clipboard-button\", ClipboardButton)\n","const formatItem = (object) => {\n const optionEl = object.element[0]\n const swatch = optionEl.dataset.swatch || optionEl.value\n const customColor = optionEl.value === \"custom_color\"\n const colorIndicator = customColor\n ? `<alchemy-icon name=\"palette\"></alchemy-icon>`\n : `<span class=\"color-indicator\" style=\"--color: ${swatch}\"></span>`\n\n return `\n <div class=\"select-color-option\">\n ${colorIndicator}\n <span>${object.text}</span>\n </div>`\n}\n\nclass ColorSelect extends HTMLElement {\n #select2 = null\n\n connectedCallback() {\n if (this.select) {\n this.#initializeSelect2()\n this.#select2.on(\"change\", this.#onSelectChange)\n } else {\n this.colorInput?.addEventListener(\"input\", this)\n this.textInput?.addEventListener(\"input\", this)\n this.#toggleColorPicker(true)\n }\n }\n\n handleEvent(event) {\n switch (event.target) {\n case this.colorInput:\n this.textInput.value = this.colorInput.value\n break\n case this.textInput:\n this.colorInput.value = this.textInput.value\n break\n }\n }\n\n disconnectedCallback() {\n this.colorInput?.removeEventListener(\"input\", this)\n this.textInput?.removeEventListener(\"input\", this)\n if (this.#select2) {\n this.#select2.off(\"change\", this.#onSelectChange)\n this.#select2.select2(\"destroy\")\n this.#select2 = null\n }\n }\n\n #onSelectChange = (event) => {\n this.#toggleColorPicker(event.val === \"custom_color\")\n }\n\n #initializeSelect2() {\n this.select.classList.add(\"alchemy_selectbox\")\n const options = {\n minimumResultsForSearch: 10,\n formatResult: formatItem,\n formatSelection: formatItem\n }\n this.#select2 = $(this.select).select2(options)\n }\n\n #toggleColorPicker(enabled = true) {\n this.colorInput.disabled = !enabled\n }\n\n get colorInput() {\n return this.querySelector(\"input[type='color']\")\n }\n\n get textInput() {\n return this.querySelector(\"input[type='text']\")\n }\n\n get select() {\n return this.querySelector(\"select\")\n }\n}\n\ncustomElements.define(\"alchemy-color-select\", ColorSelect)\n","import { translate, currentLocale } from \"alchemy_admin/i18n\"\nimport flatpickr from \"flatpickr\"\n\nconst locale = currentLocale()\n\nclass Datepicker extends HTMLElement {\n // Load the locales for flatpickr before setting it up.\n async connectedCallback() {\n // English is the default locale for flatpickr, so we don't need to load it\n if (locale !== \"en\") {\n await import(`flatpickr/${locale}.js`)\n }\n // Bail out if the element was disconnected while the locale was loading.\n // Otherwise flatpickr would leak a calendar onto a detached input.\n if (!this.isConnected) return\n\n this.flatpickr = flatpickr(this.inputField, this.flatpickrOptions)\n }\n\n disconnectedCallback() {\n this.flatpickr?.destroy()\n }\n\n get flatpickrOptions() {\n const enableTime = /time/.test(this.inputType)\n const options = {\n // alchemy_i18n supports `zh_CN` etc., but flatpickr only has two-letter codes (`zh`)\n locale: locale.slice(0, 2),\n altInput: true,\n altFormat: translate(`formats.${this.inputType}`),\n altInputClass: \"flatpickr-input\",\n enableTime,\n noCalendar: this.inputType === \"time\",\n time_24hr: translate(\"formats.time_24hr\"),\n onValueUpdate(_selectedDates, _dateStr, instance) {\n instance.element\n .closest(\"alchemy-element-editor\")\n ?.setDirty(this.inputField)\n }\n }\n\n if (enableTime) {\n options.dateFormat = \"Z\"\n }\n\n return options\n }\n\n get inputField() {\n return this.querySelector(\"input\")\n }\n\n get inputType() {\n return this.getAttribute(\"input-type\") || \"date\"\n }\n}\n\ncustomElements.define(\"alchemy-datepicker\", Datepicker)\n","import { Dialog } from \"alchemy_admin/dialog\"\n\nexport class DialogLink extends HTMLAnchorElement {\n connectedCallback() {\n this.addEventListener(\"click\", this)\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"click\", this)\n }\n\n handleEvent(evt) {\n if (!this.disabled) {\n this.openDialog()\n }\n evt.preventDefault()\n }\n\n openDialog() {\n this.dialog = new Dialog(this.getAttribute(\"href\"), this.dialogOptions)\n this.dialog.open()\n }\n\n get dialogOptions() {\n const options = this.dataset.dialogOptions\n ? JSON.parse(this.dataset.dialogOptions)\n : {}\n return options\n }\n\n get disabled() {\n return this.classList.contains(\"disabled\")\n }\n}\n\ncustomElements.define(\"alchemy-dialog-link\", DialogLink, { extends: \"a\" })\n","const JSON_CONTENT_TYPE = \"application/json\"\nconst TURBO_STREAM_CONTENT_TYPE = \"text/vnd.turbo-stream.html\"\n\nfunction isGetRequest(method) {\n return method.toLowerCase() === \"get\"\n}\n\nfunction prepareURL(path, data, method) {\n const url = new URL(window.location.origin + path)\n\n if (data && isGetRequest(method)) {\n url.search = new URLSearchParams(data).toString()\n }\n\n return url.toString()\n}\n\nfunction prepareHeaders(accept) {\n return {\n \"Content-Type\": \"application/json; charset=utf-8\",\n Accept: accept,\n \"X-Requested-With\": \"XMLHttpRequest\",\n \"X-CSRF-Token\": getToken()\n }\n}\n\nfunction prepareOptions(method, data, accept) {\n const headers = prepareHeaders(accept)\n const options = { method, headers }\n\n if (data && !isGetRequest(method)) {\n options.body = JSON.stringify(data)\n }\n\n return options\n}\n\nexport function getToken() {\n const metaTag = document.querySelector('meta[name=\"csrf-token\"]')\n return metaTag.attributes.content.textContent\n}\n\nexport function get(url, params) {\n return ajax(\"GET\", url, params)\n}\n\nexport function patch(url, data, accept) {\n return ajax(\"PATCH\", url, data, accept)\n}\n\nexport function post(url, data, accept = JSON_CONTENT_TYPE) {\n return ajax(\"POST\", url, data, accept)\n}\n\nexport default async function ajax(\n method,\n path,\n data,\n accept = JSON_CONTENT_TYPE\n) {\n const response = await fetch(\n prepareURL(path, data, method),\n prepareOptions(method, data, accept)\n )\n const contentType = response.headers.get(\"content-type\")\n const isJson = contentType?.includes(JSON_CONTENT_TYPE)\n const isTurboStream = contentType?.includes(TURBO_STREAM_CONTENT_TYPE)\n\n let responseData = null\n if (isJson) {\n responseData = await response.json()\n } else if (isTurboStream) {\n responseData = await response.text()\n // Automatically render Turbo Stream if Turbo is available\n if (typeof Turbo !== \"undefined\") {\n Turbo.renderStreamMessage(responseData)\n }\n }\n\n if (response.ok) {\n return { data: responseData, status: response.status }\n } else {\n throw responseData || new Error(\"An error occurred during the transaction\")\n }\n}\n","import { get } from \"alchemy_admin/utils/ajax\"\nimport { translate } from \"alchemy_admin/i18n\"\n\nclass DomIdSelect extends HTMLElement {\n dataItem(hash) {\n return {\n id: `#${hash}`,\n text: `#${hash}`\n }\n }\n\n get selectElement() {\n return this.querySelector('select[is=\"alchemy-select\"]')\n }\n}\n\nclass DomIdApiSelect extends DomIdSelect {\n #pageId = undefined\n\n connectedCallback() {\n this.page = this.getAttribute(\"page\")\n }\n\n async #fetchDomIds() {\n const result = await get(Alchemy.routes.api_ingredients_path, {\n page_id: this.#pageId\n })\n const options = result.data.ingredients\n .filter((ingredient) => ingredient.data?.dom_id)\n .map((ingredient) => this.dataItem(ingredient.data.dom_id))\n const prompt =\n options.length > 0 ? translate(\"None\") : translate(\"No anchors found\")\n\n this.selectElement.setOptions(options, prompt)\n this.selectElement.enable()\n }\n\n #reset() {\n // wait a tick to initialize the alchemy-select\n requestAnimationFrame(() => {\n this.selectElement.disable()\n this.selectElement.setOptions([], translate(\"Select a page first\"))\n })\n }\n\n set page(pageId) {\n this.#pageId = pageId\n pageId ? this.#fetchDomIds() : this.#reset()\n }\n}\n\nclass DomIdPreviewSelect extends DomIdSelect {\n connectedCallback() {\n // wait a tick to let the browser initialize the inner select component\n requestAnimationFrame(() => {\n const frame = document.getElementById(\"alchemy_preview_window\")\n const elements = frame.contentDocument?.querySelectorAll(\"[id]\") || []\n if (elements.length > 0) {\n const options = Array.from(elements).map((element) => {\n return this.dataItem(element.id)\n })\n this.selectElement.setOptions(options, translate(\"None\"))\n }\n })\n }\n}\n\ncustomElements.define(\"alchemy-dom-id-api-select\", DomIdApiSelect)\ncustomElements.define(\"alchemy-dom-id-preview-select\", DomIdPreviewSelect)\n","export class PublishElementButton extends HTMLElement {\n #scheduleButtonVariant\n\n connectedCallback() {\n this.#scheduleButtonVariant = this.scheduleButton.getAttribute(\"variant\")\n this.publishButton.addEventListener(\"click\", this)\n this.dropdown.addEventListener(\"sl-show\", this)\n this.dropdown.addEventListener(\"sl-hide\", this)\n }\n\n disconnectedCallback() {\n this.publishButton.removeEventListener(\"click\", this)\n this.dropdown.removeEventListener(\"sl-show\", this)\n this.dropdown.removeEventListener(\"sl-hide\", this)\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"click\":\n this.publishButton.loading = true\n break\n case \"sl-show\":\n this.scheduleButton.setAttribute(\"variant\", \"primary\")\n break\n case \"sl-hide\":\n this.scheduleButton.setAttribute(\"variant\", this.#scheduleButtonVariant)\n break\n }\n }\n\n get publishButton() {\n return this.querySelector(\"sl-button[type='submit']\")\n }\n\n get dropdown() {\n return this.querySelector(\"sl-dropdown\")\n }\n\n get scheduleButton() {\n return this.querySelector(\"sl-button[slot='trigger']\")\n }\n}\n\ncustomElements.define(\"alchemy-publish-element-button\", PublishElementButton)\n","import ajax from \"alchemy_admin/utils/ajax\"\nimport { removeTab } from \"alchemy_admin/fixed_elements\"\nimport { growl } from \"alchemy_admin/growler\"\nimport { reloadPreview } from \"alchemy_admin/components/preview_window\"\nimport { openConfirmDialog } from \"alchemy_admin/confirm_dialog\"\nimport { dispatchPageDirtyEvent } from \"alchemy_admin/components/element_editor\"\n\nexport class DeleteElementButton extends HTMLElement {\n connectedCallback() {\n this.button?.addEventListener(\"click\", this)\n }\n\n disconnectedCallback() {\n this.button?.removeEventListener(\"click\", this)\n }\n\n async handleEvent() {\n const confirmed = await openConfirmDialog(this.message)\n if (confirmed) {\n const response = await ajax(\"DELETE\", this.url)\n this.#removeElement(response.data)\n }\n }\n\n #removeElement(data) {\n const elementEditor = this.closest(\"alchemy-element-editor\")\n elementEditor.addEventListener(\"transitionend\", () => {\n if (elementEditor.fixed) {\n removeTab(elementEditor.elementId)\n }\n elementEditor.remove()\n })\n elementEditor.classList.add(\"dismiss\")\n growl(data.message)\n if (data.pageHasUnpublishedChanges) {\n dispatchPageDirtyEvent(data)\n }\n reloadPreview()\n }\n\n get url() {\n return this.getAttribute(\"href\")\n }\n\n get message() {\n return this.getAttribute(\"message\")\n }\n\n get button() {\n return this.querySelector(\"button\")\n }\n}\n\ncustomElements.define(\"alchemy-delete-element-button\", DeleteElementButton)\n","import IngredientAnchorLink from \"alchemy_admin/ingredient_anchor_link\"\nimport { post } from \"alchemy_admin/utils/ajax\"\nimport { createHtmlElement } from \"alchemy_admin/utils/dom_helpers\"\nimport { growl } from \"alchemy_admin/growler\"\n\nimport \"alchemy_admin/components/element_editor/publish_element_button\"\nimport \"alchemy_admin/components/element_editor/delete_element_button\"\n\nexport function dispatchPageDirtyEvent(data) {\n document.dispatchEvent(\n new CustomEvent(\"alchemy:page-dirty\", {\n detail: { tooltip: data.publishButtonTooltip }\n })\n )\n}\n\nexport class ElementEditor extends HTMLElement {\n #form = null\n #header = null\n #toggleButton = null\n\n connectedCallback() {\n // The placeholder while be being dragged is empty.\n if (this.classList.contains(\"ui-sortable-placeholder\")) {\n return\n }\n\n // Add event listeners\n this.addEventListener(\"click\", this)\n // Triggered by child elements\n this.addEventListener(\"alchemy:element-update-title\", this)\n // We use of @rails/ujs for Rails remote forms\n this.addEventListener(\"ajax:complete\", this)\n\n // Dirty observer still needs to be jQuery\n // in order to support select2.\n this.#form = this.form\n if (this.#form) {\n $(this.#form).on(\"change\", this.onChange)\n }\n\n this.#header = this.header\n this.#header?.addEventListener(\"dblclick\", this.#onHeaderDblclick)\n\n this.#toggleButton = this.toggleButton\n this.#toggleButton?.addEventListener(\"click\", this.#onToggleClick)\n\n // When newly created, focus the element and refresh the preview\n if (this.hasAttribute(\"created\")) {\n this.focusElement()\n this.previewWindow?.refresh().then(() => {\n this.focusElementPreview()\n })\n this.removeAttribute(\"created\")\n }\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"click\", this)\n this.removeEventListener(\"alchemy:element-update-title\", this)\n this.removeEventListener(\"ajax:complete\", this)\n if (this.#form) {\n $(this.#form).off(\"change\", this.onChange)\n this.#form = null\n }\n this.#header?.removeEventListener(\"dblclick\", this.#onHeaderDblclick)\n this.#header = null\n this.#toggleButton?.removeEventListener(\"click\", this.#onToggleClick)\n this.#toggleButton = null\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"click\":\n const elementEditor = event.target.closest(\"alchemy-element-editor\")\n if (elementEditor === this) {\n this.onClickElement()\n }\n break\n case \"ajax:complete\":\n if (event.target === this.body) {\n const xhr = event.detail[0]\n event.stopPropagation()\n this.onSaveElement(xhr)\n }\n break\n case \"alchemy:element-update-title\":\n if (!this.hasEditors && event.target == this.firstChild) {\n this.setTitle(event.detail.title)\n }\n break\n }\n }\n\n onChange = (event) => {\n const target = event.target\n // SortableJS fires a native change event :/\n // and we do not want to set the element editor dirty\n // when this happens\n if (target.classList.contains(\"nested-elements\")) {\n return\n }\n this.setDirty(target)\n event.stopPropagation()\n return false\n }\n\n /**\n * Scrolls to and highlights element\n * Expands if collapsed\n * Also chooses the right fixed elements tab, if necessary.\n * Can be triggered through custom event 'FocusElementEditor.Alchemy'\n * Used by the elements on click events in the preview frame.\n */\n async focusElement() {\n // Select tab if necessary\n if (document.querySelector(\"#fixed-elements\")) {\n await this.selectTabForElement()\n }\n // Expand if necessary\n await this.expand()\n this.selectElement(true)\n }\n\n focusElementPreview() {\n this.previewWindow?.postMessage({\n message: \"Alchemy.focusElement\",\n element_id: this.elementId\n })\n }\n\n onClickElement() {\n this.selectElement()\n this.focusElementPreview()\n }\n\n /**\n * Sets the element to saved state\n * Updates title\n * JS event bubbling will also update the parents element quote.\n * Shows error messages if ingredient validations fail\n * @argument {XMLHttpRequest} xhr\n */\n onSaveElement(xhr) {\n const data = JSON.parse(xhr.responseText)\n // Reset errors that might be visible from last save attempt\n this.setClean()\n // If validation failed\n if (xhr.status === 422) {\n const warning = data.warning\n // Create error messages\n // Mark ingredients as failed\n data.ingredientsWithErrors.forEach((ingredient) => {\n const ingredientEditor = this.querySelector(\n `[data-ingredient-id=\"${ingredient.id}\"]`\n )\n const errorDisplay = createHtmlElement(\n `<small class=\"error\">${ingredient.errorMessage}</small>`\n )\n ingredientEditor?.appendChild(errorDisplay)\n ingredientEditor?.classList.add(\"validation_failed\")\n })\n // Show message\n growl(warning, \"warn\")\n this.elementErrors.classList.remove(\"hidden\")\n } else {\n growl(data.notice)\n this.previewWindow?.refresh().then(() => {\n this.focusElementPreview()\n })\n this.updateTitle(data.previewText)\n data.ingredientAnchors.forEach((anchor) => {\n IngredientAnchorLink.updateIcon(anchor.ingredientId, anchor.active)\n })\n if (data.pageHasUnpublishedChanges) {\n dispatchPageDirtyEvent(data)\n }\n }\n }\n\n /**\n * Smoothly scrolls to element\n */\n scrollToElement() {\n // The timeout gives the browser some time to calculate the position\n // of nested elements correctly\n setTimeout(() => {\n this.scrollIntoView({\n behavior: \"smooth\"\n })\n }, 50)\n }\n\n /**\n * Highlight element and optionally scroll into view\n * @param {boolean} scroll smoothly scroll element into view. Default (false)\n */\n selectElement(scroll = false) {\n document\n .querySelectorAll(\"alchemy-element-editor.selected\")\n .forEach((el) => {\n el.classList.remove(\"selected\")\n })\n window.requestAnimationFrame(() => {\n this.classList.add(\"selected\")\n })\n if (scroll) this.scrollToElement()\n }\n\n /**\n * Selects tab for given element\n * Resolves the promise if this is done.\n * @returns {Promise}\n */\n selectTabForElement() {\n return new Promise((resolve, reject) => {\n const tabs = document.querySelector(\"#fixed-elements\")\n const panel = this.closest(\"sl-tab-panel\")\n if (tabs && panel) {\n tabs.show(panel.getAttribute(\"name\"))\n resolve()\n } else {\n reject(new Error(\"No tabs present\"))\n }\n })\n }\n\n /**\n * Sets the element into clean (safed) state\n */\n setClean() {\n this.dirty = false\n window.onbeforeunload = null\n this.elementErrors.classList.add(\"hidden\")\n\n if (this.hasEditors) {\n this.body.querySelectorAll(\".ingredient-editor\").forEach((el) => {\n el.classList.remove(\"dirty\", \"validation_failed\")\n el.querySelectorAll(\"small.error\").forEach((e) => e.remove())\n })\n }\n }\n\n /**\n * Sets the element into dirty (unsafed) state\n * @param {HTMLElement} editor\n */\n setDirty(editor) {\n if (this.hasEditors) {\n this.dirty = true\n\n if (!window.onbeforeunload) {\n window.onbeforeunload = (event) => event.preventDefault()\n }\n\n editor?.closest(\".ingredient-editor\")?.classList.add(\"dirty\")\n }\n }\n\n /**\n * Sets the title quote\n * @param {string} title\n */\n setTitle(title) {\n const quote = this.querySelector(\".element-header .preview_text_quote\")\n quote.textContent = title\n }\n\n /**\n * Expands or collapses element editor\n * If the element is dirty (has unsaved changes) it displays a confirm first.\n */\n async toggle() {\n if (this.collapsed) {\n await this.expand()\n } else {\n await this.collapse()\n }\n }\n\n /**\n * Collapses the element editor and persists the state on the server\n * @returns {Promise}\n */\n collapse() {\n if (this.collapsed || this.compact || this.fixed) {\n return Promise.resolve(\"Element is already collapsed.\")\n }\n\n const spinner = new Alchemy.Spinner(\"small\")\n spinner.spin(this.toggleButton)\n this.toggleIcon?.classList?.add(\"hidden\")\n return post(Alchemy.routes.collapse_admin_element_path(this.elementId))\n .then((response) => {\n const data = response.data\n\n this.collapsed = true\n this.toggleButton?.setAttribute(\"title\", data.title)\n\n // Collapse all nested elements if necessarry\n if (data.nestedElementIds.length) {\n const selector = data.nestedElementIds\n .map((id) => `#element_${id}`)\n .join(\", \")\n this.querySelectorAll(selector).forEach((nestedElement) => {\n nestedElement.collapsed = true\n nestedElement.toggleButton?.setAttribute(\"title\", data.title)\n })\n }\n })\n .catch((error) => {\n growl(error.message, \"error\")\n console.error(error)\n })\n .finally(() => {\n this.toggleIcon?.classList?.remove(\"hidden\")\n spinner.stop()\n })\n }\n\n /**\n * Collapses the element editor and persists the state on the server\n * @* @returns {Promise}\n */\n expand() {\n if (this.expanded && !this.compact) {\n return Promise.resolve(\"Element is already expanded.\")\n }\n\n if (this.compact && this.parentElementEditor) {\n return this.parentElementEditor.expand()\n } else {\n const spinner = new Alchemy.Spinner(\"small\")\n spinner.spin(this.toggleButton)\n this.toggleIcon?.classList.add(\"hidden\")\n\n return new Promise((resolve, reject) => {\n post(Alchemy.routes.expand_admin_element_path(this.elementId))\n .then((response) => {\n const data = response.data\n\n // First expand all parent elements if necessary\n if (data.parentElementIds.length) {\n const selector = data.parentElementIds\n .map((id) => `#element_${id}`)\n .join(\", \")\n document.querySelectorAll(selector).forEach((parentElement) => {\n parentElement.collapsed = false\n parentElement.toggleButton?.setAttribute(\"title\", data.title)\n })\n }\n // Finally expand ourselve\n this.collapsed = false\n this.toggleButton?.setAttribute(\"title\", data.title)\n // Resolve the promise that scrolls to the element very last\n resolve()\n })\n .catch((error) => {\n growl(error.message, \"error\")\n console.error(error)\n reject(error)\n })\n .finally(() => {\n this.toggleIcon?.classList?.remove(\"hidden\")\n spinner.stop()\n })\n })\n }\n }\n\n /**\n * Updates the quote in the element header and dispatches event\n * to parent elements\n * @param {string} title\n */\n updateTitle(title) {\n this.setTitle(title)\n this.dispatchEvent(\n new CustomEvent(\"alchemy:element-update-title\", {\n bubbles: true,\n detail: { title }\n })\n )\n }\n\n /**\n * Sets element published or hidden\n * @param {boolean}\n */\n set published(isPublished) {\n if (isPublished) {\n this.classList.remove(\"element-hidden\")\n } else {\n this.classList.add(\"element-hidden\")\n }\n }\n\n /**\n * Is element published or hidden\n * @returns {boolean}\n */\n get published() {\n return !this.classList.contains(\"hidden\")\n }\n\n /**\n * @returns {boolean}\n */\n get compact() {\n return this.getAttribute(\"compact\") !== null\n }\n\n /**\n * @returns {boolean}\n */\n get fixed() {\n return this.getAttribute(\"fixed\") !== null\n }\n\n /**\n * @param {boolean} value\n */\n set collapsed(value) {\n this.classList.toggle(\"folded\", value)\n this.classList.toggle(\"expanded\", !value)\n this.toggleIcon &&\n (this.toggleIcon.name = value ? \"arrow-left-s\" : \"arrow-down-s\")\n }\n\n /**\n * @returns {boolean}\n */\n get collapsed() {\n return this.classList.contains(\"folded\")\n }\n\n /**\n * @returns {boolean}\n */\n get expanded() {\n return !this.collapsed\n }\n\n /**\n * Toggles the dirty class\n *\n * @param {boolean} value\n */\n set dirty(value) {\n this.classList.toggle(\"dirty\", value)\n }\n\n /**\n * Returns the dirty state of this element\n *\n * @returns {boolean}\n */\n get dirty() {\n return this.classList.contains(\"dirty\")\n }\n\n /**\n * Returns the element header\n *\n * @returns {HTMLElement|undefined}\n */\n get header() {\n return this.querySelector(`.element-header`)\n }\n\n /**\n * Returns the immediate body container of this element if present\n *\n * Makes sure it does not return a nested elements body\n * by scoping the selector to this elements id.\n *\n * @returns {HTMLElement|undefined}\n */\n get body() {\n return this.querySelector(this.bodySelector)\n }\n\n get bodySelector() {\n return `#${this.id} > .element-body`\n }\n\n /**\n * Returns the immediate footer container of this element if present\n *\n * Makes sure it does not return a nested elements footer\n * by scoping the selector to this elements id.\n *\n * @returns {HTMLElement|undefined}\n */\n get footer() {\n return this.querySelector(`#${this.id} > .element-footer`)\n }\n\n /**\n * The collapse/expand toggle button\n *\n * @returns {HTMLButtonElement|undefined}\n */\n get toggleButton() {\n return this.querySelector(\".element-toggle\")\n }\n\n /**\n * The collapse/expand toggle buttons icon\n *\n * @returns {HTMLElement|undefined}\n */\n get toggleIcon() {\n return this.toggleButton?.querySelector(\"alchemy-icon\")\n }\n\n /**\n * The validation messages list container\n *\n * @returns {HTMLElement}\n */\n get elementErrors() {\n return this.body.querySelector(\".element_errors\")\n }\n\n /**\n * The element database id\n *\n * @returns {string}\n */\n get elementId() {\n return this.dataset.elementId\n }\n\n /**\n * The element defintion name\n *\n * @returns {string}\n */\n get elementName() {\n return this.dataset.elementName\n }\n\n /**\n * Does this element have ingredient editor fields?\n *\n * @returns {boolean}\n */\n get hasEditors() {\n return !!this.body?.querySelector(\".element-ingredient-editors\")\n }\n\n /**\n * Does this element have nested elements?\n *\n * @returns {boolean}\n */\n get hasChildren() {\n return !!this.querySelector(\".nested-elements\")\n }\n\n /**\n * The first child element editor if present\n *\n * @returns {HTMLButtonElement|undefined}\n */\n get firstChild() {\n return this.querySelector(\"alchemy-element-editor\")\n }\n\n /**\n * The form element if present\n *\n * @returns {HTMLFormElement|undefined}\n */\n get form() {\n return this.querySelector(\"form.element-body\")\n }\n\n /**\n * The parent element editor if present\n *\n * @returns {ElementEditor|undefined}\n */\n get parentElementEditor() {\n return this.parentElement?.closest(\"alchemy-element-editor\")\n }\n\n get previewWindow() {\n return document.getElementById(\"alchemy_preview_window\")\n }\n\n #onHeaderDblclick = () => {\n this.toggle()\n }\n\n #onToggleClick = (evt) => {\n const elementEditor = evt.target.closest(\"alchemy-element-editor\")\n if (elementEditor === this) {\n this.toggle()\n }\n }\n}\n\ncustomElements.define(\"alchemy-element-editor\", ElementEditor)\n","import { hightlightTerm } from \"alchemy_admin/components/remote_select\"\n\nconst formatSelection = (option) => {\n return `\n <div class=\"element-select-name\">\n ${option.icon}<span>${option.text}</span>\n </div>\n `\n}\n\nconst formatItem = (icon, text, hint) => {\n const description = hint\n ? `<div class=\"element-select-description\">${hint}</div>`\n : \"\"\n return `\n <div class=\"element-select-item\">\n ${formatSelection({ icon, text })}\n ${description}\n </div>\n `\n}\n\nclass ElementSelect extends HTMLElement {\n #select2 = null\n\n connectedCallback() {\n const results = this.options\n const options = {\n minimumResultsForSearch: 3,\n dropdownAutoWidth: true,\n data() {\n return { results }\n },\n formatResult: (option, _el, search) => {\n let text\n\n if (option.id === \"\") return option.text\n if (search.term !== \"\") {\n text = hightlightTerm(option.text, search.term)\n } else {\n text = option.text\n }\n\n return formatItem(option.icon, text, option.hint)\n },\n formatSelection,\n placeholder: this.placeholder\n }\n this.#select2 = $(this.inputField).select2(options)\n }\n\n disconnectedCallback() {\n this.#select2?.select2(\"destroy\")\n this.#select2 = null\n }\n\n get options() {\n return JSON.parse(this.getAttribute(\"options\"))\n }\n\n get placeholder() {\n return this.getAttribute(\"placeholder\")\n }\n\n get inputField() {\n return this.querySelector(\"input\")\n }\n}\n\ncustomElements.define(\"alchemy-element-select\", ElementSelect)\n","import { ElementEditor } from \"alchemy_admin/components/element_editor\"\n\nclass ElementsWindow extends HTMLElement {\n #visible = true\n #turboFrame = null\n\n connectedCallback() {\n this.toggleButton?.addEventListener(\"click\", this.#onToggleClick)\n this.collapseButton?.addEventListener(\"click\", this.#onCollapseClick)\n window.addEventListener(\"message\", this.#onWindowMessage)\n document.body.addEventListener(\"click\", this.#onBodyClick)\n if (window.location.hash) {\n this.focusElementEditor(window.location.hash)\n }\n this.resize()\n }\n\n disconnectedCallback() {\n this.toggleButton?.removeEventListener(\"click\", this.#onToggleClick)\n this.collapseButton?.removeEventListener(\"click\", this.#onCollapseClick)\n window.removeEventListener(\"message\", this.#onWindowMessage)\n document.body.removeEventListener(\"click\", this.#onBodyClick)\n }\n\n #onToggleClick = (evt) => {\n evt.preventDefault()\n this.toggle()\n }\n\n #onCollapseClick = () => {\n this.collapseAllElements()\n }\n\n #onWindowMessage = (event) => {\n const data = event.data\n if (data?.message == \"Alchemy.focusElementEditor\") {\n const element = document.getElementById(`element_${data.element_id}`)\n this.show()\n element?.focusElement()\n }\n }\n\n #onBodyClick = (evt) => {\n if (!evt.target.closest(\"alchemy-element-editor\")) {\n this.querySelectorAll(\"alchemy-element-editor\").forEach((editor) => {\n editor.classList.remove(\"selected\")\n })\n this.previewWindow?.postMessage({ message: \"Alchemy.blurElements\" })\n }\n }\n\n collapseAllElements() {\n this.querySelectorAll(\n \"alchemy-element-editor:not([compact]):not([fixed])\"\n ).forEach((editor) => editor.collapse())\n }\n\n toggle() {\n this.#visible ? this.hide() : this.show()\n }\n\n show() {\n document.body.classList.add(\"elements-window-visible\")\n this.#visible = true\n this.toggleButton.closest(\"sl-tooltip\").content = Alchemy.t(\"Hide elements\")\n this.toggleButton\n .querySelector(\"alchemy-icon\")\n .setAttribute(\"name\", \"menu-unfold\")\n this.resize()\n }\n\n hide() {\n document.body.classList.remove(\"elements-window-visible\")\n document.body.style.removeProperty(\"--elements-window-width\")\n this.#visible = false\n this.toggleButton.closest(\"sl-tooltip\").content = Alchemy.t(\"Show elements\")\n this.toggleButton\n .querySelector(\"alchemy-icon\")\n .setAttribute(\"name\", \"menu-fold\")\n }\n\n resize(width) {\n if (width === undefined) {\n width = this.widthFromCookie\n }\n\n if (width) {\n document.body.style.setProperty(\"--elements-window-width\", `${width}px`)\n document.cookie = `alchemy-elements-window-width=${width}; SameSite=Lax; Path=/;`\n }\n }\n\n // Focus element editor and element in preview if URL contains hash to element editor.\n // The link is coming from the assignment view when showing assigned files or pictures.\n focusElementEditor(dom_id) {\n const el = document.querySelector(dom_id)\n\n if (el instanceof ElementEditor) {\n el.focusElement() && el.focusElementPreview()\n }\n }\n\n get collapseButton() {\n return this.querySelector(\"#collapse-all-elements-button\")\n }\n\n get toggleButton() {\n return document.querySelector(\"#element_window_button\")\n }\n\n get previewWindow() {\n return document.getElementById(\"alchemy_preview_window\")\n }\n\n get turboFrame() {\n if (!this.#turboFrame) {\n this.#turboFrame = this.closest(\"turbo-frame\")\n }\n return this.#turboFrame\n }\n\n get widthFromCookie() {\n return document.cookie\n .split(\"; \")\n .find((row) => row.startsWith(\"alchemy-elements-window-width=\"))\n ?.split(\"=\")[1]\n }\n\n set isDragged(dragged) {\n this.turboFrame.style.transitionProperty = dragged ? \"none\" : null\n this.turboFrame.style.pointerEvents = dragged ? \"none\" : null\n }\n}\n\ncustomElements.define(\"alchemy-elements-window\", ElementsWindow)\n","class ElementsWindowHandle extends HTMLElement {\n #dragging = false\n #elementsWindow = null\n #previewWindow = null\n\n connectedCallback() {\n this.addEventListener(\"mousedown\", this)\n window.addEventListener(\"mousemove\", this)\n window.addEventListener(\"mouseup\", this)\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"mousedown\", this)\n window.removeEventListener(\"mousemove\", this)\n window.removeEventListener(\"mouseup\", this)\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"mousedown\":\n event.stopPropagation()\n this.onMouseDown()\n break\n case \"mouseup\":\n this.onMouseUp()\n break\n case \"mousemove\":\n if (this.#dragging) {\n this.onDrag(event.pageX)\n }\n break\n }\n }\n\n onMouseDown() {\n this.#dragging = true\n this.elementsWindow.isDragged = true\n this.previewWindow.isDragged = true\n this.classList.add(\"is-dragged\")\n }\n\n onMouseUp() {\n this.#dragging = false\n this.elementsWindow.isDragged = false\n this.previewWindow.isDragged = false\n this.classList.remove(\"is-dragged\")\n }\n\n onDrag(pageX) {\n const elementWindowWidth = window.innerWidth - pageX\n this.elementsWindow.resize(elementWindowWidth)\n }\n\n get elementsWindow() {\n if (!this.#elementsWindow) {\n this.#elementsWindow = document.querySelector(\"alchemy-elements-window\")\n }\n return this.#elementsWindow\n }\n\n get previewWindow() {\n if (!this.#previewWindow) {\n this.#previewWindow = document.getElementById(\"alchemy_preview_window\")\n }\n return this.#previewWindow\n }\n}\n\ncustomElements.define(\"alchemy-elements-window-handle\", ElementsWindowHandle)\n","class FileEditor extends HTMLElement {\n connectedCallback() {\n this.deleteLink = this.querySelector(\".remove_file_link\")\n this.fileIcon = this.querySelector(\".file_icon\")\n this.fileName = this.querySelector(\".file_name\")\n this.formFieldId = this.deleteLink?.dataset.formFieldId\n this.formField = this.querySelector(`#${this.formFieldId}`)\n this.deleteLink?.addEventListener(\"click\", this)\n }\n\n disconnectedCallback() {\n this.deleteLink?.removeEventListener(\"click\", this)\n }\n\n handleEvent(event) {\n if (event.type === \"click\") this.removeFile()\n event.stopPropagation()\n }\n\n removeFile() {\n this.formField.value = \"\"\n this.fileIcon.innerHTML = \"\"\n this.fileName.innerHTML = \"\"\n this.deleteLink?.classList.add(\"hidden\")\n this.closest(\"alchemy-element-editor\").setDirty(this.formField)\n }\n}\n\ncustomElements.define(\"alchemy-file-editor\", FileEditor)\n","const DEFAULT_DEBOUNCE_TIME = 150\n\nclass ListFilter extends HTMLElement {\n #debounceTimer\n #filterField = null\n #clearButton = null\n\n connectedCallback() {\n if (this.hotkey) {\n key(this.hotkey, this.#onHotkey)\n }\n this.#filterField = this.filterField\n this.#filterField.addEventListener(\"keyup\", this.#onKeyup)\n this.#filterField.addEventListener(\"focus\", this.#onFocus)\n\n this.#clearButton = this.clearButton\n this.#clearButton.addEventListener(\"click\", this.#onClearClick)\n\n key(\"esc\", \"list_filter\", this.#onEscape)\n }\n\n disconnectedCallback() {\n clearTimeout(this.#debounceTimer)\n this.#filterField?.removeEventListener(\"keyup\", this.#onKeyup)\n this.#filterField?.removeEventListener(\"focus\", this.#onFocus)\n this.#filterField = null\n this.#clearButton?.removeEventListener(\"click\", this.#onClearClick)\n this.#clearButton = null\n if (this.hotkey) {\n key.unbind(this.hotkey)\n }\n key.unbind(\"esc\", \"list_filter\")\n }\n\n filter(term) {\n if (term === \"\") {\n this.clearButton.style.visibility = \"hidden\"\n }\n\n const matchedItems = []\n const itemsToShow = new Set()\n const lowerTerm = term.toLowerCase()\n\n // First pass: find matching items and mark their ancestors as visible too\n this.items.forEach((item) => {\n const name = item.getAttribute(this.nameAttribute)?.toLowerCase()\n // indexOf is much faster then match()\n if (name.indexOf(lowerTerm) !== -1) {\n matchedItems.push(item)\n itemsToShow.add(item)\n // Mark ancestor items as visible so nested matches stay visible\n let ancestor = item.parentElement?.closest(this.itemsSelector)\n while (ancestor) {\n itemsToShow.add(ancestor)\n ancestor = ancestor.parentElement?.closest(this.itemsSelector)\n }\n }\n })\n\n // Second pass: apply visibility\n this.items.forEach((item) => {\n item.classList.toggle(\"hidden\", !itemsToShow.has(item))\n })\n\n // Scroll into view if only one match\n if (matchedItems.length === 1) {\n matchedItems[0].scrollIntoView({ behavior: \"smooth\", block: \"nearest\" })\n }\n }\n\n clear() {\n this.filterField.value = \"\"\n this.clearButton.style.visibility = \"hidden\"\n this.items.forEach((item) => item.classList.remove(\"hidden\"))\n }\n\n get nameAttribute() {\n return this.getAttribute(\"name-attribute\") || \"name\"\n }\n\n get clearButton() {\n return this.querySelector('button[type=\"button\"]')\n }\n\n get filterField() {\n return this.querySelector('input[type=\"text\"]')\n }\n\n get items() {\n return document.querySelectorAll(this.itemsSelector)\n }\n\n get itemsSelector() {\n return this.getAttribute(\"items-selector\")\n }\n\n get debounceTime() {\n return parseInt(this.getAttribute(\"debounce-time\")) || DEFAULT_DEBOUNCE_TIME\n }\n\n get hotkey() {\n return this.getAttribute(\"hotkey\")\n }\n\n #onHotkey = () => {\n this.filterField.focus()\n return false\n }\n\n #onKeyup = () => {\n clearTimeout(this.#debounceTimer)\n this.#debounceTimer = setTimeout(() => {\n const term = this.filterField.value\n this.clearButton.style.visibility = term ? \"visible\" : \"hidden\"\n this.filter(term)\n }, this.debounceTime)\n }\n\n #onFocus = () => key.setScope(\"list_filter\")\n\n #onClearClick = (e) => {\n e.preventDefault()\n this.clear()\n }\n\n #onEscape = () => {\n this.clear()\n this.filterField.blur()\n }\n}\n\ncustomElements.define(\"alchemy-list-filter\", ListFilter)\n","const DISMISS_DELAY = 5000\n\nclass Message extends HTMLElement {\n #dismissTimeoutId = null\n\n handleEvent(event) {\n if (event.type === \"click\") {\n this.dismiss()\n }\n }\n\n connectedCallback() {\n if (!this.querySelector(\":scope > alchemy-icon\")) {\n const closeIcon =\n this.dismissable && this.type === \"error\"\n ? '<alchemy-icon name=\"close\"></alchemy-icon>'\n : \"\"\n this.insertAdjacentHTML(\n \"afterbegin\",\n `<alchemy-icon name=\"${this.iconName}\"></alchemy-icon>${closeIcon}`\n )\n }\n if (this.dismissable || this.type === \"error\") {\n this.addEventListener(\"click\", this)\n }\n if (this.dismissable && this.type !== \"error\") {\n this.#dismissTimeoutId = setTimeout(() => {\n this.dismiss()\n }, this.dismissDelay)\n }\n }\n\n disconnectedCallback() {\n if (this.#dismissTimeoutId !== null) {\n clearTimeout(this.#dismissTimeoutId)\n this.#dismissTimeoutId = null\n }\n }\n\n dismiss() {\n this.addEventListener(\"transitionend\", () => this.remove())\n this.classList.add(\"dismissed\")\n }\n\n get dismissable() {\n return this.hasAttribute(\"dismissable\")\n }\n\n get icon() {\n return this.getAttribute(\"icon\")\n }\n\n get type() {\n return this.getAttribute(\"type\") || \"notice\"\n }\n\n get dismissDelay() {\n return parseInt(\n this.noticesWrapper?.dataset.autoDismissDelay || DISMISS_DELAY\n )\n }\n\n get iconName() {\n switch (this.icon || this.type) {\n case \"warning\":\n case \"warn\":\n case \"alert\":\n return \"alert\"\n case \"notice\":\n return \"check\"\n case \"info\":\n case \"hint\":\n return \"information\"\n case \"error\":\n return \"bug\"\n default:\n return this.type\n }\n }\n\n get noticesWrapper() {\n return this.closest(\"#flash_notices\")\n }\n}\n\ncustomElements.define(\"alchemy-message\", Message)\n","import { growl } from \"alchemy_admin/growler\"\n\nclass Growl extends HTMLElement {\n connectedCallback() {\n growl(this.message, this.getAttribute(\"type\") || \"notice\")\n this.remove()\n }\n\n get message() {\n return this.getAttribute(\"message\") || this.innerHTML\n }\n}\n\ncustomElements.define(\"alchemy-growl\", Growl)\n","class Icon extends HTMLElement {\n static get observedAttributes() {\n return [\"name\", \"size\", \"icon-style\"]\n }\n\n constructor() {\n super()\n this.spriteUrl = document\n .querySelector('link[rel=\"preload\"][as=\"image\"]')\n .getAttribute(\"href\")\n }\n\n connectedCallback() {\n this.render()\n }\n\n attributeChangedCallback() {\n this.render()\n }\n\n render() {\n const sizeClass = this.size ? ` icon--${this.size}` : \"\"\n this.innerHTML = `<svg class=\"icon${sizeClass}\"><use href=\"${this.spriteUrl}#ri-${this.iconName}${this.style}\" /></svg>`\n }\n\n set name(value) {\n this.setAttribute(\"name\", value)\n }\n\n get iconName() {\n return this.getAttribute(\"name\")\n }\n\n get size() {\n return this.getAttribute(\"size\")\n }\n\n get style() {\n const value = this.getAttribute(\"icon-style\")\n switch (value) {\n case \"none\":\n return \"\"\n case null:\n return \"-line\"\n default:\n return `-${value}`\n }\n }\n}\n\ncustomElements.define(\"alchemy-icon\", Icon)\n","export class IngredientGroup extends HTMLDetailsElement {\n #localStorageKey = \"Alchemy.expanded_ingredient_groups\"\n\n connectedCallback() {\n this.addEventListener(\"toggle\", this)\n\n if (this.isInLocalStorage) {\n this.open = true\n }\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"toggle\", this)\n }\n\n /**\n * Toggle visibility of the ingredient fields in this group\n */\n handleEvent() {\n let expanded_ingredient_groups = this.localStorageItem\n\n if (this.open) {\n this.toggleIcon.name = \"arrow-down-s\"\n if (!this.isInLocalStorage) expanded_ingredient_groups.push(this.id)\n } else {\n this.toggleIcon.name = \"arrow-left-s\"\n expanded_ingredient_groups = expanded_ingredient_groups.filter(\n (value) => value !== this.id\n )\n }\n\n localStorage.setItem(\n this.#localStorageKey,\n JSON.stringify(expanded_ingredient_groups)\n )\n }\n\n get isInLocalStorage() {\n return this.localStorageItem.includes(this.id)\n }\n\n get localStorageItem() {\n const item = localStorage.getItem(this.#localStorageKey)\n\n if (!item) return []\n\n try {\n return JSON.parse(item)\n } catch (error) {\n console.error(error)\n return []\n }\n }\n\n get toggleIcon() {\n return this.querySelector(\"alchemy-icon\")\n }\n}\n\ncustomElements.define(\"alchemy-ingredient-group\", IngredientGroup, {\n extends: \"details\"\n})\n","class LinkButton extends HTMLButtonElement {\n connectedCallback() {\n this.addEventListener(\"click\", this)\n this.classList.add(\"icon_button\")\n // Prevent accidental form submits if this component is wrapped inside a form\n this.setAttribute(\"type\", \"button\")\n this.innerHTML = '<alchemy-icon name=\"link\" icon-style=\"m\"></alchemy-icon>'\n }\n\n handleEvent(event) {\n const dialog = new Alchemy.LinkDialog({\n url: this.linkUrl,\n title: this.linkTitle,\n target: this.linkTarget,\n type: this.linkClass\n })\n dialog.open().then((link) => this.setLink(link))\n event.preventDefault()\n }\n\n setLink(link) {\n if (link.url === \"\") {\n this.classList.remove(\"linked\")\n this.dispatchEvent(new CustomEvent(\"alchemy:unlink\", { bubbles: true }))\n } else {\n this.classList.add(\"linked\")\n this.dispatchEvent(\n new CustomEvent(\"alchemy:link\", {\n bubbles: true,\n detail: link\n })\n )\n }\n }\n\n get linkUrl() {\n return this.linkButtons.linkUrlField.value\n }\n\n get linkTitle() {\n return this.linkButtons.linkTitleField.value\n }\n\n get linkTarget() {\n return this.linkButtons.linkTargetField.value\n }\n\n get linkClass() {\n return this.linkButtons.linkClassField.value\n }\n\n get linkButtons() {\n return this.closest(\"alchemy-link-buttons\")\n }\n}\n\ncustomElements.define(\"alchemy-link-button\", LinkButton, { extends: \"button\" })\n","class UnlinkButton extends HTMLButtonElement {\n connectedCallback() {\n this.addEventListener(\"click\", this)\n this.classList.add(\"icon_button\")\n // Prevent accidental form submits if this component is wrapped inside a form\n this.setAttribute(\"type\", \"button\")\n this.linked = this.linked\n this.innerHTML =\n '<alchemy-icon name=\"link-unlink\" icon-style=\"m\"></alchemy-icon>'\n }\n\n handleEvent(event) {\n if (this.linked) {\n this.linked = false\n this.blur()\n this.dispatchEvent(new CustomEvent(\"alchemy:unlink\", { bubbles: true }))\n }\n event.preventDefault()\n }\n\n set linked(isLinked) {\n if (isLinked) {\n this.classList.replace(\"disabled\", \"linked\")\n this.removeAttribute(\"tabindex\")\n } else {\n this.classList.replace(\"linked\", \"disabled\")\n this.setAttribute(\"tabindex\", \"-1\")\n }\n }\n\n get linked() {\n return this.classList.contains(\"linked\")\n }\n}\n\ncustomElements.define(\"alchemy-unlink-button\", UnlinkButton, {\n extends: \"button\"\n})\n","import \"alchemy_admin/components/link_buttons/link_button\"\nimport \"alchemy_admin/components/link_buttons/unlink_button\"\n\nclass LinkButtons extends HTMLElement {\n connectedCallback() {\n this.addEventListener(\"alchemy:link\", this)\n this.addEventListener(\"alchemy:unlink\", this)\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"alchemy:link\", this)\n this.removeEventListener(\"alchemy:unlink\", this)\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"alchemy:link\":\n this.setLink(event.detail)\n break\n case \"alchemy:unlink\":\n this.removeLink()\n }\n event.stopPropagation()\n }\n\n setLink(data) {\n this.linkUrlField.value = data.url\n this.linkUrlField.dispatchEvent(new Event(\"change\"))\n this.linkTitleField.value = data.title\n this.linkClassField.value = data.type\n this.linkTargetField.value = data.target\n\n this.unlinkButton.linked = true\n this.setElementDirty()\n }\n\n removeLink() {\n this.linkUrlField.value = \"\"\n this.linkUrlField.dispatchEvent(new Event(\"change\"))\n this.linkTitleField.value = \"\"\n this.linkClassField.value = \"\"\n this.linkTargetField.value = \"\"\n\n this.linkButton.classList.remove(\"linked\")\n this.unlinkButton.linked = false\n\n this.setElementDirty()\n }\n\n setElementDirty() {\n this.elementEditor.setDirty(this)\n }\n\n get linkButton() {\n return this.querySelector('[is=\"alchemy-link-button\"]')\n }\n\n get unlinkButton() {\n return this.querySelector('[is=\"alchemy-unlink-button\"]')\n }\n\n get ingredientEditor() {\n const ingredientId = this.dataset.ingredientId\n return this.parentElement.closest(`[data-ingredient-id='${ingredientId}']`)\n }\n\n get elementEditor() {\n return this.closest(\"alchemy-element-editor\")\n }\n\n get linkUrlField() {\n return this.ingredientEditor.querySelector(\"[data-link-value]\")\n }\n\n get linkTitleField() {\n return this.ingredientEditor.querySelector(\"[data-link-title]\")\n }\n\n get linkTargetField() {\n return this.ingredientEditor.querySelector(\"[data-link-target]\")\n }\n\n get linkClassField() {\n return this.ingredientEditor.querySelector(\"[data-link-class]\")\n }\n}\n\ncustomElements.define(\"alchemy-link-buttons\", LinkButtons)\n","export function formatFileSize(bytes) {\n let exponent = bytes === 0 ? 0 : Math.floor(Math.log(bytes) / Math.log(1024))\n\n // prevent format higher than GB\n if (exponent > 3) {\n exponent = 3\n }\n\n let value = (bytes / Math.pow(1024, exponent)).toFixed(2)\n return value + \" \" + [\"B\", \"kB\", \"MB\", \"GB\"][exponent]\n}\n","import { RemoteSelect } from \"alchemy_admin/components/remote_select\"\n\nclass NodeSelect extends RemoteSelect {\n _searchQuery(term, page) {\n return {\n filter: {\n name_or_page_name_cont: term,\n ...JSON.parse(this.queryParams)\n },\n page: page\n }\n }\n\n _renderResult(item) {\n return this._renderListEntry(item)\n }\n\n /**\n * html template for each list entry\n * @param {object} node\n * @param {string} term\n * @returns {string}\n * @private\n */\n _renderListEntry(node, term) {\n const ancestors = node.ancestors.map((a) => a.name)\n const seperator = `<alchemy-icon name=\"arrow-right-s\"></alchemy-icon>`\n\n return `\n <div class=\"node-select--node\">\n <alchemy-icon name=\"menu-2\"></alchemy-icon>\n <div class=\"node-select--node-display_name\">\n <span class=\"node-select--node-ancestors\">\n ${ancestors.length > 0 ? ancestors.join(seperator) + seperator : \"\"}\n </span>\n <span class=\"node-select--node-name\">\n ${this._hightlightTerm(node.name, term)}\n </span>\n </div>\n <div class=\"node-select--node-url\">\n ${node.url || \"\"}\n </div>\n </div>\n `\n }\n}\n\ncustomElements.define(\"alchemy-node-select\", NodeSelect)\n","import { formatFileSize } from \"alchemy_admin/utils/format\"\nimport { translate } from \"alchemy_admin/i18n\"\nimport { growl } from \"alchemy_admin/growler\"\n\nexport class FileUpload extends HTMLElement {\n // public — used by callers (Uploader, Progress, tests)\n file = null\n request = null\n progressEventLoaded = 0\n progressEventTotal = 0\n\n // private — backing state for getters/setters\n #valid = true\n #value = 0\n #status = undefined\n #errorMessage = \"\"\n\n connectedCallback() {\n this.innerHTML = `\n <sl-progress-bar value=\"${this.value}\"></sl-progress-bar>\n <div class=\"description\">\n <span class=\"file-name\">${this.file?.name}</span>\n <span class=\"loaded-size\">${this.loadedSize}</span>\n <span class=\"error-message\">${this.errorMessage}</span>\n </div>\n <sl-tooltip content=\"${translate(\"Abort upload\")}\">\n <button class=\"icon_button\" aria-label=\"${translate(\"Abort upload\")}\">\n <alchemy-icon name=\"close\"></alchemy-icon>\n </button>\n </sl-tooltip>\n `\n\n this.querySelector(\"button\").addEventListener(\"click\", () => this.cancel())\n\n if (this.file?.type.includes(\"image\")) {\n const reader = new FileReader()\n reader.readAsDataURL(this.file)\n reader.addEventListener(\"load\", () => {\n const image = new Image()\n image.src = reader.result\n this.prepend(image)\n })\n }\n }\n\n /**\n * Initialize the component with file and request\n * @param {File} file\n * @param {XMLHttpRequest} request\n */\n initialize(file, request) {\n this.file = file\n this.request = request\n this.progressEventTotal = file ? file.size : 0\n this.status = \"in-progress\"\n\n this.#validateFile()\n this.#addRequestEventListener()\n }\n\n /**\n * cancel the upload\n */\n cancel() {\n if (!this.finished) {\n this.status = \"canceled\"\n this.request?.abort()\n this.dispatchCustomEvent(\"FileUpload.Change\")\n }\n }\n\n /**\n * Dispatches a custom event with given name, namespaced under `Alchemy.`.\n * @param {string} name The name of the custom event\n */\n dispatchCustomEvent(name) {\n this.dispatchEvent(new CustomEvent(`Alchemy.${name}`, { bubbles: true }))\n }\n\n /**\n * validate given file with the `Alchemy.uploader_defaults` - configuration\n */\n #validateFile() {\n const config = Alchemy.uploader_defaults\n const maxFileSize = config.file_size_limit * Math.pow(1024, 2) // in Byte\n let errorMessage = undefined\n\n if (this.file?.size > maxFileSize) {\n errorMessage = translate(\"Uploaded bytes exceed file size\")\n }\n\n const allowedFiletypes = this.file?.type.includes(\"image\")\n ? config.allowed_filetypes.alchemy_pictures\n : config.allowed_filetypes.alchemy_attachments\n\n const isFileFormatSupported =\n allowedFiletypes.includes(\"*\") ||\n allowedFiletypes.includes(\n this.file?.type.replace(/^\\w+\\/(\\w+)(\\+\\w+)?/i, \"$1\")\n )\n\n if (!isFileFormatSupported) {\n errorMessage = translate(\"File type not allowed\")\n }\n\n if (errorMessage) {\n this.valid = false\n this.errorMessage = errorMessage\n }\n }\n\n /**\n * register event listeners to react on request changes\n */\n #addRequestEventListener() {\n // prevent errors if the component will be called without a request - object\n if (!this.request) {\n return\n }\n\n // update the progress bar and currently loaded size information\n this.request.upload.onprogress = (progressEvent) => {\n this.progressEvent = progressEvent\n }\n\n // triggers, when the upload is done\n this.request.onload = () => {\n if (this.request.status < 400) {\n this.status = \"successful\"\n growl(this.responseMessage)\n } else {\n this.status = \"failed\"\n this.errorMessage = this.responseMessage\n }\n this.dispatchCustomEvent(\"FileUpload.Change\")\n }\n\n // catch request errors\n this.request.onerror = () => {\n this.errorMessage = translate(\"An error occurred during the transaction\")\n }\n }\n\n /**\n * @returns {boolean}\n */\n get active() {\n return this.valid && this.status !== \"canceled\"\n }\n\n /**\n * @returns {string}\n */\n get errorMessage() {\n return this.#errorMessage || \"\"\n }\n\n /**\n * @param {string} message\n */\n set errorMessage(message) {\n this.#errorMessage = message\n const errorMessageContainer = this.querySelector(\".error-message\")\n if (errorMessageContainer) {\n errorMessageContainer.textContent = message\n }\n growl(message, \"error\")\n }\n\n /**\n * @returns {boolean}\n */\n get finished() {\n return [\"canceled\", \"successful\", \"failed\"].includes(this.status)\n }\n\n /**\n * format the loaded and total size and present that as a string\n * @returns {string}\n */\n get loadedSize() {\n return `${formatFileSize(this.progressEventLoaded)} / ${formatFileSize(\n this.progressEventTotal\n )}`\n }\n\n /**\n * @returns {HTMLProgressElement|undefined}\n */\n get progressElement() {\n return this.querySelector(\"sl-progress-bar\")\n }\n\n /**\n * @param {ProgressEvent} progressEvent\n */\n set progressEvent(progressEvent) {\n this.progressEventLoaded = progressEvent.loaded\n this.progressEventTotal = progressEvent.total\n\n this.value = Math.round((progressEvent.loaded / progressEvent.total) * 100)\n this.querySelector(\".loaded-size\").textContent = this.loadedSize\n }\n\n /**\n * @returns {string}\n */\n get responseMessage() {\n try {\n const response = JSON.parse(this.request.responseText)\n return response[\"message\"]\n } catch (error) {\n return `${this.request.status}: ${this.request.statusText}`\n }\n }\n\n /**\n * @returns {string}\n */\n get status() {\n return this.#status\n }\n\n /**\n * @param {string} status\n */\n set status(status) {\n this.#status = status\n this.className = status\n\n this.progressElement?.toggleAttribute(\n \"indeterminate\",\n status === \"upload-finished\"\n )\n }\n\n /**\n * @returns {boolean}\n */\n get valid() {\n return this.#valid\n }\n\n /**\n * @param {boolean} isValid\n */\n set valid(isValid) {\n this.#valid = isValid\n this.classList.toggle(\"invalid\", !isValid)\n }\n\n /**\n * get the progress value of the current file\n * @returns {number}\n */\n get value() {\n return this.#value\n }\n\n /**\n * @param {number} value\n */\n set value(value) {\n this.#value = value\n if (this.progressElement) {\n this.progressElement.value = value\n }\n\n if (value === 100) {\n this.status = \"upload-finished\"\n }\n\n this.dispatchCustomEvent(\"FileUpload.Change\")\n }\n}\n\ncustomElements.define(\"alchemy-file-upload\", FileUpload)\n","import { FileUpload } from \"alchemy_admin/components/uploader/file_upload\"\nimport { formatFileSize } from \"alchemy_admin/utils/format\"\nimport { translate } from \"alchemy_admin/i18n\"\n\nconst template = (buttonLabel, fileCount) => `\n <sl-progress-bar value=\"0\"></sl-progress-bar>\n <div class=\"overall-progress-value\">\n <span class=\"value-text\"></span>\n\n <sl-tooltip content=\"${buttonLabel}\">\n <button class=\"icon_button\" aria-label=\"${buttonLabel}\">\n <alchemy-icon name=\"close\"></alchemy-icon>\n </button>\n </sl-tooltip>\n </div>\n <div class=\"single-uploads\" style=\"--progress-columns: ${\n fileCount > 3 ? 3 : fileCount\n }\"></div>\n <div class=\"overall-upload-value value-text\"></div>\n`\n\nexport class Progress extends HTMLElement {\n // public — accessed by Uploader and tests\n fileCount = 0\n\n // private — backing state and internals\n #fileUploads = []\n #buttonLabel = translate(\"Cancel all uploads\")\n #actionButton = null\n #visible = false\n #handleFileChange = () => this.#updateView()\n\n connectedCallback() {\n this.innerHTML = template(this.#buttonLabel, this.fileCount)\n this.visible = true\n\n this.#actionButton = this.querySelector(\"button\")\n this.#actionButton.addEventListener(\"click\", () => {\n if (this.finished) {\n this.onComplete(this.status)\n } else {\n this.cancel()\n }\n })\n\n this.#fileUploads.forEach((fileUpload) => {\n this.querySelector(\".single-uploads\").append(fileUpload)\n })\n\n this.#updateView()\n this.addEventListener(\"Alchemy.FileUpload.Change\", this.#handleFileChange)\n }\n\n disconnectedCallback() {\n this.removeEventListener(\n \"Alchemy.FileUpload.Change\",\n this.#handleFileChange\n )\n }\n\n /**\n * Initialize the component with file uploads\n * @param {FileUpload[]} fileUploads\n */\n initialize(fileUploads = []) {\n this.#fileUploads = fileUploads\n this.fileCount = fileUploads.length\n }\n\n /**\n * cancel requests in all remaining uploads\n */\n cancel() {\n this.#activeUploads().forEach((upload) => {\n upload.cancel()\n })\n this.#setupCloseButton()\n }\n\n /**\n * a complete hook to allow the uploader to react and trigger an event\n * it would be possible to trigger the event here, but the dispatching would happen\n * in the scope of that component and can't be cached o uploader - component level\n */\n onComplete(_status) {}\n\n /**\n * get all active upload components\n * @returns {FileUpload[]}\n */\n #activeUploads() {\n return this.#fileUploads.filter((upload) => upload.active)\n }\n\n /**\n * replace cancel button to be the close button\n */\n #setupCloseButton() {\n this.#buttonLabel = translate(\"Close\")\n this.#actionButton.ariaLabel = this.#buttonLabel\n this.#actionButton.parentElement.content = this.#buttonLabel // update tooltip content\n }\n\n /**\n * @param {string} field\n * @returns {number}\n */\n #sumFileProgresses(field) {\n return this.#activeUploads().reduce(\n (accumulator, upload) => upload[field] + accumulator,\n 0\n )\n }\n\n /**\n * don't render the whole element new, because it would prevent selecting buttons\n */\n #updateView() {\n const status = this.status\n this.className = status\n\n // update progress bar\n this.progressElement.value = this.totalProgress\n this.progressElement.toggleAttribute(\n \"indeterminate\",\n status === \"upload-finished\"\n )\n\n // show progress in file size and percentage\n this.querySelector(`.overall-progress-value > span`).textContent =\n this.overallProgressValue\n this.querySelector(`.overall-upload-value`).textContent =\n this.overallUploadSize\n\n if (this.finished) {\n this.#setupCloseButton()\n this.onComplete(status)\n } else {\n this.visible = true\n }\n }\n\n /**\n * @returns {boolean}\n */\n get finished() {\n return this.#activeUploads().every((entry) => entry.finished)\n }\n\n /**\n * @returns {string}\n */\n get overallUploadSize() {\n const uploadedFileCount = this.#activeUploads().filter(\n (fileProgress) => fileProgress.value >= 100\n ).length\n const overallProgressValue = `${\n this.totalProgress\n }% (${uploadedFileCount} / ${this.#activeUploads().length})`\n\n return `${formatFileSize(\n this.#sumFileProgresses(\"progressEventLoaded\")\n )} / ${formatFileSize(this.#sumFileProgresses(\"progressEventTotal\"))}`\n }\n\n /**\n * @returns {string}\n */\n get overallProgressValue() {\n const uploadedFileCount = this.#activeUploads().filter(\n (fileProgress) => fileProgress.value >= 100\n ).length\n return `${this.totalProgress}% (${uploadedFileCount} / ${\n this.#activeUploads().length\n })`\n }\n\n /**\n * @returns {HTMLProgressElement|undefined}\n */\n get progressElement() {\n return this.querySelector(\"sl-progress-bar\")\n }\n\n /**\n * get status of file progresses and accumulate the overall status\n * @returns {string}\n */\n get status() {\n const uploadsStatuses = this.#activeUploads().map(\n (upload) => upload.className\n )\n\n // mark as failed, if any upload failed\n if (uploadsStatuses.includes(\"failed\")) {\n return \"failed\"\n }\n\n // no active upload means that every upload was canceled\n if (uploadsStatuses.length === 0) {\n return \"canceled\"\n }\n\n // all uploads are successful or upload-finished or in-progress\n if (uploadsStatuses.every((entry) => entry === uploadsStatuses[0])) {\n return uploadsStatuses[0]\n }\n\n return \"in-progress\"\n }\n\n /**\n * @returns {number}\n */\n get totalProgress() {\n const totalSize = this.#activeUploads().reduce(\n (accumulator, upload) => accumulator + upload.file.size,\n 0\n )\n let totalProgress = Math.ceil(\n this.#activeUploads().reduce((accumulator, upload) => {\n const weight = upload.file.size / totalSize\n return upload.value * weight + accumulator\n }, 0)\n )\n // prevent rounding errors\n if (totalProgress > 100) {\n totalProgress = 100\n }\n return totalProgress\n }\n\n /**\n * @returns {boolean}\n */\n get visible() {\n return this.#visible\n }\n\n /**\n * @param {boolean} visible\n */\n set visible(visible) {\n this.classList.toggle(\"visible\", visible)\n this.#visible = visible\n }\n}\n\ncustomElements.define(\"alchemy-upload-progress\", Progress)\n","/**\n * @typedef {object} PersistedFile\n * @property {string} name\n * @property {number} size\n */\nimport { Progress } from \"alchemy_admin/components/uploader/progress\"\nimport { FileUpload } from \"alchemy_admin/components/uploader/file_upload\"\nimport { translate } from \"alchemy_admin/i18n\"\nimport { getToken } from \"alchemy_admin/utils/ajax\"\n\nexport class Uploader extends HTMLElement {\n #dropzoneElement = null\n #isDraggedOver = false\n\n connectedCallback() {\n this.fileInput.addEventListener(\"change\", this.#onFileInputChange)\n if (this.dropzone) {\n this.#setupDropZone()\n }\n this.addEventListener(\"Alchemy.upload.successful\", this)\n }\n\n disconnectedCallback() {\n this.fileInput?.removeEventListener(\"change\", this.#onFileInputChange)\n if (this.#dropzoneElement) {\n this.#dropzoneElement.removeEventListener(\n \"dragleave\",\n this.#onDropzoneDragleave\n )\n this.#dropzoneElement.removeEventListener(\"drop\", this.#onDropzoneDrop)\n this.#dropzoneElement.removeEventListener(\n \"dragover\",\n this.#onDropzoneDragover\n )\n this.#dropzoneElement = null\n }\n }\n\n handleEvent(evt) {\n switch (evt.type) {\n case \"Alchemy.upload.successful\":\n this.#handleUploadComplete()\n break\n }\n }\n\n #onFileInputChange = (event) => {\n this.uploadFiles(Array.from(event.target.files))\n }\n\n #toggleDropzoneClass = (enabled) => {\n if (this.#isDraggedOver !== enabled) {\n this.#isDraggedOver = enabled\n this.#dropzoneElement.classList.toggle(\"dragover\")\n }\n }\n\n #onDropzoneDragleave = () => this.#toggleDropzoneClass(false)\n\n #onDropzoneDrop = async (event) => {\n event.preventDefault()\n this.#toggleDropzoneClass(false)\n\n const files = [...event.dataTransfer.items].map((item) => item.getAsFile())\n\n this.uploadFiles(files)\n }\n\n #onDropzoneDragover = (event) => {\n event.preventDefault() // dragover has to be disabled to use the custom drop event\n this.#toggleDropzoneClass(true)\n }\n\n #handleUploadComplete() {\n setTimeout(() => {\n const url = this.redirectUrl\n const turboFrame = this.closest(\"turbo-frame\")\n this.uploadProgress.visible = false\n\n if (!url) return\n\n if (turboFrame) {\n turboFrame.setAttribute(\"src\", url)\n turboFrame.reload()\n } else {\n Turbo.visit(url)\n }\n }, 750)\n }\n\n /**\n * add dragover class to indicate, if the file is draggable\n * @private\n */\n #setupDropZone() {\n this.#dropzoneElement = document.querySelector(this.dropzone)\n if (!this.#dropzoneElement) return\n\n this.#dropzoneElement.addEventListener(\n \"dragleave\",\n this.#onDropzoneDragleave\n )\n this.#dropzoneElement.addEventListener(\"drop\", this.#onDropzoneDrop)\n this.#dropzoneElement.addEventListener(\"dragover\", this.#onDropzoneDragover)\n }\n\n /**\n * @param {File[]} files\n */\n uploadFiles(files) {\n // prepare file progress bars and server request\n let fileUploadCount = 0\n\n const fileUploads = files.map((file) => {\n const request = new XMLHttpRequest()\n const fileUpload = new FileUpload()\n fileUpload.initialize(file, request)\n\n if (Alchemy.uploader_defaults.upload_limit - 1 < fileUploadCount) {\n fileUpload.valid = false\n fileUpload.errorMessage = translate(\"Maximum number of files exceeded\")\n } else if (fileUpload.valid) {\n fileUploadCount++\n this.#submitFile(request, file)\n }\n\n return fileUpload\n })\n\n this.#createProgress(fileUploads)\n }\n\n /**\n * @param {XMLHttpRequest} request\n * @param {File} file\n * @private\n */\n #submitFile(request, file) {\n const form = this.querySelector(\"form\")\n const formData = new FormData(form)\n formData.set(this.fileInput.name, file)\n request.open(\"POST\", form.action)\n request.setRequestHeader(\"X-CSRF-Token\", getToken())\n request.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\")\n request.setRequestHeader(\"Accept\", \"application/json\")\n request.send(formData)\n }\n\n /**\n * create (and maybe remove the old) progress bar - component\n * @param {FileUpload[]} fileUploads\n * @private\n */\n #createProgress(fileUploads) {\n if (this.uploadProgress) {\n this.uploadProgress.cancel()\n document.body.removeChild(this.uploadProgress)\n }\n this.uploadProgress = new Progress()\n this.uploadProgress.initialize(fileUploads)\n this.uploadProgress.onComplete = (status) => {\n this.dispatchEvent(\n new CustomEvent(`Alchemy.upload.${status}`, { bubbles: true })\n )\n }\n\n document.body.append(this.uploadProgress)\n }\n\n get dropzone() {\n return this.getAttribute(\"dropzone\")\n }\n\n /**\n * @returns {HTMLInputElement}\n */\n get fileInput() {\n return this.querySelector(\"input[type='file']\")\n }\n\n get redirectUrl() {\n return this.getAttribute(\"redirect-url\")\n }\n}\n\ncustomElements.define(\"alchemy-uploader\", Uploader)\n","class Overlay extends HTMLElement {\n connectedCallback() {\n this.innerHTML = `\n <alchemy-spinner></alchemy-spinner>\n <div id=\"overlay_text_box\">\n <span id=\"overlay_text\">${this.getAttribute(\"text\") ?? \"\"}</span>\n </div>\n `\n }\n\n set show(value) {\n this.classList.toggle(\"visible\", value)\n }\n}\n\ncustomElements.define(\"alchemy-overlay\", Overlay)\n","import { patch } from \"alchemy_admin/utils/ajax\"\nimport { growl } from \"alchemy_admin/growler\"\nimport Spinner from \"alchemy_admin/spinner\"\n\nconst BUTTON = \"BUTTON\"\nconst SPAN = \"SPAN\"\n\n/**\n * Custom element for page nodes in the sitemap tree\n * Handles folding/unfolding of page children\n */\nexport class AlchemyPageNode extends HTMLElement {\n connectedCallback() {\n this.pageId = this.getAttribute(\"page-id\")\n this.folded = this.hasAttribute(\"folded\")\n\n this.folderButton?.addEventListener(\"click\", this)\n }\n\n disconnectedCallback() {\n this.folderButton?.removeEventListener(\"click\", this)\n }\n\n async handleEvent(event) {\n if (event.type === \"click\") {\n await this.handleFolderClick(event)\n }\n }\n\n async handleFolderClick(event) {\n event.preventDefault()\n event.stopPropagation()\n\n const folderButton = event.currentTarget\n folderButton.innerHTML = \"\"\n const spinner = new Spinner(\"small\")\n spinner.spin(folderButton)\n\n try {\n await patch(\n Alchemy.routes.fold_admin_page_path(this.pageId),\n null,\n \"text/vnd.turbo-stream.html\"\n )\n\n this.folded = !this.folded\n this.toggleAttribute(\"folded\", this.folded)\n this.toggleChildren()\n this.updateFolderIcon()\n } catch (error) {\n growl(error.message || error, \"error\")\n this.updateFolderIcon()\n } finally {\n spinner.stop()\n }\n }\n\n toggleChildren() {\n const childrenContainer = this.querySelector(\n `#page_${this.pageId}_children`\n )\n if (childrenContainer) {\n childrenContainer.classList.toggle(\"hidden\", this.folded)\n }\n }\n\n updateFolderIcon() {\n if (this.folderButton) {\n const iconName = this.folded ? \"arrow-right-s\" : \"arrow-down-s\"\n this.folderButton.innerHTML = `<alchemy-icon name=\"${iconName}\"></alchemy-icon>`\n }\n }\n\n /**\n * Updates the folder button state based on whether the node has children\n * Converts between button and span as needed\n */\n updateFolderButton() {\n const folderElement = this.querySelector(\".page_folder\")\n if (!folderElement) return\n\n const shouldShowButton = this.hasChildren || this.folded\n\n if (shouldShowButton && folderElement.tagName === SPAN) {\n // Convert span to button with icon\n const iconName = this.folded ? \"arrow-right-s\" : \"arrow-down-s\"\n folderElement.outerHTML = `<button class=\"page_folder icon_button\">\n <alchemy-icon name=\"${iconName}\"></alchemy-icon>\n </button>`\n\n // Re-attach event listener to the new button element\n this.folderButton?.addEventListener(\"click\", this)\n } else if (!shouldShowButton && folderElement.tagName === BUTTON) {\n // Convert button to empty span (no children and not folded)\n folderElement.outerHTML = '<span class=\"page_folder\"></span>'\n } else if (shouldShowButton && folderElement.tagName === BUTTON) {\n // Button exists, just update the icon direction\n this.updateFolderIcon()\n }\n }\n\n get hasChildren() {\n const childrenContainer = this.querySelector(\n `#page_${this.pageId}_children`\n )\n if (!childrenContainer) return false\n\n return (\n childrenContainer.querySelectorAll(\":scope > alchemy-page-node\").length >\n 0\n )\n }\n\n get folderButton() {\n return this.querySelector(\"button.page_folder\")\n }\n}\n\ncustomElements.define(\"alchemy-page-node\", AlchemyPageNode)\n","// Handles the page publication date fields\nexport class PagePublicationFields extends HTMLElement {\n connectedCallback() {\n this.publicField?.addEventListener(\"click\", this.#onClick)\n }\n\n disconnectedCallback() {\n this.publicField?.removeEventListener(\"click\", this.#onClick)\n }\n\n #onClick = (evt) => {\n const checkbox = evt.target\n const now = new Date()\n\n if (checkbox.checked) {\n this.publicationDateFields.classList.remove(\"hidden\")\n this.publicOnPicker.flatpickr.setDate(now)\n } else {\n this.publicationDateFields.classList.add(\"hidden\")\n this.publicOnPicker.flatpickr.clear()\n }\n this.publicUntilPicker.flatpickr?.clear()\n }\n\n get publicField() {\n return this.querySelector(\"#page_public\")\n }\n\n get publicOnPicker() {\n return this.querySelector(\"alchemy-datepicker:has(#page_public_on)\")\n }\n\n get publicUntilPicker() {\n return this.querySelector(\"alchemy-datepicker:has(#page_public_until)\")\n }\n\n get publicationDateFields() {\n return this.querySelector(\".page-publication-date-fields\")\n }\n}\n\ncustomElements.define(\"alchemy-page-publication-fields\", PagePublicationFields)\n","import { RemoteSelect } from \"alchemy_admin/components/remote_select\"\n\nclass PageSelect extends RemoteSelect {\n get pageId() {\n return this.selection ? JSON.parse(this.selection)[\"id\"] : undefined\n }\n\n _searchQuery(term, page) {\n return {\n q: {\n name_cont: term,\n ...JSON.parse(this.queryParams)\n },\n page: page\n }\n }\n\n _parseResponse(response) {\n const meta = response.meta\n return {\n results: response.pages,\n more: meta.page * meta.per_page < meta.total_count\n }\n }\n\n /**\n * result which is visible if a page was selected\n * @param {object} page\n * @returns {string}\n * @private\n */\n _renderResult(page) {\n return page.text || page.name\n }\n\n /**\n * html template for each list entry\n * @param {object} page\n * @param {string} term\n * @returns {string}\n * @private\n */\n _renderListEntry(page, term) {\n return `\n <div class=\"page-select--page\">\n <div class=\"page-select--top\">\n <alchemy-icon name=\"file-3\"></alchemy-icon>\n <span class=\"page-select--page-name\">${this._hightlightTerm(page.name, term)}</span>\n <span class=\"page-select--site-name\">${page.site.name}</span>\n </div>\n <div class=\"page-select--bottom\">\n <span class=\"page-select--page-urlname\">${page.url_path}</span>\n <span class=\"page-select--language-code\">${page.language_code}</span>\n </div>\n </div>\n `\n }\n}\n\ncustomElements.define(\"alchemy-page-select\", PageSelect)\n","class PictureDescriptionSelect extends HTMLElement {\n connectedCallback() {\n this.addEventListener(\"change\", this)\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"change\", this)\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"change\":\n this.onChange()\n break\n }\n }\n\n onChange() {\n const url = new URL(this.getAttribute(\"url\"))\n const select = this.querySelector(\"select\")\n url.searchParams.set(\"language_id\", select.value)\n Turbo.visit(url, { frame: \"picture_descriptions\" })\n }\n}\n\ncustomElements.define(\n \"alchemy-picture-description-select\",\n PictureDescriptionSelect\n)\n","import debounce from \"alchemy_admin/utils/debounce\"\nimport max from \"alchemy_admin/utils/max\"\nimport { get } from \"alchemy_admin/utils/ajax\"\nimport { growl } from \"alchemy_admin/growler\"\n\nconst UPDATE_DELAY = 125\nconst IMAGE_PLACEHOLDER = '<alchemy-icon name=\"image\" size=\"xl\"></alchemy-icon>'\nconst THUMBNAIL_SIZE = \"160x120\"\n\nexport class PictureEditor extends HTMLElement {\n connectedCallback() {\n this.cropFromField = this.querySelector(\"[data-crop-from]\")\n this.cropSizeField = this.querySelector(\"[data-crop-size]\")\n this.pictureIdField = this.querySelector(\"[data-picture-id]\")\n this.targetSizeField = this.querySelector(\"[data-target-size]\")\n this.imageCropperField = this.querySelector(\"[data-image-cropper]\")\n this.image = this.querySelector(\"img\")\n this.pictureThumbnail = this.querySelector(\"alchemy-picture-thumbnail\")\n this.deleteButton = this.querySelector(\".picture_tool.delete\")\n this.cropLink = this.querySelector(\".crop_link\")\n\n this.targetSize = this.targetSizeField.dataset.targetSize\n this.pictureId = this.pictureIdField.value\n\n // The mutation observer is observing multiple fields that all get updated\n // simultaneously. We only want to update the image once, so we debounce.\n this.update = debounce(() => {\n this.updateImage()\n this.updateCropLink()\n }, UPDATE_DELAY)\n\n this.deleteButton?.addEventListener(\"click\", this.removeImage)\n\n this.observer = new MutationObserver(this.mutationCallback)\n this.observer.observe(this.cropFromField, { attributes: true })\n this.observer.observe(this.cropSizeField, { attributes: true })\n this.observer.observe(this.pictureIdField, { attributes: true })\n }\n\n disconnectedCallback() {\n this.observer.disconnect()\n }\n\n mutationCallback = (mutationsList) => {\n for (const mutation of mutationsList) {\n if (\"pictureId\" in mutation.target.dataset) {\n this.cropFromField.value = \"\"\n this.cropSizeField.value = \"\"\n this.pictureId = mutation.target.value\n }\n this.update()\n }\n }\n\n updateImage() {\n if (!this.pictureId) return\n\n this.pictureThumbnail.loading = true\n get(Alchemy.routes.url_admin_picture_path(this.pictureId), {\n crop: this.imageCropperEnabled,\n crop_from: this.cropFrom,\n crop_size: this.cropSize,\n flatten: true,\n size: THUMBNAIL_SIZE\n })\n .then(({ data }) => {\n this.pictureThumbnail.src = data.url\n this.pictureThumbnail.image.alt = data.alt\n this.pictureThumbnail.image.title = data.title\n this.setElementDirty()\n })\n .catch((error) => {\n console.error(error.message || error)\n growl(error.message || error, \"error\")\n })\n }\n\n removeImage = () => {\n this.pictureThumbnail.innerHTML = IMAGE_PLACEHOLDER\n this.pictureIdField.value = \"\"\n this.image = null\n this.cropLink.classList.add(\"disabled\")\n this.setElementDirty()\n }\n\n setElementDirty() {\n this.closest(\".element-editor\").setDirty(this)\n }\n\n updateCropLink() {\n if (!this.pictureId || !this.imageCropperEnabled) return\n\n this.cropLink.classList.remove(\"disabled\")\n\n if (this.cropLink.href.match(/(picture_id=)\\d+/)) {\n this.cropLink.href = this.cropLink.href.replace(\n /(picture_id=)\\d+/,\n \"$1\" + this.pictureId\n )\n } else {\n this.cropLink.href = this.cropLink.href + `&picture_id=${this.pictureId}`\n }\n }\n\n get cropFrom() {\n if (this.cropFromField.value === \"\") {\n return this.defaultCropFrom.join(\"x\")\n }\n return this.cropFromField.value\n }\n\n get cropSize() {\n if (this.cropSizeField.value === \"\") {\n return this.defaultCropSize.join(\"x\")\n }\n return this.cropSizeField.value\n }\n\n get defaultCropSize() {\n if (!this.imageCropperEnabled) return []\n\n const mask = this.targetSize.split(\"x\").map((n) => parseInt(n))\n const zoom = max(\n mask[0] / this.imageFileWidth,\n mask[1] / this.imageFileHeight\n )\n\n return [Math.round(mask[0] / zoom), Math.round(mask[1] / zoom)]\n }\n\n get defaultCropFrom() {\n if (!this.imageCropperEnabled) return []\n\n const dimensions = this.defaultCropSize\n\n return [\n Math.round((this.imageFileWidth - dimensions[0]) / 2),\n Math.round((this.imageFileHeight - dimensions[1]) / 2)\n ]\n }\n\n get imageFileWidth() {\n return parseInt(this.pictureIdField.dataset.imageFileWidth)\n }\n\n get imageFileHeight() {\n return parseInt(this.pictureIdField.dataset.imageFileHeight)\n }\n\n get imageCropperEnabled() {\n return this.targetSizeField.dataset.imageCropper === \"true\"\n }\n}\n\ncustomElements.define(\"alchemy-picture-editor\", PictureEditor)\n","export default function (func, delay) {\n let timeout\n\n return function (...args) {\n const that = this\n\n clearTimeout(timeout)\n timeout = setTimeout(() => func.apply(that, args), delay)\n }\n}\n","export default function (a, b) {\n return a >= b ? a : b\n}\n","// Shows spinner while loading images and\n// fades the image after its been loaded\n\nimport Spinner from \"alchemy_admin/spinner\"\n\nexport default class PictureThumbnail extends HTMLElement {\n constructor() {\n super()\n\n this.spinner = new Spinner(\"small\")\n }\n\n handleEvent(evt) {\n switch (evt.type) {\n case \"load\":\n this.#onLoaded()\n break\n case \"error\":\n this.#onError(evt)\n break\n default:\n break\n }\n }\n\n connectedCallback() {\n this.classList.add(\"thumbnail_background\")\n if (this.src && !this.image) {\n this.start()\n }\n this.#setImage()\n }\n\n disconnectedCallback() {\n this.image?.removeEventListener(\"load\", this)\n this.image?.removeEventListener(\"error\", this)\n this.stop()\n }\n\n createImage(src = this.src, alt = this.name) {\n this.image = new Image()\n this.image.src = src\n if (alt) {\n this.image.alt = alt\n }\n }\n\n start(src) {\n this.createImage(src)\n this.image.addEventListener(\"load\", this)\n this.image.addEventListener(\"error\", this)\n this.load()\n }\n\n load() {\n if (this.image?.complete) {\n return\n }\n this.setAttribute(\"loading\", \"loading\")\n this.innerHTML = \"\"\n this.spinner.spin(this)\n }\n\n stop() {\n this.classList.remove(\"loading\")\n this.spinner.stop()\n }\n\n #onLoaded() {\n this.spinner.stop()\n this.removeAttribute(\"loading\")\n }\n\n #onError(evt) {\n const message = `Could not load ${this.image.src}`\n const hoist = this.closest(\".ingredient-editor\")\n this.spinner.stop()\n this.innerHTML = `\n <sl-tooltip content=\"${message}\" ${hoist ? \"hoist\" : \"\"}>\n <alchemy-icon name=\"alert\" class=\"error\"></alchemy-icon>\n </sl-tooltip>\n `\n console.error(message, evt)\n }\n\n #setImage() {\n if (this.image?.complete) {\n this.replaceChildren(this.image)\n } else if (this.image) {\n this.append(this.image)\n }\n }\n\n set loading(value) {\n value ? this.load() : this.stop()\n }\n\n set src(src) {\n this.start(src)\n this.#setImage()\n }\n\n get name() {\n return this.getAttribute(\"name\")\n }\n\n get src() {\n return this.getAttribute(\"src\")\n }\n}\n\ncustomElements.define(\"alchemy-picture-thumbnail\", PictureThumbnail)\n","class PublishPageButton extends HTMLElement {\n connectedCallback() {\n this.addEventListener(\"submit\", this)\n document.addEventListener(\"alchemy:page-dirty\", this)\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"submit\", this)\n document.removeEventListener(\"alchemy:page-dirty\", this)\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"alchemy:page-dirty\":\n this.markDirty(event.detail)\n break\n case \"submit\":\n this.button.loading = true\n break\n }\n }\n\n markDirty(detail) {\n this.button.variant = \"primary\"\n this.button.disabled = false\n this.tooltip.content = detail.tooltip\n }\n\n get button() {\n return this.querySelector(\"sl-button\")\n }\n\n get tooltip() {\n return this.querySelector(\"sl-tooltip\")\n }\n}\n\ncustomElements.define(\"alchemy-publish-page-button\", PublishPageButton)\n","class Select extends HTMLSelectElement {\n #select2Element\n\n connectedCallback() {\n this.classList.add(\"alchemy_selectbox\")\n\n this.#select2Element = $(this).select2({\n minimumResultsForSearch: 5,\n dropdownAutoWidth: true,\n allowClear: !!this.allowClear\n })\n\n // For single selects, remove the close button if allowClear is not set\n // For multiple selects, always keep the close buttons\n if (!this.allowClear && !this.multiple) {\n this.#select2Element\n .prev(\".select2-container\")\n .find(\".select2-search-choice-close\")\n .remove()\n }\n }\n\n disconnectedCallback() {\n this.#select2Element?.select2(\"destroy\")\n this.#select2Element = null\n }\n\n enable() {\n this.removeAttribute(\"disabled\")\n this.#updateSelect2()\n }\n\n disable() {\n this.setAttribute(\"disabled\", \"disabled\")\n this.#updateSelect2()\n }\n\n setOptions(data, prompt = undefined) {\n let selectedValue = this.value\n\n // reset the old options and insert the placeholder(s) first\n this.innerHTML = \"\"\n if (prompt) {\n this.add(new Option(prompt, \"\"))\n }\n\n // add the new options to the select\n data.forEach((item) => {\n this.add(new Option(item.text, item.id, false, item.id === selectedValue))\n })\n\n this.#updateSelect2()\n }\n\n /**\n * inform Select2 to update\n */\n #updateSelect2() {\n this.#select2Element.trigger(\"change\")\n }\n\n get allowClear() {\n return this.dataset.hasOwnProperty(\"allowClear\") || this.multiple\n }\n}\n\ncustomElements.define(\"alchemy-select\", Select, { extends: \"select\" })\n","import Sortable from \"sortablejs\"\nimport { growl } from \"alchemy_admin/growler\"\nimport { patch } from \"alchemy_admin/utils/ajax\"\nimport { translate } from \"alchemy_admin/i18n\"\nimport pleaseWaitOverlay from \"alchemy_admin/please_wait_overlay\"\n\n/**\n * Custom element for the sitemap container\n * Handles search/filter functionality and drag-and-drop sorting\n */\nexport class AlchemySitemap extends HTMLElement {\n connectedCallback() {\n this.searchInput = document.querySelector(\".search_input_field\")\n this.clearButton = document.querySelector(\"#search_field_clear\")\n this.resultCounter = document.querySelector(\"#page_filter_result\")\n\n this.setupSearch()\n\n // Wait for child custom elements to be defined before setting up sortables\n requestAnimationFrame(() => {\n this.setupSortables()\n })\n\n // Set up MutationObserver to re-initialize sortables when children containers are added\n this.observer = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n mutation.addedNodes.forEach((node) => {\n if (node.nodeType !== Node.ELEMENT_NODE) return\n\n // If the added node itself is a children container, initialize it\n if (node.classList?.contains(\"children\")) {\n this.setupSortable(node)\n }\n\n // Also check for children containers nested within the added node\n // This handles cases where a parent element with nested children is added at once\n node\n .querySelectorAll(\".children\")\n .forEach((el) => this.setupSortable(el))\n })\n })\n })\n\n // Observe the sitemap for added nodes\n this.observer.observe(this, {\n childList: true,\n subtree: true\n })\n }\n\n disconnectedCallback() {\n this.teardownSearch()\n this.observer?.disconnect()\n }\n\n setupSearch() {\n this.searchInput?.addEventListener(\"input\", this)\n this.clearButton?.addEventListener(\"click\", this)\n }\n\n teardownSearch() {\n this.searchInput?.removeEventListener(\"input\", this)\n this.clearButton?.removeEventListener(\"click\", this)\n }\n\n handleEvent(event) {\n if (event.type === \"input\" && event.target === this.searchInput) {\n this.handleSearch(event)\n } else if (event.type === \"click\" && event.target === this.clearButton) {\n this.handleClearSearch(event)\n }\n }\n\n handleSearch(event) {\n const term = event.target.value.toLowerCase().trim()\n\n if (term === \"\") {\n this.clearFilter()\n return\n }\n\n this.filterPages(term)\n }\n\n filterPages(term) {\n const allPages = this.querySelectorAll(\".sitemap_page\")\n let matchCount = 0\n let firstMatch = null\n\n allPages.forEach((pageElement) => {\n const pageName = pageElement.getAttribute(\"name\") || \"\"\n\n if (pageName.toLowerCase().includes(term)) {\n pageElement.classList.add(\"highlight\")\n pageElement.classList.remove(\"no-match\")\n matchCount++\n if (!firstMatch) firstMatch = pageElement\n } else {\n pageElement.classList.remove(\"highlight\")\n pageElement.classList.add(\"no-match\")\n }\n })\n\n // Update result counter\n\n if (matchCount === 1) {\n this.resultCounter.textContent = `1 ${translate(\"page_found\")}`\n this.resultCounter.style.display = \"block\"\n } else if (matchCount > 1) {\n this.resultCounter.textContent = `${matchCount} ${translate(\"pages_found\")}`\n this.resultCounter.style.display = \"block\"\n } else {\n this.resultCounter.style.display = \"none\"\n }\n\n // Scroll first match into view\n if (firstMatch) {\n firstMatch.scrollIntoView({ behavior: \"smooth\", block: \"center\" })\n }\n }\n\n clearFilter() {\n const allPages = this.querySelectorAll(\".sitemap_page\")\n allPages.forEach((pageElement) => {\n pageElement.classList.remove(\"highlight\", \"no-match\")\n })\n\n this.resultCounter.style.display = \"none\"\n }\n\n handleClearSearch(event) {\n event.preventDefault()\n this.searchInput.value = \"\"\n this.clearFilter()\n }\n\n setupSortable(container) {\n new Sortable(container, {\n group: \"pages\",\n animation: 150,\n fallbackOnBody: true,\n swapThreshold: 0.65,\n handle: \".page-icon.handle\",\n draggable: \"alchemy-page-node\",\n onEnd: (evt) => this.handleSort(evt)\n })\n }\n\n setupSortables() {\n const sortables = this.querySelectorAll(\".children\")\n sortables.forEach((el) => this.setupSortable(el))\n }\n\n async handleSort(evt) {\n // Only proceed if actually moved to different position/container\n if (evt.from === evt.to && evt.oldIndex === evt.newIndex) {\n return\n }\n\n // evt.item is the <alchemy-page-node> element being dragged\n const pageNode = evt.item\n const pageId = pageNode.pageId\n const url = Alchemy.routes.move_admin_page_path(pageId)\n const data = {\n target_parent_id: evt.to.dataset.parentId,\n new_position: evt.newIndex\n }\n\n pleaseWaitOverlay(true)\n\n try {\n const response = await patch(url, data)\n const pageData = await response.data\n\n // Update the URL path of the moved page\n const pageEl = pageNode.querySelector(`#page_${pageId}`)\n if (pageEl) {\n const urlPathEl = pageEl.querySelector(\".sitemap_url\")\n if (urlPathEl && pageData.url_path) {\n urlPathEl.textContent = pageData.url_path\n }\n }\n\n // Update folder icons for affected parent pages\n this.updateFolderIcons(evt.from, evt.to)\n\n growl(translate(\"Successfully moved page\"))\n } catch (error) {\n growl(error.message || error, \"error\")\n // Revert the DOM change by reloading on error\n window.location.reload()\n } finally {\n pleaseWaitOverlay(false)\n }\n }\n\n updateFolderIcons(fromContainer, toContainer) {\n // Update folder icon for source parent (might now have no children)\n const fromParent = fromContainer.closest(\"alchemy-page-node\")\n fromParent?.updateFolderButton()\n\n // Update folder icon for destination parent (now definitely has children)\n if (fromContainer !== toContainer) {\n const toParent = toContainer.closest(\"alchemy-page-node\")\n toParent?.updateFolderButton()\n }\n }\n}\n\ncustomElements.define(\"alchemy-sitemap\", AlchemySitemap)\n","import Sortable from \"sortablejs\"\nimport { growl } from \"alchemy_admin/growler\"\nimport { post } from \"alchemy_admin/utils/ajax\"\nimport { reloadPreview } from \"alchemy_admin/components/preview_window\"\nimport { dispatchPageDirtyEvent } from \"alchemy_admin/components/element_editor\"\n\nconst SORTABLE_OPTIONS = {\n draggable: \".element-editor\",\n handle: \".element-handle.draggable\",\n ghostClass: \"dragged\",\n animation: 150,\n swapThreshold: 0.65,\n easing: \"cubic-bezier(1, 0, 0, 1)\"\n}\n\nfunction onStart(event) {\n const name = event.item.dataset.elementName\n document\n .querySelectorAll(`[data-droppable-elements~=\"${name}\"]`)\n .forEach((dropzone) => dropzone.classList.add(\"droppable-elements\"))\n}\n\nfunction onSort(event) {\n const item = event.item\n const parentElement = event.to.parentElement.closest(\".element-editor\")\n const params = {\n element_id: item.dataset.elementId,\n position: event.newIndex + 1\n }\n\n if (parentElement) {\n params.parent_element_id = parentElement.dataset.elementId\n }\n\n // Only send the request if the item was moved to a different container\n // or sorted in the same list. Not on the old list in order to avoid incrementing\n // the position of the other elements.\n if (event.target === event.to) {\n post(Alchemy.routes.order_admin_elements_path, params).then((response) => {\n const data = response.data\n growl(data.message)\n if (data.pageHasUnpublishedChanges) {\n dispatchPageDirtyEvent(data)\n }\n reloadPreview()\n item.updateTitle(data.preview_text)\n })\n }\n}\n\nfunction onEnd() {\n const dropzones = document.querySelectorAll(\"[data-droppable-elements]\")\n dropzones.forEach((dropzone) =>\n dropzone.classList.remove(\"droppable-elements\")\n )\n}\n\nclass SortableElements extends HTMLElement {\n connectedCallback() {\n const group = {\n name: this.dataset.elementName,\n put(to, _from, item) {\n return to.el.dataset.droppableElements\n .split(\" \")\n .includes(item.dataset.elementName)\n }\n }\n new Sortable(this, {\n ...SORTABLE_OPTIONS,\n onStart,\n onSort,\n onEnd,\n group\n })\n }\n}\n\ncustomElements.define(\"alchemy-sortable-elements\", SortableElements)\n","class Spinner extends HTMLElement {\n connectedCallback() {\n this.className = `spinner spinner--${this.size}`\n this.innerHTML = `\n <svg width=\"100%\" viewBox=\"0 0 28 28\" style=\"--spinner-color: ${this.color}\">\n <path\n class=\"hex1\"\n d=\"M5.938,18.07l-5.878-5.9l2.154-8.058l8.024-2.161l5.87,5.9l-2.144,8.058L5.938,18.07z\"\n />\n <path\n class=\"hex2\"\n d=\"M19.686,20.785l-4.731-4.754l1.725-6.487l6.468-1.742l4.733,4.754l-1.734,6.487L19.686,20.785z\"\n />\n <path\n class=\"hex3\"\n d=\"M11.708,26.294l-3.47-3.485l1.276-4.758l4.74-1.276l3.468,3.485l-1.265,4.758L11.708,26.294z\"\n />\n </svg>\n `\n }\n\n get size() {\n return this.getAttribute(\"size\") || \"medium\"\n }\n\n get color() {\n return this.getAttribute(\"color\") || \"currentColor\"\n }\n}\n\ncustomElements.define(\"alchemy-spinner\", Spinner)\n","import { setupSelectLocale } from \"alchemy_admin/i18n\"\n\nclass TagsAutocomplete extends HTMLElement {\n #select2 = null\n\n async connectedCallback() {\n await setupSelectLocale()\n if (!this.isConnected) return\n\n this.classList.add(\"autocomplete_tag_list\")\n this.#select2 = $(this.input).select2(this.select2Config)\n }\n\n disconnectedCallback() {\n this.#select2?.select2(\"destroy\")\n this.#select2 = null\n }\n\n get input() {\n return this.getElementsByTagName(\"input\")[0]\n }\n\n get select2Config() {\n return {\n tags: true,\n tokenSeparators: [\",\"],\n openOnEnter: false,\n minimumInputLength: 1,\n createSearchChoice: this.#createSearchChoice,\n ajax: {\n url: this.getAttribute(\"url\"),\n dataType: \"json\",\n data: (term) => {\n return { term }\n },\n results: (data) => {\n return { results: data }\n }\n },\n initSelection: this.#initSelection\n }\n }\n\n #createSearchChoice(term, data) {\n if (\n $(data).filter(function () {\n return this.text.localeCompare(term) === 0\n }).length === 0\n ) {\n return {\n id: term,\n text: term\n }\n }\n }\n\n #initSelection(element, callback) {\n const data = []\n $(element.val().split(\",\")).each(function () {\n data.push({\n id: this.trim(),\n text: this\n })\n })\n callback(data)\n }\n}\n\ncustomElements.define(\"alchemy-tags-autocomplete\", TagsAutocomplete)\n","import \"tinymce\"\nimport { currentLocale } from \"alchemy_admin/i18n\"\n\nconst DARK_THEME = \"alchemy-dark\"\nconst LIGHT_THEME = \"alchemy\"\n\nclass Tinymce extends HTMLElement {\n #min_height = null\n\n /**\n * the observer will initialize Tinymce if the textarea becomes visible\n */\n connectedCallback() {\n this.className = \"tinymce_container\"\n\n // Append the spinner if not already present (idempotent on reconnect/clone)\n if (!this.querySelector(\":scope > alchemy-spinner\")) {\n this.insertAdjacentHTML(\n \"beforeend\",\n `<alchemy-spinner size=\"small\"></alchemy-spinner>`\n )\n }\n\n // hide the textarea until TinyMCE is ready to show the editor\n this.style.minHeight = `${this.minHeight}px`\n this.editor.style.display = \"none\"\n\n const observerCallback = (entries, observer) => {\n entries.forEach((entry) => {\n if (entry.intersectionRatio > 0) {\n this._initTinymceEditor()\n // disable observer after the Tinymce was initialized\n observer.unobserve(entry.target)\n }\n })\n }\n\n const options = {\n root: document.getElementById(\"element_area\"),\n rootMargin: \"0px\",\n threshold: [0.05]\n }\n\n this.tinymceIntersectionObserver = new IntersectionObserver(\n observerCallback,\n options\n )\n this.tinymceIntersectionObserver.observe(this)\n\n // Set up theme change listener\n this._setupThemeChangeListener()\n }\n\n /**\n * disconnect intersection observer and remove Tinymce editor if the web components get destroyed\n */\n disconnectedCallback() {\n this.tinymceIntersectionObserver?.disconnect()\n\n // Remove theme change listener\n this._removeThemeChangeListener()\n\n tinymce.get(this.editorId)?.remove(this.editorId)\n }\n\n /**\n * initialize Richtext area after the Intersection observer triggered\n * @private\n */\n _initTinymceEditor() {\n tinymce.init(this.configuration).then((editors) => {\n editors.forEach((editor) => this._setupEditor(editor))\n })\n }\n\n /**\n * Setup editor after initialization\n * @param {Object} editor - The TinyMCE editor instance\n * @private\n */\n _setupEditor(editor) {\n // mark the editor container as visible\n // without these correction the editor remains hidden\n // after a drag and drop action\n editor.show()\n\n // remove the spinner after the Tinymce initialized (only on first init)\n const spinner = this.getElementsByTagName(\"alchemy-spinner\")[0]\n if (spinner) {\n spinner.remove()\n }\n\n // event listener to mark the editor as dirty\n if (this.elementEditor) {\n editor.on(\"dirty\", (evt) => {\n this.elementEditor.setDirty(evt.target.editorContainer)\n })\n editor.on(\"click\", () => this.elementEditor.onClickElement(false))\n }\n }\n\n /**\n * Set up listener for OS theme changes\n * @private\n */\n _setupThemeChangeListener() {\n this.darkModeMediaQuery = window.matchMedia(\"(prefers-color-scheme: dark)\")\n this.themeChangeHandler = (event) => this._handleThemeChange(event)\n this.darkModeMediaQuery.addEventListener(\"change\", this.themeChangeHandler)\n }\n\n /**\n * Remove theme change listener\n * @private\n */\n _removeThemeChangeListener() {\n if (this.darkModeMediaQuery && this.themeChangeHandler) {\n this.darkModeMediaQuery.removeEventListener(\n \"change\",\n this.themeChangeHandler\n )\n }\n }\n\n /**\n * Handle OS theme change and update TinyMCE skin\n * @param {MediaQueryListEvent} event - The media query change event\n * @private\n */\n _handleThemeChange(event) {\n const editor = tinymce.get(this.editorId)\n if (editor) {\n const skin = event.matches ? DARK_THEME : LIGHT_THEME\n const content_css = event.matches ? DARK_THEME : LIGHT_THEME\n\n // Update the skin by reinitializing the editor with new configuration\n editor.remove()\n tinymce\n .init({\n content_css,\n ...this.configuration,\n skin\n })\n .then((editors) => {\n editors.forEach((editor) => this._setupEditor(editor))\n })\n }\n }\n\n get configuration() {\n const customConfig = {}\n\n // read the attributes on the component and add them as custom configuration\n this.getAttributeNames().forEach((attributeName) => {\n if (![\"class\", \"id\", \"is\", \"name\", \"style\"].includes(attributeName)) {\n const config = this.getAttribute(attributeName)\n const key = attributeName.replaceAll(\"-\", \"_\")\n\n // Handle boolean HTML attributes (e.g., readonly=\"readonly\" or readonly=\"\")\n if (config === attributeName || config === \"\") {\n customConfig[key] = true\n } else {\n try {\n customConfig[key] = JSON.parse(config)\n } catch (e) {\n // also string values as parameter\n customConfig[key] = config\n }\n }\n }\n })\n\n const config = {\n content_css: this.preferredTheme,\n ...Alchemy.TinymceDefaults,\n ...customConfig,\n language: currentLocale(),\n selector: `#${this.editorId}`,\n skin: this.preferredTheme\n }\n\n // Tinymce has a height of 400px by default\n // if the element has a min_height set, we use this value for the height as well\n // so we do not need to set both values in the element configuration\n config.height = config.min_height\n\n return config\n }\n\n get preferredTheme() {\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n ? DARK_THEME\n : LIGHT_THEME\n }\n\n get editorId() {\n return this.editor.id\n }\n\n get editor() {\n return this.getElementsByTagName(\"textarea\")[0]\n }\n\n get elementEditor() {\n return document\n .getElementById(this.editorId)\n .closest(\"alchemy-element-editor\")\n }\n\n get minHeight() {\n return this.#min_height || this.configuration.min_height\n }\n\n set minHeight(value) {\n this.#min_height = value\n }\n}\n\ncustomElements.define(\"alchemy-tinymce\", Tinymce)\n","import Spinner from \"alchemy_admin/spinner\"\n\nclass UpdateCheck extends HTMLElement {\n async connectedCallback() {\n const spinner = new Spinner(\"small\")\n spinner.spin(this)\n\n try {\n const response = await fetch(this.url, { credentials: \"include\" })\n const responseJSON = await response.json()\n\n if (response.ok) {\n this.showStatus(responseJSON)\n } else {\n this.showError(response)\n }\n } catch (error) {\n this.showError(error)\n } finally {\n spinner.stop()\n }\n }\n\n get url() {\n return this.getAttribute(\"url\")\n }\n\n showStatus(responseJSON) {\n if (responseJSON[\"status\"] == \"true\") {\n this.querySelector(\".update_available\").classList.remove(\"hidden\")\n } else {\n this.querySelector(\".up_to_date\").classList.remove(\"hidden\")\n }\n }\n\n showError(error) {\n this.querySelector(\".error\").classList.remove(\"hidden\")\n console.error(\"[alchemy] Error fetching update status\", error)\n }\n}\n\ncustomElements.define(\"alchemy-update-check\", UpdateCheck)\n","(()=>{var n=Handlebars.template;(Handlebars.templates=Handlebars.templates||{})[\"node_folder.hbs\"]=n({0:function(n,e,l,a,r){return\"right\"},1:function(n,e,l,a,r){return\"down\"},compiler:[8,\">= 4.3.0\"],main:function(n,e,l,a,r){var o,t=n.lambda,d=n.escapeExpression,u=n.lookupProperty||function(n,e){if(Object.prototype.hasOwnProperty.call(n,e))return n[e]};return'<a class=\"node_folder\" data-record-id=\"'+d(t(null!=(o=null!=e?u(e,\"node\"):e)?u(o,\"id\"):o,e))+'\" data-record-type=\"'+d(t(null!=(o=null!=e?u(e,\"node\"):e)?u(o,\"type\"):o,e))+'\">\\n <alchemy-icon name=\"arrow-'+(null!=(o=u(l,\"if\").call(null!=e?e:n.nullContext||{},null!=(o=null!=e?u(e,\"node\"):e)?u(o,\"folded\"):o,{name:\"if\",hash:{},fn:n.program(0,r,0),inverse:n.program(1,r,0),data:r,loc:{start:{line:2,column:28},end:{line:2,column:72}}}))?o:\"\")+'-s\"></alchemy-icon>\\n</a>\\n'},useData:!0})})();","import { registerIconLibrary, setDefaultAnimation } from \"shoelace\"\n\n// Change the default animation for all tooltips\nsetDefaultAnimation(\"tooltip.show\", {\n keyframes: [\n { transform: \"translateY(10px)\", opacity: \"0\" },\n { transform: \"translateY(0)\", opacity: \"1\" }\n ],\n options: {\n duration: 100\n }\n})\n\nsetDefaultAnimation(\"tooltip.hide\", {\n keyframes: [\n { transform: \"translateY(0)\", opacity: \"1\" },\n { transform: \"translateY(10px)\", opacity: \"0\" }\n ],\n options: {\n duration: 100\n }\n})\n\n// Change the default animation for all dialogs\nsetDefaultAnimation(\"dialog.show\", {\n keyframes: [\n { transform: \"scale(0.98)\", opacity: \"0\" },\n { transform: \"scale(1)\", opacity: \"1\" }\n ],\n options: {\n duration: 150\n }\n})\n\nsetDefaultAnimation(\"dialog.hide\", {\n keyframes: [\n { transform: \"scale(1)\", opacity: \"1\" },\n { transform: \"scale(0.98)\", opacity: \"0\" }\n ],\n options: {\n duration: 150\n }\n})\n\nconst spriteUrl = document\n .querySelector('link[rel=\"preload\"][as=\"image\"]')\n .getAttribute(\"href\")\n\nconst iconMap = {\n \"x-lg\": \"close\",\n caret: \"arrow-down-s\"\n}\n\nconst options = {\n resolver: (name) => `${spriteUrl}#ri-${iconMap[name] || name}-line`,\n mutator: (svg) => {\n svg.setAttribute(\"fill\", \"currentColor\")\n svg.setAttribute(\"viewBox\", \"0 0 24 24\")\n },\n spriteSheet: true\n}\n\nregisterIconLibrary(\"default\", options)\nregisterIconLibrary(\"system\", options)\n","export function on(eventName, baseSelector, targetSelector, callback) {\n document.querySelectorAll(baseSelector).forEach((baseNode) => {\n baseNode.addEventListener(eventName, (evt) => {\n const targets = Array.from(baseNode.querySelectorAll(targetSelector))\n let currentNode = evt.target\n\n while (currentNode !== baseNode) {\n if (targets.includes(currentNode)) {\n callback.call(currentNode, evt)\n return\n }\n currentNode = currentNode.parentElement\n }\n })\n })\n}\n","import Cropper from \"cropperjs\"\n\nexport default class ImageCropper {\n #initialized = false\n #cropper = null\n #cropFromField = null\n #cropSizeField = null\n\n constructor(image, settings) {\n this.image = image\n this.defaultBox = settings.default_box\n this.aspectRatio = settings.ratio\n this.#cropFromField = document.getElementById(\n settings.crop_from_form_field_id\n )\n this.#cropSizeField = document.getElementById(\n settings.crop_size_form_field_id\n )\n this.elementId = settings.element_id\n this.dialog = Alchemy.currentDialog()\n if (this.dialog) {\n this.dialog.options.closed = () => this.destroy()\n this.bind()\n }\n this.init()\n }\n\n get cropperOptions() {\n return {\n aspectRatio: this.aspectRatio,\n viewMode: 1,\n zoomable: false,\n checkCrossOrigin: false, // Prevent CORS issues\n checkOrientation: false, // Prevent loading the image via AJAX which can cause CORS issues\n data: this.box,\n cropend: () => {\n const data = this.#cropper.getData(true)\n this.update(data)\n }\n }\n }\n\n get cropFrom() {\n if (this.#cropFromField?.value) {\n return this.#cropFromField.value.split(\"x\").map((v) => parseInt(v))\n }\n }\n\n get cropSize() {\n if (this.#cropSizeField?.value) {\n return this.#cropSizeField.value.split(\"x\").map((v) => parseInt(v))\n }\n }\n\n get box() {\n if (this.cropFrom && this.cropSize) {\n return {\n x: this.cropFrom[0],\n y: this.cropFrom[1],\n width: this.cropSize[0],\n height: this.cropSize[1]\n }\n } else {\n return this.defaultBoxSize\n }\n }\n\n get defaultBoxSize() {\n return {\n x: this.defaultBox[0],\n y: this.defaultBox[1],\n width: this.defaultBox[2],\n height: this.defaultBox[3]\n }\n }\n\n init() {\n if (!this.#initialized) {\n this.#cropper = new Cropper(this.image, this.cropperOptions)\n this.#initialized = true\n }\n }\n\n update(coords) {\n this.#cropFromField.value = `${coords.x}x${coords.y}`\n this.#cropFromField.dispatchEvent(new Event(\"change\"))\n this.#cropSizeField.value = `${coords.width}x${coords.height}`\n this.#cropSizeField.dispatchEvent(new Event(\"change\"))\n }\n\n reset() {\n this.#cropper.setData(this.defaultBoxSize)\n this.update(this.defaultBoxSize)\n }\n\n destroy() {\n if (this.#cropper) {\n this.#cropper.destroy()\n }\n this.#initialized = false\n return true\n }\n\n bind() {\n this.dialog.dialog_body.find('button[type=\"submit\"]').on(\"click\", () => {\n const elementEditor = document.querySelector(\n `[data-element-id='${this.elementId}']`\n )\n elementEditor.setDirty()\n this.dialog.close()\n return false\n })\n this.dialog.dialog_body.find('button[type=\"reset\"]').on(\"click\", () => {\n this.reset()\n return false\n })\n }\n}\n","import { Dialog } from \"alchemy_admin/dialog\"\n\nexport default class ImageOverlay extends Dialog {\n constructor(url, options = {}) {\n super(url, options)\n }\n\n init() {\n $(\".zoomed-picture-background\").on(\"click\", (e) => {\n e.stopPropagation()\n if (e.target.nodeName === \"IMG\") {\n return\n }\n this.close()\n return false\n })\n $(\".picture-overlay-handle\").on(\"click\", (e) => {\n this.dialog.toggleClass(\"hide-form\")\n return false\n })\n this.$previous = $(\".previous-picture\")\n this.$next = $(\".next-picture\")\n this.#initKeyboardNavigation()\n super.init()\n }\n\n previous() {\n if (this.$previous[0] != null) {\n this.$previous[0].click()\n }\n }\n\n next() {\n if (this.$next[0] != null) {\n this.$next[0].click()\n }\n }\n\n build() {\n this.dialog_container = $('<div class=\"alchemy-image-overlay-container\" />')\n this.dialog = $('<div class=\"alchemy-image-overlay-dialog\" />')\n this.dialog_body = $('<div class=\"alchemy-image-overlay-body\" />')\n this.close_button = $(`<a class=\"alchemy-image-overlay-close\">\n <alchemy-icon name=\"close\" size=\"xl\"></alchemy-icon>\n </a>`)\n this.dialog.append(this.close_button)\n this.dialog.append(this.dialog_body)\n this.dialog_container.append(this.dialog)\n this.overlay = $('<div class=\"alchemy-image-overlay\" />')\n this.$body.append(this.overlay)\n this.$body.append(this.dialog_container)\n }\n\n #initKeyboardNavigation() {\n this.$document.keydown((e) => {\n if (e.target.nodeName === \"INPUT\" || e.target.nodeName === \"TEXTAREA\") {\n return true\n }\n switch (e.which) {\n case 37:\n this.previous()\n return false\n case 39:\n this.next()\n return false\n default:\n return true\n }\n })\n }\n}\n","import { on } from \"alchemy_admin/utils/events\"\nimport { openDialog } from \"alchemy_admin/dialog\"\n\nfunction toggleCheckboxes(state) {\n document\n .querySelectorAll(\".picture_tool.select input[type='checkbox']\")\n .forEach((checkbox) => {\n checkbox.checked = state\n checkbox.closest(\".picture_thumbnail\").classList.toggle(\"active\", state)\n })\n}\n\nfunction checkedInputs() {\n return document.querySelectorAll(\"#picture_archive input:checked\")\n}\n\nfunction editMultiplePicturesUrl(href) {\n const url = new URL(href)\n\n checkedInputs().forEach((entry) =>\n url.searchParams.append(entry.name, entry.value)\n )\n\n return url.toString()\n}\n\n/**\n * Multiple picture select handler for the picture archive.\n */\nexport default function PictureSelector() {\n const selectAllButton = document.querySelector(\"#select_all_pictures\")\n const selectedItemTools = document.querySelector(\".selected_item_tools\")\n\n on(\"click\", \".toolbar_buttons\", \"a#select_all_pictures\", (event) => {\n event.preventDefault()\n\n selectAllButton.classList.toggle(\"active\")\n\n const state = selectAllButton.classList.contains(\"active\")\n\n toggleCheckboxes(state)\n\n selectedItemTools.classList.toggle(\"hidden\", !state)\n })\n\n // make the item toolbar visible and show the checkbox also if it is not hovered anymore\n on(\"change\", \".picture_tool.select\", \"input\", (event) => {\n selectedItemTools.classList.toggle(\"hidden\", checkedInputs().length === 0)\n\n const parentElementClassList = event.target.parentElement.classList\n const checked = event.target.checked\n\n parentElementClassList.toggle(\"visible\", checked)\n })\n\n // open the edit view in a dialog modal\n on(\"click\", \".selected_item_tools\", \"a#edit_multiple_pictures\", (event) => {\n event.preventDefault()\n\n const url = editMultiplePicturesUrl(event.target.href)\n\n openDialog(url, {\n title: event.target.title,\n size: \"400x295\"\n })\n })\n}\n","import Sortable from \"sortablejs\"\nimport { patch } from \"alchemy_admin/utils/ajax\"\nimport { on } from \"alchemy_admin/utils/events\"\nimport { growl } from \"alchemy_admin/growler\"\n\nfunction displayNodeFolders() {\n document.querySelectorAll(\"li.menu-item\").forEach((el) => {\n const leftIconArea = el.querySelector(\".nodes_tree-left_images\")\n const list = el.querySelector(\".children\")\n const node = {\n folded: el.dataset.folded === \"true\",\n id: el.dataset.id,\n type: el.dataset.type\n }\n\n if (list.children.length > 0 || node.folded) {\n leftIconArea.innerHTML = Handlebars.templates[\"node_folder.hbs\"]({\n node: node\n })\n } else {\n leftIconArea.innerHTML = \"&nbsp;\"\n }\n })\n}\n\nfunction onFinishDragging(evt) {\n const url = Alchemy.routes[evt.item.dataset.type].move_api_path(\n evt.item.dataset.id\n )\n const data = {\n target_parent_id: evt.to.dataset.recordId,\n new_position: evt.newIndex\n }\n\n patch(url, data)\n .then(() => {\n const message = Alchemy.t(\"Successfully moved menu item\")\n growl(message)\n displayNodeFolders()\n })\n .catch((error) => {\n growl(error.message || error, \"error\")\n })\n}\n\nfunction handleNodeFolders() {\n on(\"click\", \".nodes_tree\", \".node_folder\", function () {\n const nodeId = this.dataset.recordId\n const menu_item = this.closest(\"li.menu-item\")\n const url =\n Alchemy.routes[this.dataset.recordType].toggle_folded_api_path(nodeId)\n const list = menu_item.querySelector(\".children\")\n\n patch(url)\n .then(() => {\n list.classList.toggle(\"folded\")\n menu_item.dataset.folded =\n menu_item.dataset.folded == \"true\" ? \"false\" : \"true\"\n displayNodeFolders()\n })\n .catch((error) => {\n growl(error.message || error)\n })\n })\n}\n\nexport default function NodeTree() {\n handleNodeFolders()\n displayNodeFolders()\n\n document.querySelectorAll(\".nodes_tree ul.children\").forEach((el) => {\n new Sortable(el, {\n group: \"nodes\",\n animation: 150,\n fallbackOnBody: true,\n swapThreshold: 0.65,\n handle: \".node_name\",\n invertSwap: true,\n onEnd: onFinishDragging\n })\n })\n}\n","// We still use jQuery in some places (ie. select2)\nimport \"handlebars\"\nimport \"jquery\"\nimport \"@ungap/custom-elements\"\nimport { Turbo } from \"@hotwired/turbo-rails\"\nimport \"select2\"\n\nimport Rails from \"@rails/ujs\"\n\nimport { translate } from \"alchemy_admin/i18n\"\nimport { currentDialog, closeCurrentDialog } from \"alchemy_admin/dialog\"\nimport Dirty from \"alchemy_admin/dirty\"\nimport * as FixedElements from \"alchemy_admin/fixed_elements\"\nimport { growl } from \"alchemy_admin/growler\"\nimport Initializer from \"alchemy_admin/initializer\"\nimport { LinkDialog } from \"alchemy_admin/link_dialog\"\nimport pleaseWaitOverlay from \"alchemy_admin/please_wait_overlay\"\nimport Spinner from \"alchemy_admin/spinner\"\nimport { reloadPreview } from \"alchemy_admin/components/preview_window\"\nimport { openConfirmDialog } from \"alchemy_admin/confirm_dialog\"\n\n// Web Components\nimport \"alchemy_admin/components\"\n\n// Handlebars Templates\nimport \"alchemy_admin/templates/compiled\"\n\n// Shoelace Setup\nimport \"alchemy_admin/shoelace_theme\"\n\n// Global Alchemy object\nif (typeof window.Alchemy === \"undefined\") {\n window.Alchemy = {}\n}\n\n// Enhance the global Alchemy object with imported features\nObject.assign(Alchemy, {\n closeCurrentDialog,\n currentDialog,\n ...Dirty,\n t: translate, // Global utility method for translating a given string\n FixedElements,\n growl,\n LinkDialog,\n pleaseWaitOverlay,\n Spinner,\n reloadPreview\n})\n\nRails.start()\nTurbo.config.forms.confirm = openConfirmDialog\ndocument.addEventListener(\"turbo:load\", Initializer)\n\n// Public API for extensions\nexport { RemoteSelect } from \"alchemy_admin/components/remote_select\"\nexport { on } from \"alchemy_admin/utils/events\"\n\n// Page-specific modules - bundled to avoid dual-loading\nexport { default as ImageCropper } from \"alchemy_admin/image_cropper\"\nexport { default as ImageOverlay } from \"alchemy_admin/image_overlay\"\nexport { default as pictureSelector } from \"alchemy_admin/picture_selector\"\nexport { default as NodeTree } from \"alchemy_admin/node_tree\"\n","import Hotkeys from \"alchemy_admin/hotkeys\"\nimport pleaseWaitOverlay from \"alchemy_admin/please_wait_overlay\"\n\nexport default function Initializer() {\n // We obviously have javascript enabled.\n document.documentElement.classList.remove(\"no-js\")\n\n // Initialize hotkeys.\n Hotkeys()\n\n // Add observer for please wait overlay.\n document.querySelectorAll(\".please_wait\").forEach((element) => {\n element.addEventListener(\"click\", pleaseWaitOverlay)\n })\n\n // Hack for enabling tab focus for <a>'s styled as button.\n document.querySelectorAll(\"a.button\").forEach((button) => {\n button.setAttribute(\"tabindex\", 0)\n })\n\n // Override the filter of keymaster.js so we can blur the fields on esc key.\n key.filter = function (event) {\n let tagName = (event.target || event.srcElement).tagName\n return (\n key.isPressed(\"esc\") ||\n !(tagName === \"INPUT\" || tagName === \"SELECT\" || tagName === \"TEXTAREA\")\n )\n }\n}\n"],"names":["KEY_SEPARATOR","getTranslation","key","locale","currentLocale","translations","Alchemy","test","keys","split","group","nestedTranslation","console","warn","document","documentElement","lang","translate","replacement","undefined","translation","replace","async","setupSelectLocale","import","$","extend","fn","select2","defaults","locales","bindedHotkeys","showHelp","evt","target","is","String","fromCharCode","which","openDialog","title","t","size","Hotkeys","scope","jQuery","removeEventListener","addEventListener","forEach","hotkey","unbind","search_fields","querySelectorAll","search_fields_clear","setScope","el","focus","focusVisible","push","click","blur","dataset","alchemyHotkey","createHtmlElement","text","element","createElement","innerHTML","content","children","Spinner$1","constructor","color","this","spinner","spin","parent","body","append","stop","remove","currentDialogs","DEFAULTS","header_height","padding","modal","overflow","ready","closed","Dialog","url","options","$document","$window","window","$body","width","parseInt","height","build","resize","open","dialog","trigger","bind_close_events","requestAnimationFrame","dialog_container","addClass","overlay","load","close","off","removeClass","on","pop","show_spinner","get","data","fail","xhr","show_error","reload","dialog_body","empty","remove_spinner","hide","html","init","dispatchEvent","CustomEvent","bubbles","detail","show","Spinner","watch_remote_forms","$form","event","getResponseHeader","match","responseText","statusText","status","error_body","error_header","error_type","error_messages","$errorDiv","error","close_button","e","keydown","dialog_header","dialog_title","getSize","css","doc_width","doc_height","currentDialog","length","closeCurrentDialog","callback","ConfirmDialog","message","ok_label","cancel_label","on_ok","bindEvents","cancelButton","preventDefault","on_cancel","okButton","source","querySelector","openConfirmDialog","Promise","resolve","pleaseWaitOverlay","checkPageDirtyness","action","find","appendTo","Turbo","visit","pathname","then","proceed","onbeforeunload","Dirty","PageLeaveObserver","currentTarget","removeTab","element_id","fixed_elements","getElementById","panel_name","label","tab","panel","growl","style","flashType","flashNotices","flashMessage","ANCHOR_REGEX","PreviewWindow","HTMLIFrameElement","afterLoad","reloadIcon","loadTimeout","handleEvent","type","clearLoadTimeout","stopSpinner","call","onPreviewReady","connectedCallback","attachEvents","localStorage","getItem","previewUrlSelect","value","refresh","disconnectedCallback","postMessage","contentWindow","startSpinner","src","setTimeout","isDragged","dragged","transitionProperty","pointerEvents","reloadButton","sizeSelect","setItem","includes","clearTimeout","getAttribute","reloadPreview","customElements","define","extends","IngredientAnchorLink","updateIcon","ingredientId","active","ingredientEditor","setAttribute","Action","HTMLElement","super","actions","removeFixedElement","updateAnchorIcon","hidePleaseWaitOverlay","func","name","params","hasAttribute","JSON","parse","hightlightTerm","term","RegExp","RemoteSelect","isConnected","input","classList","add","select2Config","onOpen","onChange","added","stringify","dispatchCustomEvent","removed","allowClear","selection","placeholder","queryParams","getElementsByTagName","initSelection","_$el","ajax","ajaxConfig","formatSelection","item","_renderResult","formatResult","_el","query","_renderListEntry","datatype","quietMillis","page","_searchQuery","results","response","_parseResponse","q","name_cont","meta","more","per_page","total_count","Error","_hightlightTerm","attachment","icon_css_class","AutoSubmit","submitEvent","Event","cancelable","form","Button","HTMLButtonElement","remote","stopPropagation","disable","enable","rect","getBoundingClientRect","initialButtonText","removeAttribute","CharCounter","maxChars","formField","getFormField","createDisplayElement","countCharacters","formFields","display","className","after","charLength","textContent","toggle","ClipboardButton","clipboard","ClipboardJS","destroy","formatItem","object","optionEl","swatch","ColorSelect","select","initializeSelect2","onSelectChange","colorInput","textInput","toggleColorPicker","val","minimumResultsForSearch","enabled","disabled","Datepicker","flatpickr","inputField","flatpickrOptions","enableTime","inputType","slice","altInput","altFormat","altInputClass","noCalendar","time_24hr","onValueUpdate","_selectedDates","_dateStr","instance","closest","setDirty","dateFormat","DialogLink","HTMLAnchorElement","dialogOptions","contains","JSON_CONTENT_TYPE","TURBO_STREAM_CONTENT_TYPE","isGetRequest","method","toLowerCase","prepareOptions","accept","headers","Accept","getToken","prepareHeaders","attributes","patch","post","path","fetch","URL","location","origin","search","URLSearchParams","toString","prepareURL","contentType","isJson","isTurboStream","responseData","json","renderStreamMessage","ok","DomIdSelect","dataItem","hash","id","selectElement","pageId","fetchDomIds","routes","api_ingredients_path","page_id","ingredients","filter","ingredient","dom_id","map","prompt","setOptions","reset","frame","elements","contentDocument","Array","from","PublishElementButton","scheduleButtonVariant","scheduleButton","publishButton","dropdown","loading","DeleteElementButton","button","removeElement","elementEditor","fixed","elementId","pageHasUnpublishedChanges","dispatchPageDirtyEvent","tooltip","publishButtonTooltip","ElementEditor","header","toggleButton","onHeaderDblclick","onToggleClick","focusElement","previewWindow","focusElementPreview","onClickElement","onSaveElement","hasEditors","firstChild","setTitle","selectTabForElement","expand","setClean","warning","ingredientsWithErrors","errorDisplay","errorMessage","appendChild","elementErrors","notice","updateTitle","previewText","ingredientAnchors","anchor","scrollToElement","scrollIntoView","behavior","scroll","reject","tabs","dirty","editor","collapsed","collapse","compact","toggleIcon","collapse_admin_element_path","nestedElementIds","selector","join","nestedElement","catch","finally","expanded","parentElementEditor","expand_admin_element_path","parentElementIds","parentElement","published","isPublished","bodySelector","footer","elementName","hasChildren","option","icon","ElementSelect","dropdownAutoWidth","hint","description","ElementsWindow","visible","turboFrame","collapseButton","onCollapseClick","onWindowMessage","onBodyClick","focusElementEditor","collapseAllElements","removeProperty","widthFromCookie","setProperty","cookie","row","startsWith","ElementsWindowHandle","dragging","elementsWindow","onMouseDown","onMouseUp","onDrag","pageX","elementWindowWidth","innerWidth","FileEditor","deleteLink","fileIcon","fileName","formFieldId","removeFile","ListFilter","debounceTimer","filterField","clearButton","onHotkey","onKeyup","onFocus","onClearClick","onEscape","visibility","matchedItems","itemsToShow","Set","lowerTerm","items","nameAttribute","indexOf","ancestor","itemsSelector","has","block","clear","debounceTime","Message","dismissTimeoutId","dismiss","closeIcon","dismissable","insertAdjacentHTML","iconName","dismissDelay","noticesWrapper","autoDismissDelay","Growl","Icon","observedAttributes","spriteUrl","render","attributeChangedCallback","sizeClass","IngredientGroup","HTMLDetailsElement","localStorageKey","isInLocalStorage","expanded_ingredient_groups","localStorageItem","LinkButton","LinkDialog","linkUrl","linkTitle","linkTarget","linkClass","link","setLink","linkButtons","linkUrlField","linkTitleField","linkTargetField","linkClassField","UnlinkButton","linked","isLinked","LinkButtons","removeLink","unlinkButton","setElementDirty","linkButton","formatFileSize","bytes","exponent","Math","floor","log","pow","toFixed","name_or_page_name_cont","node","ancestors","a","seperator","FileUpload","file","request","progressEventLoaded","progressEventTotal","valid","loadedSize","cancel","reader","FileReader","readAsDataURL","image","Image","result","prepend","initialize","validateFile","addRequestEventListener","finished","abort","config","uploader_defaults","maxFileSize","file_size_limit","allowedFiletypes","allowed_filetypes","alchemy_pictures","alchemy_attachments","upload","onprogress","progressEvent","onload","responseMessage","onerror","errorMessageContainer","progressElement","loaded","total","round","toggleAttribute","isValid","Progress","fileCount","fileUploads","buttonLabel","actionButton","handleFileChange","updateView","onComplete","fileUpload","activeUploads","setupCloseButton","_status","ariaLabel","sumFileProgresses","field","reduce","accumulator","totalProgress","overallProgressValue","overallUploadSize","every","entry","fileProgress","uploadedFileCount","uploadsStatuses","totalSize","ceil","weight","Uploader","dropzoneElement","isDraggedOver","fileInput","onFileInputChange","dropzone","setupDropZone","onDropzoneDragleave","onDropzoneDrop","onDropzoneDragover","handleUploadComplete","uploadFiles","files","toggleDropzoneClass","dataTransfer","getAsFile","redirectUrl","uploadProgress","fileUploadCount","XMLHttpRequest","upload_limit","submitFile","createProgress","formData","FormData","set","setRequestHeader","send","removeChild","Overlay","BUTTON","AlchemyPageNode","folded","folderButton","handleFolderClick","fold_admin_page_path","toggleChildren","updateFolderIcon","childrenContainer","updateFolderButton","folderElement","shouldShowButton","tagName","outerHTML","PagePublicationFields","publicField","onClick","checkbox","now","Date","checked","publicationDateFields","publicOnPicker","setDate","publicUntilPicker","pages","site","url_path","language_code","PictureDescriptionSelect","searchParams","PictureEditor","cropFromField","cropSizeField","pictureIdField","targetSizeField","imageCropperField","pictureThumbnail","deleteButton","cropLink","targetSize","pictureId","update","delay","timeout","args","that","apply","debounce","updateImage","updateCropLink","removeImage","observer","MutationObserver","mutationCallback","observe","disconnect","mutationsList","mutation","url_admin_picture_path","crop","imageCropperEnabled","crop_from","cropFrom","crop_size","cropSize","flatten","alt","href","defaultCropFrom","defaultCropSize","mask","n","zoom","imageFileWidth","b","imageFileHeight","dimensions","imageCropper","PictureThumbnail","onLoaded","onError","start","setImage","createImage","complete","hoist","replaceChildren","PublishPageButton","markDirty","variant","Select","HTMLSelectElement","select2Element","multiple","prev","updateSelect2","selectedValue","Option","hasOwnProperty","AlchemySitemap","searchInput","resultCounter","setupSearch","setupSortables","mutations","addedNodes","nodeType","Node","ELEMENT_NODE","setupSortable","childList","subtree","teardownSearch","handleSearch","handleClearSearch","trim","filterPages","clearFilter","allPages","matchCount","firstMatch","pageElement","container","Sortable","animation","fallbackOnBody","swapThreshold","handle","draggable","onEnd","handleSort","to","oldIndex","newIndex","pageNode","move_admin_page_path","target_parent_id","parentId","new_position","pageData","pageEl","urlPathEl","updateFolderIcons","fromContainer","toContainer","fromParent","toParent","SORTABLE_OPTIONS","ghostClass","easing","onStart","onSort","position","parent_element_id","order_admin_elements_path","preview_text","SortableElements","put","_from","droppableElements","TagsAutocomplete","tags","tokenSeparators","openOnEnter","minimumInputLength","createSearchChoice","dataType","localeCompare","each","DARK_THEME","LIGHT_THEME","Tinymce","min_height","minHeight","root","rootMargin","threshold","tinymceIntersectionObserver","IntersectionObserver","entries","intersectionRatio","_initTinymceEditor","unobserve","_setupThemeChangeListener","_removeThemeChangeListener","tinymce","editorId","configuration","editors","_setupEditor","editorContainer","darkModeMediaQuery","matchMedia","themeChangeHandler","_handleThemeChange","skin","matches","content_css","customConfig","getAttributeNames","attributeName","replaceAll","preferredTheme","TinymceDefaults","language","UpdateCheck","credentials","responseJSON","showStatus","showError","Handlebars","template","templates","l","r","compiler","main","o","lambda","d","escapeExpression","u","lookupProperty","Object","prototype","nullContext","program","inverse","loc","line","column","end","useData","setDefaultAnimation","keyframes","transform","opacity","duration","iconMap","caret","resolver","mutator","svg","spriteSheet","eventName","baseSelector","targetSelector","baseNode","targets","currentNode","registerIconLibrary","ImageCropper","initialized","cropper","settings","defaultBox","default_box","aspectRatio","ratio","crop_from_form_field_id","crop_size_form_field_id","bind","cropperOptions","viewMode","zoomable","checkCrossOrigin","checkOrientation","box","cropend","getData","v","x","y","defaultBoxSize","Cropper","coords","setData","ImageOverlay","nodeName","toggleClass","$previous","$next","initKeyboardNavigation","previous","next","checkedInputs","PictureSelector","selectAllButton","selectedItemTools","state","toggleCheckboxes","parentElementClassList","editMultiplePicturesUrl","displayNodeFolders","leftIconArea","list","onFinishDragging","move_api_path","recordId","NodeTree","nodeId","menu_item","recordType","toggle_folded_api_path","invertSwap","assign","FixedElements","onCreateLink","link_admin_pages_path","parameterMapping","selected_tab","link_title","link_target","internalForm","attachmentSelect","updatePage","submitForm","linkFormType","internalLink","domIdSelect","linkType","elementAnchor","link_url_regexp","showValidationError","errors","Rails","forms","confirm","srcElement","isPressed"],"mappings":"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"}
5
6
  >>>>>>> 314d20b16 (fix(RemoteSelect): Persist selection on change)
7
+ =======
8
+ {"version":3,"file":"alchemy_admin.min.js","sources":["../../../javascript/alchemy_admin/i18n.js","../../../javascript/alchemy_admin/hotkeys.js","../../../javascript/alchemy_admin/utils/dom_helpers.js","../../../javascript/alchemy_admin/spinner.js","../../../javascript/alchemy_admin/dialog.js","../../../javascript/alchemy_admin/confirm_dialog.js","../../../javascript/alchemy_admin/please_wait_overlay.js","../../../javascript/alchemy_admin/dirty.js","../../../javascript/alchemy_admin/fixed_elements.js","../../../javascript/alchemy_admin/growler.js","../../../javascript/alchemy_admin/link_dialog.js","../../../javascript/alchemy_admin/components/preview_window.js","../../../javascript/alchemy_admin/ingredient_anchor_link.js","../../../javascript/alchemy_admin/components/action.js","../../../javascript/alchemy_admin/components/remote_select.js","../../../javascript/alchemy_admin/components/attachment_select.js","../../../javascript/alchemy_admin/components/auto_submit.js","../../../javascript/alchemy_admin/components/button.js","../../../javascript/alchemy_admin/components/char_counter.js","../../../javascript/alchemy_admin/components/clipboard_button.js","../../../javascript/alchemy_admin/components/color_select.js","../../../javascript/alchemy_admin/components/datepicker.js","../../../javascript/alchemy_admin/components/dialog_link.js","../../../javascript/alchemy_admin/utils/ajax.js","../../../javascript/alchemy_admin/components/dom_id_select.js","../../../javascript/alchemy_admin/components/element_editor/publish_element_button.js","../../../javascript/alchemy_admin/components/element_editor/delete_element_button.js","../../../javascript/alchemy_admin/components/element_editor.js","../../../javascript/alchemy_admin/components/element_select.js","../../../javascript/alchemy_admin/components/elements_window.js","../../../javascript/alchemy_admin/components/elements_window_handle.js","../../../javascript/alchemy_admin/components/file_editor.js","../../../javascript/alchemy_admin/components/list_filter.js","../../../javascript/alchemy_admin/components/message.js","../../../javascript/alchemy_admin/components/growl.js","../../../javascript/alchemy_admin/components/icon.js","../../../javascript/alchemy_admin/components/ingredient_group.js","../../../javascript/alchemy_admin/components/link_buttons/link_button.js","../../../javascript/alchemy_admin/components/link_buttons/unlink_button.js","../../../javascript/alchemy_admin/components/link_buttons.js","../../../javascript/alchemy_admin/utils/format.js","../../../javascript/alchemy_admin/components/node_select.js","../../../javascript/alchemy_admin/components/uploader/file_upload.js","../../../javascript/alchemy_admin/components/uploader/progress.js","../../../javascript/alchemy_admin/components/uploader.js","../../../javascript/alchemy_admin/components/overlay.js","../../../javascript/alchemy_admin/components/page_node.js","../../../javascript/alchemy_admin/components/page_publication_fields.js","../../../javascript/alchemy_admin/components/page_select.js","../../../javascript/alchemy_admin/components/picture_description_select.js","../../../javascript/alchemy_admin/components/picture_editor.js","../../../javascript/alchemy_admin/utils/debounce.js","../../../javascript/alchemy_admin/utils/max.js","../../../javascript/alchemy_admin/components/picture_thumbnail.js","../../../javascript/alchemy_admin/components/publish_page_button.js","../../../../node_modules/tom-select/dist/esm/contrib/microevent.js","../../../../node_modules/@orchidjs/unicode-variants/dist/esm/regex.js","../../../../node_modules/@orchidjs/unicode-variants/dist/esm/strings.js","../../../../node_modules/@orchidjs/unicode-variants/dist/esm/index.js","../../../../node_modules/@orchidjs/sifter/dist/esm/utils.js","../../../../node_modules/@orchidjs/sifter/dist/esm/sifter.js","../../../../node_modules/tom-select/dist/esm/utils.js","../../../../node_modules/tom-select/dist/esm/vanilla.js","../../../../node_modules/tom-select/dist/esm/contrib/highlight.js","../../../../node_modules/tom-select/dist/esm/constants.js","../../../../node_modules/tom-select/dist/esm/defaults.js","../../../../node_modules/tom-select/dist/esm/getSettings.js","../../../../node_modules/tom-select/dist/esm/tom-select.js","../../../../node_modules/tom-select/dist/esm/contrib/microplugin.js","../../../../node_modules/tom-select/dist/esm/plugins/checkbox_options/plugin.js","../../../../node_modules/tom-select/dist/esm/plugins/clear_button/plugin.js","../../../../node_modules/tom-select/dist/esm/plugins/drag_drop/plugin.js","../../../../node_modules/tom-select/dist/esm/plugins/dropdown_header/plugin.js","../../../../node_modules/tom-select/dist/esm/plugins/caret_position/plugin.js","../../../../node_modules/tom-select/dist/esm/plugins/dropdown_input/plugin.js","../../../../node_modules/tom-select/dist/esm/plugins/input_autogrow/plugin.js","../../../../node_modules/tom-select/dist/esm/plugins/remove_button/plugin.js","../../../../node_modules/tom-select/dist/esm/plugins/virtual_scroll/plugin.js","../../../../node_modules/tom-select/dist/esm/tom-select.complete.js","../../../../node_modules/tom-select/dist/esm/plugins/change_listener/plugin.js","../../../../node_modules/tom-select/dist/esm/plugins/no_backspace_delete/plugin.js","../../../../node_modules/tom-select/dist/esm/plugins/no_active_items/plugin.js","../../../../node_modules/tom-select/dist/esm/plugins/optgroup_columns/plugin.js","../../../../node_modules/tom-select/dist/esm/plugins/restore_on_backspace/plugin.js","../../../../node_modules/@floating-ui/utils/dist/floating-ui.utils.mjs","../../../../node_modules/@floating-ui/core/dist/floating-ui.core.mjs","../../../../node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.mjs","../../../../node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs","../../../javascript/alchemy_admin/components/select.js","../../../javascript/alchemy_admin/components/sitemap.js","../../../javascript/alchemy_admin/components/sortable_elements.js","../../../javascript/alchemy_admin/components/spinner.js","../../../javascript/alchemy_admin/components/tags_autocomplete.js","../../../javascript/alchemy_admin/components/tinymce.js","../../../javascript/alchemy_admin/components/update_check.js","../../../javascript/alchemy_admin/templates/compiled.js","../../../javascript/alchemy_admin/shoelace_theme.js","../../../javascript/alchemy_admin/utils/events.js","../../../javascript/alchemy_admin/image_cropper.js","../../../javascript/alchemy_admin/image_overlay.js","../../../javascript/alchemy_admin/picture_selector.js","../../../javascript/alchemy_admin/node_tree.js","../../../javascript/alchemy_admin.js","../../../javascript/alchemy_admin/initializer.js"],"sourcesContent":["const KEY_SEPARATOR = /\\./\n\nfunction nestedTranslation(translations, key) {\n const keys = key.split(KEY_SEPARATOR)\n const group = translations[keys[0]]\n if (group) {\n return group[keys[1]] || key\n }\n return key\n}\n\nfunction getTranslation(key) {\n const locale = currentLocale()\n const translations = Alchemy.translations\n\n if (!translations) {\n console.warn(`Translations for locale ${locale} not found!`)\n return key\n }\n\n if (KEY_SEPARATOR.test(key)) {\n return nestedTranslation(translations, key)\n }\n return translations[key] || key\n}\n\nexport function currentLocale() {\n if (document.documentElement.lang) {\n return document.documentElement.lang\n }\n return \"en\"\n}\n\nexport function translate(key, replacement = undefined) {\n let translation = getTranslation(key)\n\n if (replacement) {\n return translation.replace(/%\\{.+\\}/, replacement)\n }\n return translation\n}\n\nexport async function setupSelectLocale() {\n const locale = currentLocale()\n if (locale === \"en\") return\n\n await import(`select2/${locale}.js`)\n $.extend($.fn.select2.defaults, $.fn.select2.locales[locale])\n}\n","import \"keymaster\"\nimport { openDialog } from \"alchemy_admin/dialog\"\n\nconst bindedHotkeys = []\n\nfunction showHelp(evt) {\n if (\n !$(evt.target).is(\"input, textarea\") &&\n String.fromCharCode(evt.which) === \"?\"\n ) {\n openDialog(\"/admin/help\", {\n title: Alchemy.t(\"help\"),\n size: \"400x492\"\n })\n return false\n } else {\n return true\n }\n}\n\nexport default function (scope = document) {\n // The scope can be a jQuery object because we still use jQuery in alchemy_admin/dialog.js.\n if (scope instanceof jQuery) {\n scope = scope[0]\n }\n\n // Unbind all previously registered hotkeys if we are not inside a dialog.\n if (scope === document) {\n document.removeEventListener(\"keypress\", showHelp)\n document.addEventListener(\"keypress\", showHelp)\n bindedHotkeys.forEach((hotkey) => key.unbind(hotkey))\n }\n\n // Binds keyboard shortcuts to search fields.\n const search_fields = scope.querySelectorAll(\".search_input_field\")\n const search_fields_clear = scope.querySelectorAll(\n \".search_field_clear, .js_filter_field_clear\"\n )\n key(\"alt+f\", function () {\n key.setScope(\"search\")\n search_fields.forEach((el) => el.focus({ focusVisible: true }))\n return false\n })\n bindedHotkeys.push(\"alt+f\")\n key(\"esc\", \"search\", function () {\n search_fields_clear.forEach((el) => el.click())\n search_fields.forEach((el) => el.blur())\n })\n bindedHotkeys.push(\"esc\")\n\n // Binds click events to buttons with hotkeys.\n //\n // Simply add a data-alchemy-hotkey attribute to your link.\n // If a hotkey is triggered by user, the click event of the element gets triggerd.\n //\n scope.querySelectorAll(\"[data-alchemy-hotkey]\").forEach(function (el) {\n const hotkey = el.dataset.alchemyHotkey\n key(hotkey, () => el.click())\n bindedHotkeys.push(hotkey)\n })\n}\n","/**\n * create a HTML element\n * @param {string} text\n * @returns {HTMLElement}\n */\nexport function createHtmlElement(text) {\n const element = document.createElement(\"template\")\n element.innerHTML = text\n return element.content.children[0]\n}\n\n/**\n * wrap element with wrappingElement\n * @param {HTMLElement} element\n * @param {HTMLElement} wrappingElement\n */\nexport function wrap(element, wrappingElement) {\n element.replaceWith(wrappingElement)\n wrappingElement.appendChild(element)\n}\n","import { createHtmlElement } from \"alchemy_admin/utils/dom_helpers\"\n\nexport default class Spinner {\n constructor(size, color = \"currentColor\") {\n this.size = size\n this.color = color\n this.spinner = undefined\n }\n\n /**\n * @returns {HTMLElement|undefined}\n */\n get el() {\n return this.spinner\n }\n /**\n * @param {HTMLElement|undefined} parent\n */\n spin(parent) {\n if (typeof parent === \"undefined\") {\n parent = document.body\n }\n this.spinner = createHtmlElement(\n `<alchemy-spinner size=\"${this.size}\" color=\"${this.color}\"></alchemy-spinner>`\n )\n parent.append(this.spinner)\n return this\n }\n\n stop() {\n if (this.spinner) {\n this.spinner.remove()\n this.spinner = undefined\n }\n }\n}\n","import Hotkeys from \"alchemy_admin/hotkeys\"\nimport Spinner from \"alchemy_admin/spinner\"\n\n// Collection of all current dialog instances\nconst currentDialogs = []\n\nconst DEFAULTS = {\n header_height: 36,\n size: \"400x300\",\n padding: true,\n title: \"\",\n modal: true,\n overflow: \"visible\",\n ready: () => {},\n closed: () => {}\n}\n\nexport class Dialog {\n // Arguments:\n // - url: The url to load the content from via ajax\n // - options: A object holding options\n // - size: The maximum size of the Dialog\n // - title: The title of the Dialog\n constructor(url, options = {}) {\n this.url = url\n this.options = { ...DEFAULTS, ...options }\n this.$document = $(document)\n this.$window = $(window)\n this.$body = $(\"body\")\n const size = this.options.size.split(\"x\")\n this.width = parseInt(size[0], 10)\n this.height = parseInt(size[1], 10)\n this.build()\n this.resize()\n }\n\n // Opens the Dialog and loads the content via ajax.\n open() {\n this.dialog.trigger(\"Alchemy.DialogOpen\")\n this.bind_close_events()\n window.requestAnimationFrame(() => {\n this.dialog_container.addClass(\"open\")\n if (this.overlay != null) {\n return this.overlay.addClass(\"open\")\n }\n })\n this.$body.addClass(\"prevent-scrolling\")\n currentDialogs.push(this)\n this.load()\n }\n\n // Closes the Dialog and removes it from the DOM\n close() {\n this.dialog.trigger(\"DialogClose.Alchemy\")\n this.$document.off(\"keydown\")\n this.dialog_container.removeClass(\"open\")\n if (this.overlay != null) {\n this.overlay.removeClass(\"open\")\n }\n this.$document.on(\n \"webkitTransitionEnd transitionend oTransitionEnd\",\n () => {\n this.$document.off(\"webkitTransitionEnd transitionend oTransitionEnd\")\n this.dialog_container.remove()\n if (this.overlay != null) {\n this.overlay.remove()\n }\n this.$body.removeClass(\"prevent-scrolling\")\n currentDialogs.pop(this)\n if (this.options.closed != null) {\n return this.options.closed()\n }\n }\n )\n return true\n }\n\n // Loads the content via ajax and replaces the Dialog body with server response.\n load() {\n this.show_spinner()\n $.get(this.url, (data) => {\n this.replace(data)\n }).fail((xhr) => {\n this.show_error(xhr)\n })\n }\n\n // Reloads the Dialog content\n reload() {\n this.dialog_body.empty()\n this.load()\n }\n\n // Replaces the dialog body with given content and initializes it.\n replace(data) {\n this.remove_spinner()\n this.dialog_body.hide()\n this.dialog_body.html(data)\n this.init()\n this.dialog[0].dispatchEvent(\n new CustomEvent(\"DialogReady.Alchemy\", {\n bubbles: true,\n detail: {\n body: this.dialog_body[0]\n }\n })\n )\n if (this.options.ready != null) {\n this.options.ready(this.dialog_body)\n }\n this.dialog_body.show()\n }\n\n // Adds a spinner into Dialog body\n show_spinner() {\n this.spinner = new Spinner(\"medium\")\n this.spinner.spin(this.dialog_body[0])\n }\n\n // Removes the spinner from Dialog body\n remove_spinner() {\n this.spinner.stop()\n }\n\n // Initializes the Dialog body\n init() {\n Hotkeys(this.dialog_body)\n this.watch_remote_forms()\n window.requestAnimationFrame(() => {\n this.dialog_body.find(\"[autofocus]\").focus()\n })\n }\n\n // Watches ajax requests inside of dialog body and replaces the content accordingly\n watch_remote_forms() {\n const $form = $('[data-remote=\"true\"]', this.dialog_body)\n\n $form.on(\"ajax:success\", (event) => {\n const xhr = event.detail[2]\n const content_type = xhr.getResponseHeader(\"Content-Type\")\n if (content_type.match(/javascript/)) {\n return\n } else {\n this.dialog_body.html(xhr.responseText)\n this.init()\n }\n })\n\n $form.on(\"ajax:error\", (event) => {\n const statusText = event.detail[1]\n const xhr = event.detail[2]\n this.show_error(xhr, statusText)\n })\n }\n\n // Displays an error message\n show_error(xhr, statusText) {\n if (xhr.status === 422) {\n this.dialog_body.html(xhr.responseText)\n this.init()\n return\n }\n\n const { error_body, error_header, error_type } = this.error_messages(\n xhr,\n statusText\n )\n\n const $errorDiv = $(`<alchemy-message type=\"${error_type}\">\n <h1>${error_header}</h1>\n <p>${error_body}</p>\n </alchemy-message>`)\n\n this.dialog_body.html($errorDiv)\n }\n\n // Returns error message based on xhr status\n error_messages(xhr, statusText) {\n let error_body,\n error_header,\n error_type = \"warning\"\n\n switch (xhr.status) {\n case 0:\n error_header = \"The server does not respond.\"\n error_body = \"Please check server and try again.\"\n break\n case 403:\n error_header = \"You are not authorized!\"\n error_body = \"Please close this window.\"\n break\n default:\n error_type = \"error\"\n if (statusText) {\n error_header = statusText\n console.error(xhr.responseText)\n } else {\n error_header = `${xhr.statusText} (${xhr.status})`\n }\n error_body = \"Please check log and try again.\"\n }\n\n return { error_header, error_body, error_type }\n }\n\n // Binds close events on:\n // - Close button\n // - Overlay (if the Dialog is a modal)\n // - ESC Key\n bind_close_events() {\n this.close_button.on(\"click\", () => {\n this.close()\n })\n this.dialog_container.addClass(\"closable\").on(\"click\", (e) => {\n if (e.target !== this.dialog_container.get(0)) {\n return true\n }\n this.close()\n return false\n })\n this.$document.keydown((e) => {\n if (e.which === 27) {\n this.close()\n return false\n } else {\n return true\n }\n })\n }\n\n // Builds the html structure of the Dialog\n build() {\n this.dialog_container = $('<div class=\"alchemy-dialog-container\" />')\n this.dialog = $('<div class=\"alchemy-dialog\" />')\n this.dialog_body = $('<div class=\"alchemy-dialog-body\" />')\n this.dialog_header = $('<div class=\"alchemy-dialog-header\" />')\n this.dialog_title = $('<div class=\"alchemy-dialog-title\" />')\n this.close_button = $(\n '<button class=\"alchemy-dialog-close\"><alchemy-icon name=\"close\"></alchemy-icon></button>'\n )\n this.dialog_title.text(this.options.title)\n this.dialog_header.append(this.dialog_title)\n this.dialog_header.append(this.close_button)\n this.dialog.append(this.dialog_header)\n this.dialog.append(this.dialog_body)\n this.dialog_container.append(this.dialog)\n if (this.options.modal) {\n this.dialog.addClass(\"modal\")\n }\n if (this.options.padding) {\n this.dialog_body.addClass(\"padded\")\n }\n if (this.options.modal) {\n this.overlay = $('<div class=\"alchemy-dialog-overlay\" />')\n this.$body.append(this.overlay)\n }\n this.$body.append(this.dialog_container)\n }\n\n // Sets the correct size of the dialog\n // It normalizes the given size, so that it never acceeds the window size.\n resize() {\n const { width, height } = this.getSize()\n\n this.dialog.css({\n width: width,\n \"min-height\": height,\n overflow: this.options.overflow\n })\n\n if (this.options.overflow === \"hidden\") {\n this.dialog_body.css({\n height: height,\n overflow: \"auto\"\n })\n } else {\n this.dialog_body.css({\n \"min-height\": height,\n overflow: \"visible\"\n })\n }\n }\n\n getSize() {\n const padding = this.options.padding ? 16 : 0\n const doc_width = this.$window.width()\n const doc_height = this.$window.height()\n\n let width = this.width\n let height = this.height\n\n if (width >= doc_width) {\n width = doc_width - padding\n }\n\n if (height >= doc_height) {\n height = doc_height - padding - DEFAULTS.header_height\n }\n\n return { width, height }\n }\n}\n\n// Gets the last dialog instantiated, which is the current one.\nexport function currentDialog() {\n const { length } = currentDialogs\n if (length === 0) {\n return\n }\n return currentDialogs[length - 1]\n}\n\n// Utility function to close the current Dialog\n//\n// You can pass a callback function, that gets triggered after the Dialog gets closed.\n//\nexport function closeCurrentDialog(callback) {\n const dialog = currentDialog()\n if (dialog != null) {\n dialog.options.closed = callback\n return dialog.close()\n }\n}\n\n// Utility function to open a new Dialog\nexport function openDialog(url, options) {\n if (!url) {\n throw \"No url given! Please provide an url.\"\n }\n const dialog = new Dialog(url, options)\n dialog.open()\n}\n","import { createHtmlElement } from \"alchemy_admin/utils/dom_helpers\"\nimport { translate } from \"alchemy_admin/i18n\"\n\nconst getDefaults = () => ({\n // The default size of the dialog\n size: \"300x100\",\n title: translate(\"Please confirm\"),\n ok_label: translate(\"Yes\"),\n cancel_label: translate(\"No\"),\n on_ok() {}\n})\n\nclass ConfirmDialog {\n constructor(message, options = {}) {\n this.message = message\n this.options = { ...getDefaults(), ...options }\n this.#build()\n this.#bindEvents()\n }\n\n open() {\n requestAnimationFrame(() => {\n this.dialog.show()\n })\n }\n\n #build() {\n const width = this.options.size.split(\"x\")[0]\n this.dialog = createHtmlElement(`\n <sl-dialog label=\"${this.options.title}\" style=\"--width: ${width}px\">\n ${this.message}\n <button slot=\"footer\" type=\"reset\" class=\"secondary mx-1 my-0\" autofocus>\n ${this.options.cancel_label}\n </button>\n <button slot=\"footer\" type=\"submit\" class=\"mx-1 my-0\">\n ${this.options.ok_label}\n </button>\n </sl-dialog>\n `)\n document.body.append(this.dialog)\n }\n\n #bindEvents() {\n this.cancelButton.addEventListener(\"click\", (evt) => {\n evt.preventDefault()\n this.options.on_cancel()\n this.dialog.hide()\n })\n this.okButton.addEventListener(\"click\", (evt) => {\n evt.preventDefault()\n this.options.on_ok()\n this.dialog.hide()\n })\n // Prevent the dialog from closing when the user clicks on the overlay\n this.dialog.addEventListener(\"sl-request-close\", (event) => {\n if (event.detail.source === \"overlay\") {\n this.options.on_cancel()\n event.preventDefault()\n }\n })\n // Remove the dialog from the DOM after it has been hidden\n this.dialog.addEventListener(\"sl-after-hide\", () => {\n this.dialog.remove()\n })\n }\n\n get cancelButton() {\n return this.dialog.querySelector(\"button[type=reset]\")\n }\n\n get okButton() {\n return this.dialog.querySelector(\"button[type=submit]\")\n }\n}\n\n/* Opens a confirm dialog\n *\n * @param {string} message - The message that will be displayed to the user\n * @param {Object} [options={}] - Configuration options for the dialog\n * @param {string} [options.title=\"Please confirm\"] - The title of the overlay window\n * @param {string} [options.cancel_label=\"No\"] - The label of the cancel button\n * @param {string} [options.ok_label=\"Yes\"] - The label of the ok button\n *\n * @returns {Promise<void>} A promise that resolves to true when the OK button is clicked and\n * resolves to false when the cancel button is clicked. Works as confirm dialog replacement\n * for Turbo.confirm.\n */\nexport function openConfirmDialog(message, options = {}) {\n return new Promise((resolve) => {\n const dialog = new ConfirmDialog(message, {\n ...options,\n on_ok() {\n resolve(true)\n },\n on_cancel() {\n resolve(false)\n }\n })\n dialog.open()\n })\n}\n","/**\n * To show the \"Please wait\" overlay.\n * Pass false to hide it.\n * @param {boolean} show\n */\nexport default function pleaseWaitOverlay(show = true) {\n document.querySelector(\"alchemy-overlay\").show = !!show\n}\n","import { openConfirmDialog } from \"alchemy_admin/confirm_dialog\"\nimport { translate } from \"alchemy_admin/i18n\"\nimport pleaseWaitOverlay from \"alchemy_admin/please_wait_overlay\"\n\nfunction checkPageDirtyness(element) {\n let callback = () => {}\n\n if ($(element).is(\"form\")) {\n callback = function () {\n const $form = $(\n `<form action=\"${element.action}\" method=\"POST\" style=\"display: none\" />`\n )\n $form.append($(element).find(\"input\"))\n $form.appendTo(\"body\")\n\n pleaseWaitOverlay()\n $form.trigger(\"submit\")\n }\n } else if ($(element).is(\"a\")) {\n callback = () => Turbo.visit(element.pathname)\n }\n\n const isPageDirty =\n document.querySelectorAll(\"alchemy-element-editor.dirty\").length > 0\n\n if (isPageDirty) {\n openConfirmDialog(translate(\"page_dirty_notice\"), {\n title: translate(\"warning\"),\n ok_label: translate(\"ok\"),\n cancel_label: translate(\"cancel\")\n }).then((proceed) => {\n if (proceed) {\n window.onbeforeunload = void 0\n callback()\n }\n })\n return false\n }\n return true\n}\n\nfunction PageLeaveObserver() {\n document.querySelectorAll(\"#main_navi a\").forEach((element) => {\n element.addEventListener(\"click\", (event) => {\n if (!checkPageDirtyness(event.currentTarget)) {\n event.preventDefault()\n }\n })\n })\n}\n\nexport default {\n checkPageDirtyness,\n PageLeaveObserver\n}\n","// Creates a fixed element tab.\nexport function createTab(element_id, label) {\n const fixed_elements = document.getElementById(\"fixed-elements\")\n const panel_name = `fixed-element-${element_id}`\n\n const tab = `<sl-tab slot=\"nav\" panel=\"${panel_name}\">${label}</sl-tab>`\n const panel = `<sl-tab-panel name=\"${panel_name}\" style=\"--padding: 0\" />`\n\n fixed_elements.innerHTML += tab + panel\n\n window.requestAnimationFrame(function () {\n fixed_elements.show(panel_name)\n })\n}\n\nexport function removeTab(element_id) {\n const fixed_elements = document.getElementById(\"fixed-elements\")\n const panel_name = `fixed-element-${element_id}`\n\n fixed_elements.querySelector(`sl-tab[panel=\"${panel_name}\"]`).remove()\n fixed_elements.querySelector(`sl-tab-panel[name=\"${panel_name}\"]`).remove()\n\n fixed_elements.show(\"main-content-elements\")\n}\n","import { createHtmlElement } from \"alchemy_admin/utils/dom_helpers\"\n\nfunction build(message, flashType) {\n const flashNotices = document.getElementById(\"flash_notices\")\n const flashMessage = createHtmlElement(`\n <alchemy-message type=\"${flashType}\" dismissable>\n ${message}\n </alchemy-message>\n `)\n flashNotices.append(flashMessage)\n}\n\nexport function growl(message, style = \"notice\") {\n build(message, style)\n}\n","import { translate } from \"alchemy_admin/i18n\"\nimport { Dialog } from \"alchemy_admin/dialog\"\n\n// Matches a URL fragment (#anchor) at the end of a string.\n// Covers RFC 3986 unreserved characters (ALPHA, DIGIT, \"-\", \".\", \"_\", \"~\")\n// which are the characters valid in URL fragments and common in DOM element IDs.\nconst ANCHOR_REGEX = /#[\\w.~-]+$/\n\n// Represents the link Dialog that appears, if a user clicks the link buttons\n// in TinyMCE or on an Ingredient that has links enabled (e.g. Picture)\n//\nexport class LinkDialog extends Dialog {\n #onCreateLink\n\n constructor(link) {\n const url = new URL(Alchemy.routes.link_admin_pages_path, window.location)\n const parameterMapping = {\n url: link.url,\n selected_tab: link.type,\n link_title: link.title,\n link_target: link.target\n }\n\n // searchParams.set would also add undefined values\n Object.keys(parameterMapping).forEach((key) => {\n if (parameterMapping[key]) {\n url.searchParams.set(key, parameterMapping[key])\n }\n })\n\n super(url.href, {\n size: \"600x320\",\n title: translate(\"Link\")\n })\n }\n\n /**\n * Called from Dialog class after the url was loaded\n */\n replace(data) {\n // let Dialog class handle the content replacement\n super.replace(data)\n this.#attachEvents()\n }\n\n /**\n * make the open method a promise\n * maybe in a future version the whole Dialog will respond with a promise result if the dialog is closing\n * @returns {Promise<unknown>}\n */\n open() {\n super.open()\n return new Promise((resolve) => (this.#onCreateLink = resolve))\n }\n\n /**\n * Attaches click events to forms in the link dialog.\n */\n #attachEvents() {\n // enable the dom selection in internal link tab\n const internalForm = document.querySelector(\n '[data-link-form-type=\"internal\"]'\n )\n const attachmentSelect = document.querySelector(\n '[data-link-form-type=\"file\"] alchemy-attachment-select'\n )\n\n internalForm.addEventListener(\"Alchemy.RemoteSelect.Change\", (e) => {\n this.#updatePage(e.detail.added)\n })\n\n attachmentSelect.addEventListener(\"Alchemy.RemoteSelect.Change\", (e) => {\n const attachment = e.detail.added\n document.getElementById(\"file_link\").value = attachment\n ? attachment.url\n : \"\"\n })\n\n document.querySelectorAll(\"[data-link-form-type]\").forEach((form) => {\n form.addEventListener(\"submit\", (e) => {\n e.preventDefault()\n this.#submitForm(e.target.dataset.linkFormType)\n })\n })\n }\n\n /**\n * update page select and set anchor select\n * @param page\n */\n #updatePage(page = null) {\n const internalLink = document.getElementById(\"internal_link\")\n const domIdSelect = document.querySelector(\n '[data-link-form-type=\"internal\"] alchemy-dom-id-api-select'\n )\n\n internalLink.value = page ? page.url_path : \"\"\n domIdSelect.page = page ? page.id : undefined\n }\n\n /**\n * submit the form itself\n * @param linkType\n */\n #submitForm(linkType) {\n const elementAnchor = document.getElementById(\"element_anchor\")\n let url = document.getElementById(`${linkType}_link`).value\n\n if (linkType === \"internal\" && elementAnchor.value !== \"\") {\n // remove possible fragments on the url and attach the fragment (which contains the #)\n url = url.replace(ANCHOR_REGEX, \"\") + elementAnchor.value\n } else if (linkType === \"external\" && !url.match(Alchemy.link_url_regexp)) {\n // show validation error and prevent link creation\n this.#showValidationError()\n return\n }\n\n // Create the link\n this.#onCreateLink({\n url: url.trim(),\n title: document.getElementById(`${linkType}_link_title`).value,\n target: document.getElementById(`${linkType}_link_target`)?.value,\n type: linkType\n })\n this.close()\n }\n\n /**\n * Shows validation errors\n */\n #showValidationError() {\n const errors = document.getElementById(\"errors\")\n errors.querySelector(\"ul\").innerHTML =\n `<li>${Alchemy.t(\"url_validation_failed\")}</li>`\n errors.style.display = \"block\"\n }\n}\n","import { growl } from \"alchemy_admin/growler\"\nimport { translate } from \"alchemy_admin/i18n\"\n\nclass PreviewWindow extends HTMLIFrameElement {\n #afterLoad\n #reloadIcon\n #loadTimeout\n\n handleEvent(evt) {\n if (evt.type === \"load\") {\n this.#clearLoadTimeout()\n this.#stopSpinner()\n this.#afterLoad?.call(this, evt)\n }\n }\n\n #onPreviewReady = (event) => {\n if (event.data.message === \"Alchemy.previewReady\") {\n this.#clearLoadTimeout()\n this.#stopSpinner()\n this.#afterLoad?.call(this, event)\n }\n }\n\n connectedCallback() {\n let url = this.url\n\n this.addEventListener(\"load\", this)\n this.#attachEvents()\n window.addEventListener(\"message\", this.#onPreviewReady)\n\n if (window.localStorage.getItem(\"alchemy-preview-url\")) {\n url = window.localStorage.getItem(\"alchemy-preview-url\")\n this.previewUrlSelect.value = url\n }\n\n this.refresh(url)\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"load\", this)\n key.unbind(\"alt+r\")\n window.removeEventListener(\"message\", this.#onPreviewReady)\n }\n\n postMessage(data) {\n this.contentWindow.postMessage(data, \"*\")\n }\n\n resize(width) {\n this.style.width = `${width}px`\n }\n\n refresh(url) {\n this.#startSpinner()\n\n if (url) {\n this.src = url\n } else {\n this.src = this.url\n }\n\n // Set 5s timeout as fallback - if iframe doesn't load, stop spinner anyway\n this.#clearLoadTimeout()\n this.#loadTimeout = setTimeout(() => {\n this.#stopSpinner()\n growl(translate(\"Preview failed to load\"), \"warning\")\n }, 5000)\n\n return new Promise((resolve) => {\n this.#afterLoad = resolve\n })\n }\n\n set isDragged(dragged) {\n this.style.transitionProperty = dragged ? \"none\" : null\n this.style.pointerEvents = dragged ? \"none\" : null\n }\n\n #attachEvents() {\n this.reloadButton?.addEventListener(\"click\", (evt) => {\n evt.preventDefault()\n this.refresh()\n })\n\n key(\"alt+r\", () => this.refresh())\n\n this.sizeSelect.addEventListener(\"change\", (evt) => {\n const select = evt.target\n const width = select.value\n\n if (width === \"\") {\n this.style.width = null\n } else {\n this.resize(width)\n }\n })\n\n this.previewUrlSelect?.addEventListener(\"change\", (evt) => {\n const url = evt.target.value\n window.localStorage.setItem(\"alchemy-preview-url\", url)\n this.refresh(url)\n })\n }\n\n #startSpinner() {\n // Only save the reload icon if we're not already showing a spinner\n if (!this.reloadButton.innerHTML.includes(\"alchemy-spinner\")) {\n this.#reloadIcon = this.reloadButton.innerHTML\n }\n this.reloadButton.innerHTML = `<alchemy-spinner size=\"small\"></alchemy-spinner>`\n }\n\n #stopSpinner() {\n this.reloadButton.innerHTML = this.#reloadIcon\n }\n\n #clearLoadTimeout() {\n if (this.#loadTimeout) {\n clearTimeout(this.#loadTimeout)\n this.#loadTimeout = null\n }\n }\n\n get url() {\n return this.getAttribute(\"url\")\n }\n\n get sizeSelect() {\n return document.querySelector(\"select#preview_size\")\n }\n\n get previewUrlSelect() {\n return document.querySelector(\"select#preview_url\")\n }\n\n get reloadButton() {\n return document.querySelector(\"#reload_preview_button\")\n }\n}\n\ncustomElements.define(\"alchemy-preview-window\", PreviewWindow, {\n extends: \"iframe\"\n})\n\nexport function reloadPreview() {\n const previewWindow = document.getElementById(\"alchemy_preview_window\")\n previewWindow.refresh()\n}\n","export default class IngredientAnchorLink {\n static updateIcon(ingredientId, active = false) {\n const ingredientEditor = document.querySelector(\n `[data-ingredient-id=\"${ingredientId}\"]`\n )\n if (ingredientEditor) {\n const icon = ingredientEditor.querySelector(\n \".edit-ingredient-anchor-link alchemy-icon\"\n )\n icon.setAttribute(\"icon-style\", active ? \"fill\" : \"line\")\n }\n }\n}\n","import { reloadPreview } from \"alchemy_admin/components/preview_window\"\nimport { removeTab } from \"alchemy_admin/fixed_elements\"\nimport { closeCurrentDialog } from \"alchemy_admin/dialog\"\nimport IngredientAnchorLink from \"alchemy_admin/ingredient_anchor_link\"\nimport pleaseWaitOverlay from \"alchemy_admin/please_wait_overlay\"\n\nclass Action extends HTMLElement {\n constructor() {\n super()\n\n // map action names with Javascript functions\n this.actions = {\n // add a intermediate closeCurrentDialog - action\n // this will be gone, if all dialogs are working with a promise and\n // we don't have to implicitly close the dialog\n closeCurrentDialog,\n reloadPreview,\n removeFixedElement: removeTab,\n updateAnchorIcon: IngredientAnchorLink.updateIcon,\n hidePleaseWaitOverlay() {\n pleaseWaitOverlay(false)\n }\n }\n }\n\n connectedCallback() {\n const func = this.actions[this.name]\n\n if (func) {\n func(...this.params)\n } else {\n console.error(`Unknown Alchemy action: ${this.name}`)\n }\n\n this.remove()\n }\n\n get name() {\n return this.getAttribute(\"name\")\n }\n\n get params() {\n if (this.hasAttribute(\"params\")) {\n return JSON.parse(this.getAttribute(\"params\"))\n }\n return []\n }\n}\n\ncustomElements.define(\"alchemy-action\", Action)\n","import { setupSelectLocale } from \"alchemy_admin/i18n\"\n\nexport function hightlightTerm(name, term) {\n return name.replace(new RegExp(term, \"gi\"), (match) => `<em>${match}</em>`)\n}\n\nexport class RemoteSelect extends HTMLElement {\n #select2 = null\n\n async connectedCallback() {\n await setupSelectLocale()\n // Bail out if the element was disconnected while the locale was loading.\n // Otherwise Select2 would leak onto a detached input.\n if (!this.isConnected) return\n\n this.input.classList.add(\"alchemy_selectbox\")\n\n this.#select2 = $(this.input)\n .select2(this.select2Config)\n .on(\"select2-open\", this.#onOpen)\n .on(\"change\", this.#onChange)\n }\n\n disconnectedCallback() {\n if (this.#select2) {\n this.#select2.off(\"select2-open\", this.#onOpen)\n this.#select2.off(\"change\", this.#onChange)\n this.#select2.select2(\"destroy\")\n this.#select2 = null\n }\n }\n\n #onOpen = (evt) => this.onOpen(evt)\n #onChange = (evt) => this.onChange(evt)\n\n /**\n * Optional on change handler called by Select2.\n * @param {Event} event\n */\n onChange(event) {\n // Update selection attribute so re-attaching the select2 component to\n // the same input (e.g. after dragndrop) does not reset the selection.\n if (event.added) {\n this.setAttribute(\"selection\", JSON.stringify(event.added))\n }\n this.dispatchCustomEvent(\"RemoteSelect.Change\", {\n removed: event.removed,\n added: event.added\n })\n }\n\n /**\n * Optional on open handler called by Select2.\n * @param {Event} event\n */\n onOpen(event) {\n // add focus to the search input. Select2 is handling the focus on the first opening,\n // but it does not work the second time. One process in select2 is \"stealing\" the focus\n // if the command is not delayed. It is an intermediate solution until we are going to\n // move away from Select2\n setTimeout(() => {\n document.querySelector(\"#select2-drop .select2-input\").focus()\n }, 100)\n }\n\n /**\n * Dispatches a custom event with given name, namespaced under `Alchemy.`.\n * Subclasses may call this to emit their own events.\n * @param {string} name The name of the custom event\n * @param {object} detail Optional event details\n */\n dispatchCustomEvent(name, detail = {}) {\n this.dispatchEvent(\n new CustomEvent(`Alchemy.${name}`, { bubbles: true, detail })\n )\n }\n\n get allowClear() {\n return this.hasAttribute(\"allow-clear\")\n }\n\n get selection() {\n return this.getAttribute(\"selection\")\n }\n\n get placeholder() {\n return this.getAttribute(\"placeholder\") ?? \"\"\n }\n\n get queryParams() {\n return this.getAttribute(\"query-params\") ?? \"{}\"\n }\n\n get url() {\n return this.getAttribute(\"url\") ?? \"\"\n }\n\n get input() {\n return this.getElementsByTagName(\"input\")[0]\n }\n\n get select2Config() {\n return {\n placeholder: this.placeholder,\n allowClear: this.allowClear,\n initSelection: (_$el, callback) => {\n if (this.selection) {\n callback(JSON.parse(this.selection))\n }\n },\n ajax: this.ajaxConfig,\n formatSelection: (item) => this._renderResult(item),\n formatResult: (item, _el, query) =>\n this._renderListEntry(item, query.term)\n }\n }\n\n /**\n * Ajax configuration for Select2\n * @returns {object}\n */\n get ajaxConfig() {\n return {\n url: this.url,\n datatype: \"json\",\n quietMillis: 300,\n data: (term, page) => this._searchQuery(term, page),\n results: (response) => this._parseResponse(response)\n }\n }\n\n /**\n * Search query send to server from select2\n * @param {string} term\n * @param {number} page\n * @returns {object}\n * @private\n */\n _searchQuery(term, page) {\n return {\n q: {\n name_cont: term,\n ...JSON.parse(this.queryParams)\n },\n page: page\n }\n }\n\n /**\n * Parses server response into select2 results object\n * @param {object} response\n * @returns {object}\n * @private\n */\n _parseResponse(response) {\n const meta = response.meta\n return {\n results: response.data,\n more: meta.page * meta.per_page < meta.total_count\n }\n }\n\n /**\n * result which is visible if a page was selected\n * @param {object} item\n * @returns {string}\n * @private\n */\n _renderResult() {\n throw new Error(\n \"You need to define a _renderResult function on your sub class!\"\n )\n }\n\n /**\n * html template for each list entry\n * @param {object} item\n * @param {string} term\n * @returns {string}\n * @private\n */\n _renderListEntry() {\n throw new Error(\n \"You need to define a _renderListEntry function on your sub class!\"\n )\n }\n\n /**\n * hightlighted search term\n * @param {string} name\n * @param {string} term\n * @returns {string}\n * @private\n */\n _hightlightTerm(name, term) {\n return hightlightTerm(name, term)\n }\n}\n","import { RemoteSelect } from \"alchemy_admin/components/remote_select\"\n\nclass AttachmentSelect extends RemoteSelect {\n _renderResult(item) {\n return this._renderListEntry(item)\n }\n\n /**\n * html template for each list entry\n * @param {object} page\n * @param {string} term\n * @returns {string}\n * @private\n */\n _renderListEntry(attachment, term) {\n return `\n <div class=\"attachment-select--attachment\">\n <alchemy-icon name=\"${attachment.icon_css_class}\"></alchemy-icon>\n <span class=\"attachment-select--attachment-name\">${this._hightlightTerm(attachment.name, term)}</span>\n </div>\n `\n }\n}\n\ncustomElements.define(\"alchemy-attachment-select\", AttachmentSelect)\n","// Dispatch a submit event on change of input or select elements\n// contained in a form, so that Turbo can submit the form.\nclass AutoSubmit extends HTMLElement {\n connectedCallback() {\n // Still using jQuery here, because select2 does not emit\n // the event from the original select element.\n $(this).on(\"change\", this.#onChange)\n }\n\n disconnectedCallback() {\n $(this).off(\"change\", this.#onChange)\n }\n\n #onChange = (event) => {\n // We need to dispatch a submit event, so that Turbo that listens\n // to it submits the search form us.\n const submitEvent = new Event(\"submit\", {\n bubbles: true,\n cancelable: true\n })\n event.target.form.dispatchEvent(submitEvent)\n return false\n }\n}\n\ncustomElements.define(\"alchemy-auto-submit\", AutoSubmit)\n","import Spinner from \"alchemy_admin/spinner\"\n\nclass Button extends HTMLButtonElement {\n connectedCallback() {\n if (this.form) {\n this.form.addEventListener(\"submit\", this)\n\n if (this.form.dataset.remote == \"true\") {\n this.form.addEventListener(\"ajax:complete\", this)\n }\n\n this.form.addEventListener(\"turbo:submit-end\", this)\n } else {\n console.warn(\"No form for button found!\", this)\n }\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"submit\":\n const isDisabled = this.getAttribute(\"disabled\") === \"disabled\"\n\n if (isDisabled) {\n event.preventDefault()\n event.stopPropagation()\n } else {\n this.disable()\n }\n break\n case \"ajax:complete\":\n case \"turbo:submit-end\":\n this.enable()\n break\n }\n }\n\n disable() {\n const spinner = new Spinner(\"small\")\n const rect = this.getBoundingClientRect()\n\n this.dataset.initialButtonText = this.innerHTML\n this.setAttribute(\"disabled\", \"disabled\")\n this.setAttribute(\"tabindex\", \"-1\")\n this.classList.add(\"disabled\")\n this.style.width = `${rect.width}px`\n this.style.height = `${rect.height}px`\n this.innerHTML = \"&nbsp;\"\n\n spinner.spin(this)\n }\n\n enable() {\n this.classList.remove(\"disabled\")\n this.removeAttribute(\"disabled\")\n this.removeAttribute(\"tabindex\")\n this.style.width = null\n this.style.height = null\n this.innerHTML = this.dataset.initialButtonText\n }\n}\n\ncustomElements.define(\"alchemy-button\", Button, { extends: \"button\" })\n","/**\n * Show the character counter below input fields and textareas\n */\nimport { translate } from \"alchemy_admin/i18n\"\n\nclass CharCounter extends HTMLElement {\n connectedCallback() {\n this.translation = translate(\"allowed_chars\", this.maxChars)\n this.formField = this.getFormField()\n\n if (this.formField) {\n this.createDisplayElement()\n this.countCharacters()\n this.formField.addEventListener(\"keyup\", this)\n }\n }\n\n disconnectedCallback() {\n this.formField?.removeEventListener(\"keyup\", this)\n }\n\n handleEvent(event) {\n if (event.type === \"keyup\") this.countCharacters()\n }\n\n getFormField() {\n const formFields = this.querySelectorAll(\"input, textarea\")\n return formFields.length > 0 ? formFields[0] : undefined\n }\n\n createDisplayElement() {\n this.display = this.querySelector(\":scope > .alchemy-char-counter\")\n if (this.display) return\n this.display = document.createElement(\"small\")\n this.display.className = \"alchemy-char-counter\"\n this.formField.after(this.display)\n }\n\n countCharacters() {\n const charLength = this.formField.value.length\n this.display.textContent = `${charLength} ${this.translation}`\n this.display.classList.toggle(\"too-long\", charLength > this.maxChars)\n }\n\n get maxChars() {\n return this.getAttribute(\"max-chars\") ?? 60\n }\n}\n\ncustomElements.define(\"alchemy-char-counter\", CharCounter)\n","import \"clipboard\"\nimport { growl } from \"alchemy_admin/growler\"\n\nclass ClipboardButton extends HTMLElement {\n connectedCallback() {\n this.innerHTML = '<alchemy-icon name=\"clipboard\"></alchemy-icon>'\n\n this.clipboard = new ClipboardJS(this, {\n text: () => {\n return this.getAttribute(\"content\")\n }\n })\n\n this.clipboard.on(\"success\", () => {\n growl(this.getAttribute(\"success-text\"))\n })\n }\n\n disconnectedCallback() {\n this.clipboard.destroy()\n }\n}\n\ncustomElements.define(\"alchemy-clipboard-button\", ClipboardButton)\n","const formatItem = (object) => {\n const optionEl = object.element[0]\n const swatch = optionEl.dataset.swatch || optionEl.value\n const customColor = optionEl.value === \"custom_color\"\n const colorIndicator = customColor\n ? `<alchemy-icon name=\"palette\"></alchemy-icon>`\n : `<span class=\"color-indicator\" style=\"--color: ${swatch}\"></span>`\n\n return `\n <div class=\"select-color-option\">\n ${colorIndicator}\n <span>${object.text}</span>\n </div>`\n}\n\nclass ColorSelect extends HTMLElement {\n #select2 = null\n\n connectedCallback() {\n if (this.select) {\n this.#initializeSelect2()\n this.#select2.on(\"change\", this.#onSelectChange)\n } else {\n this.colorInput?.addEventListener(\"input\", this)\n this.textInput?.addEventListener(\"input\", this)\n this.#toggleColorPicker(true)\n }\n }\n\n handleEvent(event) {\n switch (event.target) {\n case this.colorInput:\n this.textInput.value = this.colorInput.value\n break\n case this.textInput:\n this.colorInput.value = this.textInput.value\n break\n }\n }\n\n disconnectedCallback() {\n this.colorInput?.removeEventListener(\"input\", this)\n this.textInput?.removeEventListener(\"input\", this)\n if (this.#select2) {\n this.#select2.off(\"change\", this.#onSelectChange)\n this.#select2.select2(\"destroy\")\n this.#select2 = null\n }\n }\n\n #onSelectChange = (event) => {\n this.#toggleColorPicker(event.val === \"custom_color\")\n }\n\n #initializeSelect2() {\n this.select.classList.add(\"alchemy_selectbox\")\n const options = {\n minimumResultsForSearch: 10,\n formatResult: formatItem,\n formatSelection: formatItem\n }\n this.#select2 = $(this.select).select2(options)\n }\n\n #toggleColorPicker(enabled = true) {\n this.colorInput.disabled = !enabled\n }\n\n get colorInput() {\n return this.querySelector(\"input[type='color']\")\n }\n\n get textInput() {\n return this.querySelector(\"input[type='text']\")\n }\n\n get select() {\n return this.querySelector(\"select\")\n }\n}\n\ncustomElements.define(\"alchemy-color-select\", ColorSelect)\n","import { translate, currentLocale } from \"alchemy_admin/i18n\"\nimport flatpickr from \"flatpickr\"\n\nconst locale = currentLocale()\n\nclass Datepicker extends HTMLElement {\n // Load the locales for flatpickr before setting it up.\n async connectedCallback() {\n // English is the default locale for flatpickr, so we don't need to load it\n if (locale !== \"en\") {\n await import(`flatpickr/${locale}.js`)\n }\n // Bail out if the element was disconnected while the locale was loading.\n // Otherwise flatpickr would leak a calendar onto a detached input.\n if (!this.isConnected) return\n\n this.flatpickr = flatpickr(this.inputField, this.flatpickrOptions)\n }\n\n disconnectedCallback() {\n this.flatpickr?.destroy()\n }\n\n get flatpickrOptions() {\n const enableTime = /time/.test(this.inputType)\n const options = {\n // alchemy_i18n supports `zh_CN` etc., but flatpickr only has two-letter codes (`zh`)\n locale: locale.slice(0, 2),\n altInput: true,\n altFormat: translate(`formats.${this.inputType}`),\n altInputClass: \"flatpickr-input\",\n enableTime,\n noCalendar: this.inputType === \"time\",\n time_24hr: translate(\"formats.time_24hr\"),\n onValueUpdate(_selectedDates, _dateStr, instance) {\n instance.element\n .closest(\"alchemy-element-editor\")\n ?.setDirty(this.inputField)\n }\n }\n\n if (enableTime) {\n options.dateFormat = \"Z\"\n }\n\n return options\n }\n\n get inputField() {\n return this.querySelector(\"input\")\n }\n\n get inputType() {\n return this.getAttribute(\"input-type\") || \"date\"\n }\n}\n\ncustomElements.define(\"alchemy-datepicker\", Datepicker)\n","import { Dialog } from \"alchemy_admin/dialog\"\n\nexport class DialogLink extends HTMLAnchorElement {\n connectedCallback() {\n this.addEventListener(\"click\", this)\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"click\", this)\n }\n\n handleEvent(evt) {\n if (!this.disabled) {\n this.openDialog()\n }\n evt.preventDefault()\n }\n\n openDialog() {\n this.dialog = new Dialog(this.getAttribute(\"href\"), this.dialogOptions)\n this.dialog.open()\n }\n\n get dialogOptions() {\n const options = this.dataset.dialogOptions\n ? JSON.parse(this.dataset.dialogOptions)\n : {}\n return options\n }\n\n get disabled() {\n return this.classList.contains(\"disabled\")\n }\n}\n\ncustomElements.define(\"alchemy-dialog-link\", DialogLink, { extends: \"a\" })\n","const JSON_CONTENT_TYPE = \"application/json\"\nconst TURBO_STREAM_CONTENT_TYPE = \"text/vnd.turbo-stream.html\"\n\nfunction isGetRequest(method) {\n return method.toLowerCase() === \"get\"\n}\n\nfunction prepareURL(path, data, method) {\n const url = new URL(window.location.origin + path)\n\n if (data && isGetRequest(method)) {\n url.search = new URLSearchParams(data).toString()\n }\n\n return url.toString()\n}\n\nfunction prepareHeaders(accept) {\n return {\n \"Content-Type\": \"application/json; charset=utf-8\",\n Accept: accept,\n \"X-Requested-With\": \"XMLHttpRequest\",\n \"X-CSRF-Token\": getToken()\n }\n}\n\nfunction prepareOptions(method, data, accept) {\n const headers = prepareHeaders(accept)\n const options = { method, headers }\n\n if (data && !isGetRequest(method)) {\n options.body = JSON.stringify(data)\n }\n\n return options\n}\n\nexport function getToken() {\n const metaTag = document.querySelector('meta[name=\"csrf-token\"]')\n return metaTag.attributes.content.textContent\n}\n\nexport function get(url, params) {\n return ajax(\"GET\", url, params)\n}\n\nexport function patch(url, data, accept) {\n return ajax(\"PATCH\", url, data, accept)\n}\n\nexport function post(url, data, accept = JSON_CONTENT_TYPE) {\n return ajax(\"POST\", url, data, accept)\n}\n\nexport default async function ajax(\n method,\n path,\n data,\n accept = JSON_CONTENT_TYPE\n) {\n const response = await fetch(\n prepareURL(path, data, method),\n prepareOptions(method, data, accept)\n )\n const contentType = response.headers.get(\"content-type\")\n const isJson = contentType?.includes(JSON_CONTENT_TYPE)\n const isTurboStream = contentType?.includes(TURBO_STREAM_CONTENT_TYPE)\n\n let responseData = null\n if (isJson) {\n responseData = await response.json()\n } else if (isTurboStream) {\n responseData = await response.text()\n // Automatically render Turbo Stream if Turbo is available\n if (typeof Turbo !== \"undefined\") {\n Turbo.renderStreamMessage(responseData)\n }\n }\n\n if (response.ok) {\n return { data: responseData, status: response.status }\n } else {\n throw responseData || new Error(\"An error occurred during the transaction\")\n }\n}\n","import { get } from \"alchemy_admin/utils/ajax\"\nimport { translate } from \"alchemy_admin/i18n\"\n\nclass DomIdSelect extends HTMLElement {\n dataItem(hash) {\n return {\n id: `#${hash}`,\n text: `#${hash}`\n }\n }\n\n get selectElement() {\n return this.querySelector('select[is=\"alchemy-select\"]')\n }\n}\n\nclass DomIdApiSelect extends DomIdSelect {\n #pageId = undefined\n\n connectedCallback() {\n this.page = this.getAttribute(\"page\")\n }\n\n async #fetchDomIds() {\n const result = await get(Alchemy.routes.api_ingredients_path, {\n page_id: this.#pageId\n })\n const options = result.data.ingredients\n .filter((ingredient) => ingredient.data?.dom_id)\n .map((ingredient) => this.dataItem(ingredient.data.dom_id))\n const prompt =\n options.length > 0 ? translate(\"None\") : translate(\"No anchors found\")\n\n this.selectElement.setOptions(options, prompt)\n this.selectElement.enable()\n }\n\n #reset() {\n // wait a tick to initialize the alchemy-select\n requestAnimationFrame(() => {\n this.selectElement.disable()\n this.selectElement.setOptions([], translate(\"Select a page first\"))\n })\n }\n\n set page(pageId) {\n this.#pageId = pageId\n pageId ? this.#fetchDomIds() : this.#reset()\n }\n}\n\nclass DomIdPreviewSelect extends DomIdSelect {\n connectedCallback() {\n // wait a tick to let the browser initialize the inner select component\n requestAnimationFrame(() => {\n const frame = document.getElementById(\"alchemy_preview_window\")\n const elements = frame.contentDocument?.querySelectorAll(\"[id]\") || []\n if (elements.length > 0) {\n const options = Array.from(elements).map((element) => {\n return this.dataItem(element.id)\n })\n this.selectElement.setOptions(options, translate(\"None\"))\n }\n })\n }\n}\n\ncustomElements.define(\"alchemy-dom-id-api-select\", DomIdApiSelect)\ncustomElements.define(\"alchemy-dom-id-preview-select\", DomIdPreviewSelect)\n","export class PublishElementButton extends HTMLElement {\n #scheduleButtonVariant\n\n connectedCallback() {\n this.#scheduleButtonVariant = this.scheduleButton.getAttribute(\"variant\")\n this.publishButton.addEventListener(\"click\", this)\n this.dropdown.addEventListener(\"sl-show\", this)\n this.dropdown.addEventListener(\"sl-hide\", this)\n }\n\n disconnectedCallback() {\n this.publishButton.removeEventListener(\"click\", this)\n this.dropdown.removeEventListener(\"sl-show\", this)\n this.dropdown.removeEventListener(\"sl-hide\", this)\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"click\":\n this.publishButton.loading = true\n break\n case \"sl-show\":\n this.scheduleButton.setAttribute(\"variant\", \"primary\")\n break\n case \"sl-hide\":\n this.scheduleButton.setAttribute(\"variant\", this.#scheduleButtonVariant)\n break\n }\n }\n\n get publishButton() {\n return this.querySelector(\"sl-button[type='submit']\")\n }\n\n get dropdown() {\n return this.querySelector(\"sl-dropdown\")\n }\n\n get scheduleButton() {\n return this.querySelector(\"sl-button[slot='trigger']\")\n }\n}\n\ncustomElements.define(\"alchemy-publish-element-button\", PublishElementButton)\n","import ajax from \"alchemy_admin/utils/ajax\"\nimport { removeTab } from \"alchemy_admin/fixed_elements\"\nimport { growl } from \"alchemy_admin/growler\"\nimport { reloadPreview } from \"alchemy_admin/components/preview_window\"\nimport { openConfirmDialog } from \"alchemy_admin/confirm_dialog\"\nimport { dispatchPageDirtyEvent } from \"alchemy_admin/components/element_editor\"\n\nexport class DeleteElementButton extends HTMLElement {\n connectedCallback() {\n this.button?.addEventListener(\"click\", this)\n }\n\n disconnectedCallback() {\n this.button?.removeEventListener(\"click\", this)\n }\n\n async handleEvent() {\n const confirmed = await openConfirmDialog(this.message)\n if (confirmed) {\n const response = await ajax(\"DELETE\", this.url)\n this.#removeElement(response.data)\n }\n }\n\n #removeElement(data) {\n const elementEditor = this.closest(\"alchemy-element-editor\")\n elementEditor.addEventListener(\"transitionend\", () => {\n if (elementEditor.fixed) {\n removeTab(elementEditor.elementId)\n }\n elementEditor.remove()\n })\n elementEditor.classList.add(\"dismiss\")\n growl(data.message)\n if (data.pageHasUnpublishedChanges) {\n dispatchPageDirtyEvent(data)\n }\n reloadPreview()\n }\n\n get url() {\n return this.getAttribute(\"href\")\n }\n\n get message() {\n return this.getAttribute(\"message\")\n }\n\n get button() {\n return this.querySelector(\"button\")\n }\n}\n\ncustomElements.define(\"alchemy-delete-element-button\", DeleteElementButton)\n","import IngredientAnchorLink from \"alchemy_admin/ingredient_anchor_link\"\nimport { post } from \"alchemy_admin/utils/ajax\"\nimport { createHtmlElement } from \"alchemy_admin/utils/dom_helpers\"\nimport { growl } from \"alchemy_admin/growler\"\n\nimport \"alchemy_admin/components/element_editor/publish_element_button\"\nimport \"alchemy_admin/components/element_editor/delete_element_button\"\n\nexport function dispatchPageDirtyEvent(data) {\n document.dispatchEvent(\n new CustomEvent(\"alchemy:page-dirty\", {\n detail: { tooltip: data.publishButtonTooltip }\n })\n )\n}\n\nexport class ElementEditor extends HTMLElement {\n #form = null\n #header = null\n #toggleButton = null\n\n connectedCallback() {\n // The placeholder while be being dragged is empty.\n if (this.classList.contains(\"ui-sortable-placeholder\")) {\n return\n }\n\n // Add event listeners\n this.addEventListener(\"click\", this)\n // Triggered by child elements\n this.addEventListener(\"alchemy:element-update-title\", this)\n // We use of @rails/ujs for Rails remote forms\n this.addEventListener(\"ajax:complete\", this)\n\n // Dirty observer still needs to be jQuery\n // in order to support select2.\n this.#form = this.form\n if (this.#form) {\n $(this.#form).on(\"change\", this.onChange)\n }\n\n this.#header = this.header\n this.#header?.addEventListener(\"dblclick\", this.#onHeaderDblclick)\n\n this.#toggleButton = this.toggleButton\n this.#toggleButton?.addEventListener(\"click\", this.#onToggleClick)\n\n // When newly created, focus the element and refresh the preview\n if (this.hasAttribute(\"created\")) {\n this.focusElement()\n this.previewWindow?.refresh().then(() => {\n this.focusElementPreview()\n })\n this.removeAttribute(\"created\")\n }\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"click\", this)\n this.removeEventListener(\"alchemy:element-update-title\", this)\n this.removeEventListener(\"ajax:complete\", this)\n if (this.#form) {\n $(this.#form).off(\"change\", this.onChange)\n this.#form = null\n }\n this.#header?.removeEventListener(\"dblclick\", this.#onHeaderDblclick)\n this.#header = null\n this.#toggleButton?.removeEventListener(\"click\", this.#onToggleClick)\n this.#toggleButton = null\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"click\":\n const elementEditor = event.target.closest(\"alchemy-element-editor\")\n if (elementEditor === this) {\n this.onClickElement()\n }\n break\n case \"ajax:complete\":\n if (event.target === this.body) {\n const xhr = event.detail[0]\n event.stopPropagation()\n this.onSaveElement(xhr)\n }\n break\n case \"alchemy:element-update-title\":\n if (!this.hasEditors && event.target == this.firstChild) {\n this.setTitle(event.detail.title)\n }\n break\n }\n }\n\n onChange = (event) => {\n const target = event.target\n // SortableJS fires a native change event :/\n // and we do not want to set the element editor dirty\n // when this happens\n if (target.classList.contains(\"nested-elements\")) {\n return\n }\n this.setDirty(target)\n event.stopPropagation()\n return false\n }\n\n /**\n * Scrolls to and highlights element\n * Expands if collapsed\n * Also chooses the right fixed elements tab, if necessary.\n * Can be triggered through custom event 'FocusElementEditor.Alchemy'\n * Used by the elements on click events in the preview frame.\n */\n async focusElement() {\n // Select tab if necessary\n if (document.querySelector(\"#fixed-elements\")) {\n await this.selectTabForElement()\n }\n // Expand if necessary\n await this.expand()\n this.selectElement(true)\n }\n\n focusElementPreview() {\n this.previewWindow?.postMessage({\n message: \"Alchemy.focusElement\",\n element_id: this.elementId\n })\n }\n\n onClickElement() {\n this.selectElement()\n this.focusElementPreview()\n }\n\n /**\n * Sets the element to saved state\n * Updates title\n * JS event bubbling will also update the parents element quote.\n * Shows error messages if ingredient validations fail\n * @argument {XMLHttpRequest} xhr\n */\n onSaveElement(xhr) {\n const data = JSON.parse(xhr.responseText)\n // Reset errors that might be visible from last save attempt\n this.setClean()\n // If validation failed\n if (xhr.status === 422) {\n const warning = data.warning\n // Create error messages\n // Mark ingredients as failed\n data.ingredientsWithErrors.forEach((ingredient) => {\n const ingredientEditor = this.querySelector(\n `[data-ingredient-id=\"${ingredient.id}\"]`\n )\n const errorDisplay = createHtmlElement(\n `<small class=\"error\">${ingredient.errorMessage}</small>`\n )\n ingredientEditor?.appendChild(errorDisplay)\n ingredientEditor?.classList.add(\"validation_failed\")\n })\n // Show message\n growl(warning, \"warn\")\n this.elementErrors.classList.remove(\"hidden\")\n } else {\n growl(data.notice)\n this.previewWindow?.refresh().then(() => {\n this.focusElementPreview()\n })\n this.updateTitle(data.previewText)\n data.ingredientAnchors.forEach((anchor) => {\n IngredientAnchorLink.updateIcon(anchor.ingredientId, anchor.active)\n })\n if (data.pageHasUnpublishedChanges) {\n dispatchPageDirtyEvent(data)\n }\n }\n }\n\n /**\n * Smoothly scrolls to element\n */\n scrollToElement() {\n // The timeout gives the browser some time to calculate the position\n // of nested elements correctly\n setTimeout(() => {\n this.scrollIntoView({\n behavior: \"smooth\"\n })\n }, 50)\n }\n\n /**\n * Highlight element and optionally scroll into view\n * @param {boolean} scroll smoothly scroll element into view. Default (false)\n */\n selectElement(scroll = false) {\n document\n .querySelectorAll(\"alchemy-element-editor.selected\")\n .forEach((el) => {\n el.classList.remove(\"selected\")\n })\n window.requestAnimationFrame(() => {\n this.classList.add(\"selected\")\n })\n if (scroll) this.scrollToElement()\n }\n\n /**\n * Selects tab for given element\n * Resolves the promise if this is done.\n * @returns {Promise}\n */\n selectTabForElement() {\n return new Promise((resolve, reject) => {\n const tabs = document.querySelector(\"#fixed-elements\")\n const panel = this.closest(\"sl-tab-panel\")\n if (tabs && panel) {\n tabs.show(panel.getAttribute(\"name\"))\n resolve()\n } else {\n reject(new Error(\"No tabs present\"))\n }\n })\n }\n\n /**\n * Sets the element into clean (safed) state\n */\n setClean() {\n this.dirty = false\n window.onbeforeunload = null\n this.elementErrors.classList.add(\"hidden\")\n\n if (this.hasEditors) {\n this.body.querySelectorAll(\".ingredient-editor\").forEach((el) => {\n el.classList.remove(\"dirty\", \"validation_failed\")\n el.querySelectorAll(\"small.error\").forEach((e) => e.remove())\n })\n }\n }\n\n /**\n * Sets the element into dirty (unsafed) state\n * @param {HTMLElement} editor\n */\n setDirty(editor) {\n if (this.hasEditors) {\n this.dirty = true\n\n if (!window.onbeforeunload) {\n window.onbeforeunload = (event) => event.preventDefault()\n }\n\n editor?.closest(\".ingredient-editor\")?.classList.add(\"dirty\")\n }\n }\n\n /**\n * Sets the title quote\n * @param {string} title\n */\n setTitle(title) {\n const quote = this.querySelector(\".element-header .preview_text_quote\")\n // Fixed elements have no header, so there is no quote to update.\n if (quote) {\n quote.textContent = title\n }\n }\n\n /**\n * Expands or collapses element editor\n * If the element is dirty (has unsaved changes) it displays a confirm first.\n */\n async toggle() {\n if (this.collapsed) {\n await this.expand()\n } else {\n await this.collapse()\n }\n }\n\n /**\n * Collapses the element editor and persists the state on the server\n * @returns {Promise}\n */\n collapse() {\n if (this.collapsed || this.compact || this.fixed) {\n return Promise.resolve(\"Element is already collapsed.\")\n }\n\n const spinner = new Alchemy.Spinner(\"small\")\n spinner.spin(this.toggleButton)\n this.toggleIcon?.classList?.add(\"hidden\")\n return post(Alchemy.routes.collapse_admin_element_path(this.elementId))\n .then((response) => {\n const data = response.data\n\n this.collapsed = true\n this.toggleButton?.setAttribute(\"title\", data.title)\n\n // Collapse all nested elements if necessarry\n if (data.nestedElementIds.length) {\n const selector = data.nestedElementIds\n .map((id) => `#element_${id}`)\n .join(\", \")\n this.querySelectorAll(selector).forEach((nestedElement) => {\n nestedElement.collapsed = true\n nestedElement.toggleButton?.setAttribute(\"title\", data.title)\n })\n }\n })\n .catch((error) => {\n growl(error.message, \"error\")\n console.error(error)\n })\n .finally(() => {\n this.toggleIcon?.classList?.remove(\"hidden\")\n spinner.stop()\n })\n }\n\n /**\n * Collapses the element editor and persists the state on the server\n * @* @returns {Promise}\n */\n expand() {\n if (this.expanded && !this.compact) {\n return Promise.resolve(\"Element is already expanded.\")\n }\n\n if (this.compact && this.parentElementEditor) {\n return this.parentElementEditor.expand()\n } else {\n const spinner = new Alchemy.Spinner(\"small\")\n spinner.spin(this.toggleButton)\n this.toggleIcon?.classList.add(\"hidden\")\n\n return new Promise((resolve, reject) => {\n post(Alchemy.routes.expand_admin_element_path(this.elementId))\n .then((response) => {\n const data = response.data\n\n // First expand all parent elements if necessary\n if (data.parentElementIds.length) {\n const selector = data.parentElementIds\n .map((id) => `#element_${id}`)\n .join(\", \")\n document.querySelectorAll(selector).forEach((parentElement) => {\n parentElement.collapsed = false\n parentElement.toggleButton?.setAttribute(\"title\", data.title)\n })\n }\n // Finally expand ourselve\n this.collapsed = false\n this.toggleButton?.setAttribute(\"title\", data.title)\n // Resolve the promise that scrolls to the element very last\n resolve()\n })\n .catch((error) => {\n growl(error.message, \"error\")\n console.error(error)\n reject(error)\n })\n .finally(() => {\n this.toggleIcon?.classList?.remove(\"hidden\")\n spinner.stop()\n })\n })\n }\n }\n\n /**\n * Updates the quote in the element header and dispatches event\n * to parent elements\n * @param {string} title\n */\n updateTitle(title) {\n this.setTitle(title)\n this.dispatchEvent(\n new CustomEvent(\"alchemy:element-update-title\", {\n bubbles: true,\n detail: { title }\n })\n )\n }\n\n /**\n * Sets element published or hidden\n * @param {boolean}\n */\n set published(isPublished) {\n if (isPublished) {\n this.classList.remove(\"element-hidden\")\n } else {\n this.classList.add(\"element-hidden\")\n }\n }\n\n /**\n * Is element published or hidden\n * @returns {boolean}\n */\n get published() {\n return !this.classList.contains(\"hidden\")\n }\n\n /**\n * @returns {boolean}\n */\n get compact() {\n return this.getAttribute(\"compact\") !== null\n }\n\n /**\n * @returns {boolean}\n */\n get fixed() {\n return this.getAttribute(\"fixed\") !== null\n }\n\n /**\n * @param {boolean} value\n */\n set collapsed(value) {\n this.classList.toggle(\"folded\", value)\n this.classList.toggle(\"expanded\", !value)\n this.toggleIcon &&\n (this.toggleIcon.name = value ? \"arrow-left-s\" : \"arrow-down-s\")\n }\n\n /**\n * @returns {boolean}\n */\n get collapsed() {\n return this.classList.contains(\"folded\")\n }\n\n /**\n * @returns {boolean}\n */\n get expanded() {\n return !this.collapsed\n }\n\n /**\n * Toggles the dirty class\n *\n * @param {boolean} value\n */\n set dirty(value) {\n this.classList.toggle(\"dirty\", value)\n }\n\n /**\n * Returns the dirty state of this element\n *\n * @returns {boolean}\n */\n get dirty() {\n return this.classList.contains(\"dirty\")\n }\n\n /**\n * Returns the element header\n *\n * @returns {HTMLElement|undefined}\n */\n get header() {\n return this.querySelector(`.element-header`)\n }\n\n /**\n * Returns the immediate body container of this element if present\n *\n * Makes sure it does not return a nested elements body\n * by scoping the selector to this elements id.\n *\n * @returns {HTMLElement|undefined}\n */\n get body() {\n return this.querySelector(this.bodySelector)\n }\n\n get bodySelector() {\n return `#${this.id} > .element-body`\n }\n\n /**\n * Returns the immediate footer container of this element if present\n *\n * Makes sure it does not return a nested elements footer\n * by scoping the selector to this elements id.\n *\n * @returns {HTMLElement|undefined}\n */\n get footer() {\n return this.querySelector(`#${this.id} > .element-footer`)\n }\n\n /**\n * The collapse/expand toggle button\n *\n * @returns {HTMLButtonElement|undefined}\n */\n get toggleButton() {\n return this.querySelector(\".element-toggle\")\n }\n\n /**\n * The collapse/expand toggle buttons icon\n *\n * @returns {HTMLElement|undefined}\n */\n get toggleIcon() {\n return this.toggleButton?.querySelector(\"alchemy-icon\")\n }\n\n /**\n * The validation messages list container\n *\n * @returns {HTMLElement}\n */\n get elementErrors() {\n return this.body.querySelector(\".element_errors\")\n }\n\n /**\n * The element database id\n *\n * @returns {string}\n */\n get elementId() {\n return this.dataset.elementId\n }\n\n /**\n * The element defintion name\n *\n * @returns {string}\n */\n get elementName() {\n return this.dataset.elementName\n }\n\n /**\n * Does this element have ingredient editor fields?\n *\n * @returns {boolean}\n */\n get hasEditors() {\n return !!this.body?.querySelector(\".element-ingredient-editors\")\n }\n\n /**\n * Does this element have nested elements?\n *\n * @returns {boolean}\n */\n get hasChildren() {\n return !!this.querySelector(\".nested-elements\")\n }\n\n /**\n * The first child element editor if present\n *\n * @returns {HTMLButtonElement|undefined}\n */\n get firstChild() {\n return this.querySelector(\"alchemy-element-editor\")\n }\n\n /**\n * The form element if present\n *\n * @returns {HTMLFormElement|undefined}\n */\n get form() {\n return this.querySelector(\"form.element-body\")\n }\n\n /**\n * The parent element editor if present\n *\n * @returns {ElementEditor|undefined}\n */\n get parentElementEditor() {\n return this.parentElement?.closest(\"alchemy-element-editor\")\n }\n\n get previewWindow() {\n return document.getElementById(\"alchemy_preview_window\")\n }\n\n #onHeaderDblclick = () => {\n this.toggle()\n }\n\n #onToggleClick = (evt) => {\n const elementEditor = evt.target.closest(\"alchemy-element-editor\")\n if (elementEditor === this) {\n this.toggle()\n }\n }\n}\n\ncustomElements.define(\"alchemy-element-editor\", ElementEditor)\n","import { hightlightTerm } from \"alchemy_admin/components/remote_select\"\n\nconst formatSelection = (option) => {\n return `\n <div class=\"element-select-name\">\n ${option.icon}<span>${option.text}</span>\n </div>\n `\n}\n\nconst formatItem = (icon, text, hint) => {\n const description = hint\n ? `<div class=\"element-select-description\">${hint}</div>`\n : \"\"\n return `\n <div class=\"element-select-item\">\n ${formatSelection({ icon, text })}\n ${description}\n </div>\n `\n}\n\nclass ElementSelect extends HTMLElement {\n #select2 = null\n\n connectedCallback() {\n const results = this.options\n const options = {\n minimumResultsForSearch: 3,\n dropdownAutoWidth: true,\n data() {\n return { results }\n },\n formatResult: (option, _el, search) => {\n let text\n\n if (option.id === \"\") return option.text\n if (search.term !== \"\") {\n text = hightlightTerm(option.text, search.term)\n } else {\n text = option.text\n }\n\n return formatItem(option.icon, text, option.hint)\n },\n formatSelection,\n placeholder: this.placeholder\n }\n this.#select2 = $(this.inputField).select2(options)\n }\n\n disconnectedCallback() {\n this.#select2?.select2(\"destroy\")\n this.#select2 = null\n }\n\n get options() {\n return JSON.parse(this.getAttribute(\"options\"))\n }\n\n get placeholder() {\n return this.getAttribute(\"placeholder\")\n }\n\n get inputField() {\n return this.querySelector(\"input\")\n }\n}\n\ncustomElements.define(\"alchemy-element-select\", ElementSelect)\n","import { ElementEditor } from \"alchemy_admin/components/element_editor\"\n\nclass ElementsWindow extends HTMLElement {\n #visible = true\n #turboFrame = null\n\n connectedCallback() {\n this.toggleButton?.addEventListener(\"click\", this.#onToggleClick)\n this.collapseButton?.addEventListener(\"click\", this.#onCollapseClick)\n window.addEventListener(\"message\", this.#onWindowMessage)\n document.body.addEventListener(\"click\", this.#onBodyClick)\n if (window.location.hash) {\n this.focusElementEditor(window.location.hash)\n }\n this.resize()\n }\n\n disconnectedCallback() {\n this.toggleButton?.removeEventListener(\"click\", this.#onToggleClick)\n this.collapseButton?.removeEventListener(\"click\", this.#onCollapseClick)\n window.removeEventListener(\"message\", this.#onWindowMessage)\n document.body.removeEventListener(\"click\", this.#onBodyClick)\n }\n\n #onToggleClick = (evt) => {\n evt.preventDefault()\n this.toggle()\n }\n\n #onCollapseClick = () => {\n this.collapseAllElements()\n }\n\n #onWindowMessage = (event) => {\n const data = event.data\n if (data?.message == \"Alchemy.focusElementEditor\") {\n const element = document.getElementById(`element_${data.element_id}`)\n this.show()\n element?.focusElement()\n }\n }\n\n #onBodyClick = (evt) => {\n if (!evt.target.closest(\"alchemy-element-editor\")) {\n this.querySelectorAll(\"alchemy-element-editor\").forEach((editor) => {\n editor.classList.remove(\"selected\")\n })\n this.previewWindow?.postMessage({ message: \"Alchemy.blurElements\" })\n }\n }\n\n collapseAllElements() {\n this.querySelectorAll(\n \"alchemy-element-editor:not([compact]):not([fixed])\"\n ).forEach((editor) => editor.collapse())\n }\n\n toggle() {\n this.#visible ? this.hide() : this.show()\n }\n\n show() {\n document.body.classList.add(\"elements-window-visible\")\n this.#visible = true\n this.toggleButton.closest(\"sl-tooltip\").content = Alchemy.t(\"Hide elements\")\n this.toggleButton\n .querySelector(\"alchemy-icon\")\n .setAttribute(\"name\", \"menu-unfold\")\n this.resize()\n }\n\n hide() {\n document.body.classList.remove(\"elements-window-visible\")\n document.body.style.removeProperty(\"--elements-window-width\")\n this.#visible = false\n this.toggleButton.closest(\"sl-tooltip\").content = Alchemy.t(\"Show elements\")\n this.toggleButton\n .querySelector(\"alchemy-icon\")\n .setAttribute(\"name\", \"menu-fold\")\n }\n\n resize(width) {\n if (width === undefined) {\n width = this.widthFromCookie\n }\n\n if (width) {\n document.body.style.setProperty(\"--elements-window-width\", `${width}px`)\n document.cookie = `alchemy-elements-window-width=${width}; SameSite=Lax; Path=/;`\n }\n }\n\n // Focus element editor and element in preview if URL contains hash to element editor.\n // The link is coming from the assignment view when showing assigned files or pictures.\n focusElementEditor(dom_id) {\n const el = document.querySelector(dom_id)\n\n if (el instanceof ElementEditor) {\n el.focusElement() && el.focusElementPreview()\n }\n }\n\n get collapseButton() {\n return this.querySelector(\"#collapse-all-elements-button\")\n }\n\n get toggleButton() {\n return document.querySelector(\"#element_window_button\")\n }\n\n get previewWindow() {\n return document.getElementById(\"alchemy_preview_window\")\n }\n\n get turboFrame() {\n if (!this.#turboFrame) {\n this.#turboFrame = this.closest(\"turbo-frame\")\n }\n return this.#turboFrame\n }\n\n get widthFromCookie() {\n return document.cookie\n .split(\"; \")\n .find((row) => row.startsWith(\"alchemy-elements-window-width=\"))\n ?.split(\"=\")[1]\n }\n\n set isDragged(dragged) {\n this.turboFrame.style.transitionProperty = dragged ? \"none\" : null\n this.turboFrame.style.pointerEvents = dragged ? \"none\" : null\n }\n}\n\ncustomElements.define(\"alchemy-elements-window\", ElementsWindow)\n","const MIN_WIDTH = 400\nconst MAX_WIDTH = 1000\nclass ElementsWindowHandle extends HTMLElement {\n #dragging = false\n #elementsWindow = null\n #previewWindow = null\n #minWidth = MIN_WIDTH\n #maxWidth = MAX_WIDTH\n\n connectedCallback() {\n this.addEventListener(\"mousedown\", this)\n window.addEventListener(\"mousemove\", this)\n window.addEventListener(\"mouseup\", this)\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"mousedown\", this)\n window.removeEventListener(\"mousemove\", this)\n window.removeEventListener(\"mouseup\", this)\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"mousedown\":\n event.stopPropagation()\n this.onMouseDown()\n break\n case \"mouseup\":\n this.onMouseUp()\n break\n case \"mousemove\":\n if (this.#dragging) {\n this.onDrag(event.pageX)\n }\n break\n }\n }\n\n onMouseDown() {\n this.#dragging = true\n // Read the resolved min/max width the browser computed from the CSS\n // custom properties (incl. calc() and active media queries) once, so the\n // drag stays clamped to the same bounds the stylesheet defines.\n const styles = getComputedStyle(this.elementsWindow)\n this.#minWidth = parseFloat(styles.minWidth) || MIN_WIDTH\n this.#maxWidth =\n styles.maxWidth === \"none\" ? MAX_WIDTH : parseFloat(styles.maxWidth)\n this.elementsWindow.isDragged = true\n this.previewWindow.isDragged = true\n this.classList.add(\"is-dragged\")\n }\n\n onMouseUp() {\n this.#dragging = false\n this.elementsWindow.isDragged = false\n this.previewWindow.isDragged = false\n this.classList.remove(\"is-dragged\")\n }\n\n onDrag(pageX) {\n const elementWindowWidth = window.innerWidth - pageX\n const width = Math.min(\n Math.max(elementWindowWidth, this.#minWidth),\n this.#maxWidth\n )\n this.elementsWindow.resize(width)\n }\n\n get elementsWindow() {\n if (!this.#elementsWindow) {\n this.#elementsWindow = document.querySelector(\"alchemy-elements-window\")\n }\n return this.#elementsWindow\n }\n\n get previewWindow() {\n if (!this.#previewWindow) {\n this.#previewWindow = document.getElementById(\"alchemy_preview_window\")\n }\n return this.#previewWindow\n }\n}\n\ncustomElements.define(\"alchemy-elements-window-handle\", ElementsWindowHandle)\n","class FileEditor extends HTMLElement {\n connectedCallback() {\n this.deleteLink = this.querySelector(\".remove_file_link\")\n this.fileIcon = this.querySelector(\".file_icon\")\n this.fileName = this.querySelector(\".file_name\")\n this.formFieldId = this.deleteLink?.dataset.formFieldId\n this.formField = this.querySelector(`#${this.formFieldId}`)\n this.deleteLink?.addEventListener(\"click\", this)\n }\n\n disconnectedCallback() {\n this.deleteLink?.removeEventListener(\"click\", this)\n }\n\n handleEvent(event) {\n if (event.type === \"click\") this.removeFile()\n event.stopPropagation()\n }\n\n removeFile() {\n this.formField.value = \"\"\n this.fileIcon.innerHTML = \"\"\n this.fileName.innerHTML = \"\"\n this.deleteLink?.classList.add(\"hidden\")\n this.closest(\"alchemy-element-editor\").setDirty(this.formField)\n }\n}\n\ncustomElements.define(\"alchemy-file-editor\", FileEditor)\n","const DEFAULT_DEBOUNCE_TIME = 150\n\nclass ListFilter extends HTMLElement {\n #debounceTimer\n #filterField = null\n #clearButton = null\n\n connectedCallback() {\n if (this.hotkey) {\n key(this.hotkey, this.#onHotkey)\n }\n this.#filterField = this.filterField\n this.#filterField.addEventListener(\"keyup\", this.#onKeyup)\n this.#filterField.addEventListener(\"focus\", this.#onFocus)\n\n this.#clearButton = this.clearButton\n this.#clearButton.addEventListener(\"click\", this.#onClearClick)\n\n key(\"esc\", \"list_filter\", this.#onEscape)\n }\n\n disconnectedCallback() {\n clearTimeout(this.#debounceTimer)\n this.#filterField?.removeEventListener(\"keyup\", this.#onKeyup)\n this.#filterField?.removeEventListener(\"focus\", this.#onFocus)\n this.#filterField = null\n this.#clearButton?.removeEventListener(\"click\", this.#onClearClick)\n this.#clearButton = null\n if (this.hotkey) {\n key.unbind(this.hotkey)\n }\n key.unbind(\"esc\", \"list_filter\")\n }\n\n filter(term) {\n if (term === \"\") {\n this.clearButton.style.visibility = \"hidden\"\n }\n\n const matchedItems = []\n const itemsToShow = new Set()\n const lowerTerm = term.toLowerCase()\n\n // First pass: find matching items and mark their ancestors as visible too\n this.items.forEach((item) => {\n const name = item.getAttribute(this.nameAttribute)?.toLowerCase()\n // indexOf is much faster then match()\n if (name.indexOf(lowerTerm) !== -1) {\n matchedItems.push(item)\n itemsToShow.add(item)\n // Mark ancestor items as visible so nested matches stay visible\n let ancestor = item.parentElement?.closest(this.itemsSelector)\n while (ancestor) {\n itemsToShow.add(ancestor)\n ancestor = ancestor.parentElement?.closest(this.itemsSelector)\n }\n }\n })\n\n // Second pass: apply visibility\n this.items.forEach((item) => {\n item.classList.toggle(\"hidden\", !itemsToShow.has(item))\n })\n\n // Scroll into view if only one match\n if (matchedItems.length === 1) {\n matchedItems[0].scrollIntoView({ behavior: \"smooth\", block: \"nearest\" })\n }\n }\n\n clear() {\n this.filterField.value = \"\"\n this.clearButton.style.visibility = \"hidden\"\n this.items.forEach((item) => item.classList.remove(\"hidden\"))\n }\n\n get nameAttribute() {\n return this.getAttribute(\"name-attribute\") || \"name\"\n }\n\n get clearButton() {\n return this.querySelector('button[type=\"button\"]')\n }\n\n get filterField() {\n return this.querySelector('input[type=\"text\"]')\n }\n\n get items() {\n return document.querySelectorAll(this.itemsSelector)\n }\n\n get itemsSelector() {\n return this.getAttribute(\"items-selector\")\n }\n\n get debounceTime() {\n return parseInt(this.getAttribute(\"debounce-time\")) || DEFAULT_DEBOUNCE_TIME\n }\n\n get hotkey() {\n return this.getAttribute(\"hotkey\")\n }\n\n #onHotkey = () => {\n this.filterField.focus()\n return false\n }\n\n #onKeyup = () => {\n clearTimeout(this.#debounceTimer)\n this.#debounceTimer = setTimeout(() => {\n const term = this.filterField.value\n this.clearButton.style.visibility = term ? \"visible\" : \"hidden\"\n this.filter(term)\n }, this.debounceTime)\n }\n\n #onFocus = () => key.setScope(\"list_filter\")\n\n #onClearClick = (e) => {\n e.preventDefault()\n this.clear()\n }\n\n #onEscape = () => {\n this.clear()\n this.filterField.blur()\n }\n}\n\ncustomElements.define(\"alchemy-list-filter\", ListFilter)\n","const DISMISS_DELAY = 5000\n\nclass Message extends HTMLElement {\n #dismissTimeoutId = null\n\n handleEvent(event) {\n if (event.type === \"click\") {\n this.dismiss()\n }\n }\n\n connectedCallback() {\n if (!this.querySelector(\":scope > alchemy-icon\")) {\n const closeIcon =\n this.dismissable && this.type === \"error\"\n ? '<alchemy-icon name=\"close\"></alchemy-icon>'\n : \"\"\n this.insertAdjacentHTML(\n \"afterbegin\",\n `<alchemy-icon name=\"${this.iconName}\"></alchemy-icon>${closeIcon}`\n )\n }\n if (this.dismissable || this.type === \"error\") {\n this.addEventListener(\"click\", this)\n }\n if (this.dismissable && this.type !== \"error\") {\n this.#dismissTimeoutId = setTimeout(() => {\n this.dismiss()\n }, this.dismissDelay)\n }\n }\n\n disconnectedCallback() {\n if (this.#dismissTimeoutId !== null) {\n clearTimeout(this.#dismissTimeoutId)\n this.#dismissTimeoutId = null\n }\n }\n\n dismiss() {\n this.addEventListener(\"transitionend\", () => this.remove())\n this.classList.add(\"dismissed\")\n }\n\n get dismissable() {\n return this.hasAttribute(\"dismissable\")\n }\n\n get icon() {\n return this.getAttribute(\"icon\")\n }\n\n get type() {\n return this.getAttribute(\"type\") || \"notice\"\n }\n\n get dismissDelay() {\n return parseInt(\n this.noticesWrapper?.dataset.autoDismissDelay || DISMISS_DELAY\n )\n }\n\n get iconName() {\n switch (this.icon || this.type) {\n case \"warning\":\n case \"warn\":\n case \"alert\":\n return \"alert\"\n case \"notice\":\n return \"check\"\n case \"info\":\n case \"hint\":\n return \"information\"\n case \"error\":\n return \"bug\"\n default:\n return this.type\n }\n }\n\n get noticesWrapper() {\n return this.closest(\"#flash_notices\")\n }\n}\n\ncustomElements.define(\"alchemy-message\", Message)\n","import { growl } from \"alchemy_admin/growler\"\n\nclass Growl extends HTMLElement {\n connectedCallback() {\n growl(this.message, this.getAttribute(\"type\") || \"notice\")\n this.remove()\n }\n\n get message() {\n return this.getAttribute(\"message\") || this.innerHTML\n }\n}\n\ncustomElements.define(\"alchemy-growl\", Growl)\n","class Icon extends HTMLElement {\n static get observedAttributes() {\n return [\"name\", \"size\", \"icon-style\"]\n }\n\n constructor() {\n super()\n this.spriteUrl = document\n .querySelector('link[rel=\"preload\"][as=\"image\"]')\n .getAttribute(\"href\")\n }\n\n connectedCallback() {\n this.render()\n }\n\n attributeChangedCallback() {\n this.render()\n }\n\n render() {\n const sizeClass = this.size ? ` icon--${this.size}` : \"\"\n this.innerHTML = `<svg class=\"icon${sizeClass}\"><use href=\"${this.spriteUrl}#ri-${this.iconName}${this.style}\" /></svg>`\n }\n\n set name(value) {\n this.setAttribute(\"name\", value)\n }\n\n get iconName() {\n return this.getAttribute(\"name\")\n }\n\n get size() {\n return this.getAttribute(\"size\")\n }\n\n get style() {\n const value = this.getAttribute(\"icon-style\")\n switch (value) {\n case \"none\":\n return \"\"\n case null:\n return \"-line\"\n default:\n return `-${value}`\n }\n }\n}\n\ncustomElements.define(\"alchemy-icon\", Icon)\n","export class IngredientGroup extends HTMLDetailsElement {\n #localStorageKey = \"Alchemy.expanded_ingredient_groups\"\n\n connectedCallback() {\n this.addEventListener(\"toggle\", this)\n\n if (this.isInLocalStorage) {\n this.open = true\n }\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"toggle\", this)\n }\n\n /**\n * Toggle visibility of the ingredient fields in this group\n */\n handleEvent() {\n let expanded_ingredient_groups = this.localStorageItem\n\n if (this.open) {\n this.toggleIcon.name = \"arrow-down-s\"\n if (!this.isInLocalStorage) expanded_ingredient_groups.push(this.id)\n } else {\n this.toggleIcon.name = \"arrow-right-s\"\n expanded_ingredient_groups = expanded_ingredient_groups.filter(\n (value) => value !== this.id\n )\n }\n\n localStorage.setItem(\n this.#localStorageKey,\n JSON.stringify(expanded_ingredient_groups)\n )\n }\n\n get isInLocalStorage() {\n return this.localStorageItem.includes(this.id)\n }\n\n get localStorageItem() {\n const item = localStorage.getItem(this.#localStorageKey)\n\n if (!item) return []\n\n try {\n return JSON.parse(item)\n } catch (error) {\n console.error(error)\n return []\n }\n }\n\n get toggleIcon() {\n return this.querySelector(\"alchemy-icon\")\n }\n}\n\ncustomElements.define(\"alchemy-ingredient-group\", IngredientGroup, {\n extends: \"details\"\n})\n","class LinkButton extends HTMLButtonElement {\n connectedCallback() {\n this.addEventListener(\"click\", this)\n this.classList.add(\"icon_button\")\n // Prevent accidental form submits if this component is wrapped inside a form\n this.setAttribute(\"type\", \"button\")\n this.innerHTML = '<alchemy-icon name=\"link\" icon-style=\"m\"></alchemy-icon>'\n }\n\n handleEvent(event) {\n const dialog = new Alchemy.LinkDialog({\n url: this.linkUrl,\n title: this.linkTitle,\n target: this.linkTarget,\n type: this.linkClass\n })\n dialog.open().then((link) => this.setLink(link))\n event.preventDefault()\n }\n\n setLink(link) {\n if (link.url === \"\") {\n this.classList.remove(\"linked\")\n this.dispatchEvent(new CustomEvent(\"alchemy:unlink\", { bubbles: true }))\n } else {\n this.classList.add(\"linked\")\n this.dispatchEvent(\n new CustomEvent(\"alchemy:link\", {\n bubbles: true,\n detail: link\n })\n )\n }\n }\n\n get linkUrl() {\n return this.linkButtons.linkUrlField.value\n }\n\n get linkTitle() {\n return this.linkButtons.linkTitleField.value\n }\n\n get linkTarget() {\n return this.linkButtons.linkTargetField.value\n }\n\n get linkClass() {\n return this.linkButtons.linkClassField.value\n }\n\n get linkButtons() {\n return this.closest(\"alchemy-link-buttons\")\n }\n}\n\ncustomElements.define(\"alchemy-link-button\", LinkButton, { extends: \"button\" })\n","class UnlinkButton extends HTMLButtonElement {\n connectedCallback() {\n this.addEventListener(\"click\", this)\n this.classList.add(\"icon_button\")\n // Prevent accidental form submits if this component is wrapped inside a form\n this.setAttribute(\"type\", \"button\")\n this.linked = this.linked\n this.innerHTML =\n '<alchemy-icon name=\"link-unlink\" icon-style=\"m\"></alchemy-icon>'\n }\n\n handleEvent(event) {\n if (this.linked) {\n this.linked = false\n this.blur()\n this.dispatchEvent(new CustomEvent(\"alchemy:unlink\", { bubbles: true }))\n }\n event.preventDefault()\n }\n\n set linked(isLinked) {\n if (isLinked) {\n this.classList.replace(\"disabled\", \"linked\")\n this.removeAttribute(\"tabindex\")\n } else {\n this.classList.replace(\"linked\", \"disabled\")\n this.setAttribute(\"tabindex\", \"-1\")\n }\n }\n\n get linked() {\n return this.classList.contains(\"linked\")\n }\n}\n\ncustomElements.define(\"alchemy-unlink-button\", UnlinkButton, {\n extends: \"button\"\n})\n","import \"alchemy_admin/components/link_buttons/link_button\"\nimport \"alchemy_admin/components/link_buttons/unlink_button\"\n\nclass LinkButtons extends HTMLElement {\n connectedCallback() {\n this.addEventListener(\"alchemy:link\", this)\n this.addEventListener(\"alchemy:unlink\", this)\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"alchemy:link\", this)\n this.removeEventListener(\"alchemy:unlink\", this)\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"alchemy:link\":\n this.setLink(event.detail)\n break\n case \"alchemy:unlink\":\n this.removeLink()\n }\n event.stopPropagation()\n }\n\n setLink(data) {\n this.linkUrlField.value = data.url\n this.linkUrlField.dispatchEvent(new Event(\"change\"))\n this.linkTitleField.value = data.title\n this.linkClassField.value = data.type\n this.linkTargetField.value = data.target\n\n this.unlinkButton.linked = true\n this.setElementDirty()\n }\n\n removeLink() {\n this.linkUrlField.value = \"\"\n this.linkUrlField.dispatchEvent(new Event(\"change\"))\n this.linkTitleField.value = \"\"\n this.linkClassField.value = \"\"\n this.linkTargetField.value = \"\"\n\n this.linkButton.classList.remove(\"linked\")\n this.unlinkButton.linked = false\n\n this.setElementDirty()\n }\n\n setElementDirty() {\n this.elementEditor.setDirty(this)\n }\n\n get linkButton() {\n return this.querySelector('[is=\"alchemy-link-button\"]')\n }\n\n get unlinkButton() {\n return this.querySelector('[is=\"alchemy-unlink-button\"]')\n }\n\n get ingredientEditor() {\n const ingredientId = this.dataset.ingredientId\n return this.parentElement.closest(`[data-ingredient-id='${ingredientId}']`)\n }\n\n get elementEditor() {\n return this.closest(\"alchemy-element-editor\")\n }\n\n get linkUrlField() {\n return this.ingredientEditor.querySelector(\"[data-link-value]\")\n }\n\n get linkTitleField() {\n return this.ingredientEditor.querySelector(\"[data-link-title]\")\n }\n\n get linkTargetField() {\n return this.ingredientEditor.querySelector(\"[data-link-target]\")\n }\n\n get linkClassField() {\n return this.ingredientEditor.querySelector(\"[data-link-class]\")\n }\n}\n\ncustomElements.define(\"alchemy-link-buttons\", LinkButtons)\n","export function formatFileSize(bytes) {\n let exponent = bytes === 0 ? 0 : Math.floor(Math.log(bytes) / Math.log(1024))\n\n // prevent format higher than GB\n if (exponent > 3) {\n exponent = 3\n }\n\n let value = (bytes / Math.pow(1024, exponent)).toFixed(2)\n return value + \" \" + [\"B\", \"kB\", \"MB\", \"GB\"][exponent]\n}\n","import { RemoteSelect } from \"alchemy_admin/components/remote_select\"\n\nclass NodeSelect extends RemoteSelect {\n _searchQuery(term, page) {\n return {\n filter: {\n name_or_page_name_cont: term,\n ...JSON.parse(this.queryParams)\n },\n page: page\n }\n }\n\n _renderResult(item) {\n return this._renderListEntry(item)\n }\n\n /**\n * html template for each list entry\n * @param {object} node\n * @param {string} term\n * @returns {string}\n * @private\n */\n _renderListEntry(node, term) {\n const ancestors = node.ancestors.map((a) => a.name)\n const seperator = `<alchemy-icon name=\"arrow-right-s\"></alchemy-icon>`\n\n return `\n <div class=\"node-select--node\">\n <alchemy-icon name=\"menu-2\"></alchemy-icon>\n <div class=\"node-select--node-display_name\">\n <span class=\"node-select--node-ancestors\">\n ${ancestors.length > 0 ? ancestors.join(seperator) + seperator : \"\"}\n </span>\n <span class=\"node-select--node-name\">\n ${this._hightlightTerm(node.name, term)}\n </span>\n </div>\n <div class=\"node-select--node-url\">\n ${node.url || \"\"}\n </div>\n </div>\n `\n }\n}\n\ncustomElements.define(\"alchemy-node-select\", NodeSelect)\n","import { formatFileSize } from \"alchemy_admin/utils/format\"\nimport { translate } from \"alchemy_admin/i18n\"\nimport { growl } from \"alchemy_admin/growler\"\n\nexport class FileUpload extends HTMLElement {\n // public — used by callers (Uploader, Progress, tests)\n file = null\n request = null\n progressEventLoaded = 0\n progressEventTotal = 0\n\n // private — backing state for getters/setters\n #valid = true\n #value = 0\n #status = undefined\n #errorMessage = \"\"\n\n connectedCallback() {\n this.innerHTML = `\n <sl-progress-bar value=\"${this.value}\"></sl-progress-bar>\n <div class=\"description\">\n <span class=\"file-name\">${this.file?.name}</span>\n <span class=\"loaded-size\">${this.loadedSize}</span>\n <span class=\"error-message\">${this.errorMessage}</span>\n </div>\n <sl-tooltip content=\"${translate(\"Abort upload\")}\">\n <button class=\"icon_button\" aria-label=\"${translate(\"Abort upload\")}\">\n <alchemy-icon name=\"close\"></alchemy-icon>\n </button>\n </sl-tooltip>\n `\n\n this.querySelector(\"button\").addEventListener(\"click\", () => this.cancel())\n\n if (this.file?.type.includes(\"image\")) {\n const reader = new FileReader()\n reader.readAsDataURL(this.file)\n reader.addEventListener(\"load\", () => {\n const image = new Image()\n image.src = reader.result\n this.prepend(image)\n })\n }\n }\n\n /**\n * Initialize the component with file and request\n * @param {File} file\n * @param {XMLHttpRequest} request\n */\n initialize(file, request) {\n this.file = file\n this.request = request\n this.progressEventTotal = file ? file.size : 0\n this.status = \"in-progress\"\n\n this.#validateFile()\n this.#addRequestEventListener()\n }\n\n /**\n * cancel the upload\n */\n cancel() {\n if (!this.finished) {\n this.status = \"canceled\"\n this.request?.abort()\n this.dispatchCustomEvent(\"FileUpload.Change\")\n }\n }\n\n /**\n * Dispatches a custom event with given name, namespaced under `Alchemy.`.\n * @param {string} name The name of the custom event\n */\n dispatchCustomEvent(name) {\n this.dispatchEvent(new CustomEvent(`Alchemy.${name}`, { bubbles: true }))\n }\n\n /**\n * validate given file with the `Alchemy.uploader_defaults` - configuration\n */\n #validateFile() {\n const config = Alchemy.uploader_defaults\n const maxFileSize = config.file_size_limit * Math.pow(1024, 2) // in Byte\n let errorMessage = undefined\n\n if (this.file?.size > maxFileSize) {\n errorMessage = translate(\"Uploaded bytes exceed file size\")\n }\n\n const allowedFiletypes = this.file?.type.includes(\"image\")\n ? config.allowed_filetypes.alchemy_pictures\n : config.allowed_filetypes.alchemy_attachments\n\n const isFileFormatSupported =\n allowedFiletypes.includes(\"*\") ||\n allowedFiletypes.includes(\n this.file?.type.replace(/^\\w+\\/(\\w+)(\\+\\w+)?/i, \"$1\")\n )\n\n if (!isFileFormatSupported) {\n errorMessage = translate(\"File type not allowed\")\n }\n\n if (errorMessage) {\n this.valid = false\n this.errorMessage = errorMessage\n }\n }\n\n /**\n * register event listeners to react on request changes\n */\n #addRequestEventListener() {\n // prevent errors if the component will be called without a request - object\n if (!this.request) {\n return\n }\n\n // update the progress bar and currently loaded size information\n this.request.upload.onprogress = (progressEvent) => {\n this.progressEvent = progressEvent\n }\n\n // triggers, when the upload is done\n this.request.onload = () => {\n if (this.request.status < 400) {\n this.status = \"successful\"\n growl(this.responseMessage)\n } else {\n this.status = \"failed\"\n this.errorMessage = this.responseMessage\n }\n this.dispatchCustomEvent(\"FileUpload.Change\")\n }\n\n // catch request errors\n this.request.onerror = () => {\n this.errorMessage = translate(\"An error occurred during the transaction\")\n }\n }\n\n /**\n * @returns {boolean}\n */\n get active() {\n return this.valid && this.status !== \"canceled\"\n }\n\n /**\n * @returns {string}\n */\n get errorMessage() {\n return this.#errorMessage || \"\"\n }\n\n /**\n * @param {string} message\n */\n set errorMessage(message) {\n this.#errorMessage = message\n const errorMessageContainer = this.querySelector(\".error-message\")\n if (errorMessageContainer) {\n errorMessageContainer.textContent = message\n }\n growl(message, \"error\")\n }\n\n /**\n * @returns {boolean}\n */\n get finished() {\n return [\"canceled\", \"successful\", \"failed\"].includes(this.status)\n }\n\n /**\n * format the loaded and total size and present that as a string\n * @returns {string}\n */\n get loadedSize() {\n return `${formatFileSize(this.progressEventLoaded)} / ${formatFileSize(\n this.progressEventTotal\n )}`\n }\n\n /**\n * @returns {HTMLProgressElement|undefined}\n */\n get progressElement() {\n return this.querySelector(\"sl-progress-bar\")\n }\n\n /**\n * @param {ProgressEvent} progressEvent\n */\n set progressEvent(progressEvent) {\n this.progressEventLoaded = progressEvent.loaded\n this.progressEventTotal = progressEvent.total\n\n this.value = Math.round((progressEvent.loaded / progressEvent.total) * 100)\n this.querySelector(\".loaded-size\").textContent = this.loadedSize\n }\n\n /**\n * @returns {string}\n */\n get responseMessage() {\n try {\n const response = JSON.parse(this.request.responseText)\n return response[\"message\"]\n } catch (error) {\n return `${this.request.status}: ${this.request.statusText}`\n }\n }\n\n /**\n * @returns {string}\n */\n get status() {\n return this.#status\n }\n\n /**\n * @param {string} status\n */\n set status(status) {\n this.#status = status\n this.className = status\n\n this.progressElement?.toggleAttribute(\n \"indeterminate\",\n status === \"upload-finished\"\n )\n }\n\n /**\n * @returns {boolean}\n */\n get valid() {\n return this.#valid\n }\n\n /**\n * @param {boolean} isValid\n */\n set valid(isValid) {\n this.#valid = isValid\n this.classList.toggle(\"invalid\", !isValid)\n }\n\n /**\n * get the progress value of the current file\n * @returns {number}\n */\n get value() {\n return this.#value\n }\n\n /**\n * @param {number} value\n */\n set value(value) {\n this.#value = value\n if (this.progressElement) {\n this.progressElement.value = value\n }\n\n if (value === 100) {\n this.status = \"upload-finished\"\n }\n\n this.dispatchCustomEvent(\"FileUpload.Change\")\n }\n}\n\ncustomElements.define(\"alchemy-file-upload\", FileUpload)\n","import { FileUpload } from \"alchemy_admin/components/uploader/file_upload\"\nimport { formatFileSize } from \"alchemy_admin/utils/format\"\nimport { translate } from \"alchemy_admin/i18n\"\n\nconst template = (buttonLabel, fileCount) => `\n <sl-progress-bar value=\"0\"></sl-progress-bar>\n <div class=\"overall-progress-value\">\n <span class=\"value-text\"></span>\n\n <sl-tooltip content=\"${buttonLabel}\">\n <button class=\"icon_button\" aria-label=\"${buttonLabel}\">\n <alchemy-icon name=\"close\"></alchemy-icon>\n </button>\n </sl-tooltip>\n </div>\n <div class=\"single-uploads\" style=\"--progress-columns: ${\n fileCount > 3 ? 3 : fileCount\n }\"></div>\n <div class=\"overall-upload-value value-text\"></div>\n`\n\nexport class Progress extends HTMLElement {\n // public — accessed by Uploader and tests\n fileCount = 0\n\n // private — backing state and internals\n #fileUploads = []\n #buttonLabel = translate(\"Cancel all uploads\")\n #actionButton = null\n #visible = false\n #handleFileChange = () => this.#updateView()\n\n connectedCallback() {\n this.innerHTML = template(this.#buttonLabel, this.fileCount)\n this.visible = true\n\n this.#actionButton = this.querySelector(\"button\")\n this.#actionButton.addEventListener(\"click\", () => {\n if (this.finished) {\n this.onComplete(this.status)\n } else {\n this.cancel()\n }\n })\n\n this.#fileUploads.forEach((fileUpload) => {\n this.querySelector(\".single-uploads\").append(fileUpload)\n })\n\n this.#updateView()\n this.addEventListener(\"Alchemy.FileUpload.Change\", this.#handleFileChange)\n }\n\n disconnectedCallback() {\n this.removeEventListener(\n \"Alchemy.FileUpload.Change\",\n this.#handleFileChange\n )\n }\n\n /**\n * Initialize the component with file uploads\n * @param {FileUpload[]} fileUploads\n */\n initialize(fileUploads = []) {\n this.#fileUploads = fileUploads\n this.fileCount = fileUploads.length\n }\n\n /**\n * cancel requests in all remaining uploads\n */\n cancel() {\n this.#activeUploads().forEach((upload) => {\n upload.cancel()\n })\n this.#setupCloseButton()\n }\n\n /**\n * a complete hook to allow the uploader to react and trigger an event\n * it would be possible to trigger the event here, but the dispatching would happen\n * in the scope of that component and can't be cached o uploader - component level\n */\n onComplete(_status) {}\n\n /**\n * get all active upload components\n * @returns {FileUpload[]}\n */\n #activeUploads() {\n return this.#fileUploads.filter((upload) => upload.active)\n }\n\n /**\n * replace cancel button to be the close button\n */\n #setupCloseButton() {\n this.#buttonLabel = translate(\"Close\")\n this.#actionButton.ariaLabel = this.#buttonLabel\n this.#actionButton.parentElement.content = this.#buttonLabel // update tooltip content\n }\n\n /**\n * @param {string} field\n * @returns {number}\n */\n #sumFileProgresses(field) {\n return this.#activeUploads().reduce(\n (accumulator, upload) => upload[field] + accumulator,\n 0\n )\n }\n\n /**\n * don't render the whole element new, because it would prevent selecting buttons\n */\n #updateView() {\n const status = this.status\n this.className = status\n\n // update progress bar\n this.progressElement.value = this.totalProgress\n this.progressElement.toggleAttribute(\n \"indeterminate\",\n status === \"upload-finished\"\n )\n\n // show progress in file size and percentage\n this.querySelector(`.overall-progress-value > span`).textContent =\n this.overallProgressValue\n this.querySelector(`.overall-upload-value`).textContent =\n this.overallUploadSize\n\n if (this.finished) {\n this.#setupCloseButton()\n this.onComplete(status)\n } else {\n this.visible = true\n }\n }\n\n /**\n * @returns {boolean}\n */\n get finished() {\n return this.#activeUploads().every((entry) => entry.finished)\n }\n\n /**\n * @returns {string}\n */\n get overallUploadSize() {\n const uploadedFileCount = this.#activeUploads().filter(\n (fileProgress) => fileProgress.value >= 100\n ).length\n const overallProgressValue = `${\n this.totalProgress\n }% (${uploadedFileCount} / ${this.#activeUploads().length})`\n\n return `${formatFileSize(\n this.#sumFileProgresses(\"progressEventLoaded\")\n )} / ${formatFileSize(this.#sumFileProgresses(\"progressEventTotal\"))}`\n }\n\n /**\n * @returns {string}\n */\n get overallProgressValue() {\n const uploadedFileCount = this.#activeUploads().filter(\n (fileProgress) => fileProgress.value >= 100\n ).length\n return `${this.totalProgress}% (${uploadedFileCount} / ${\n this.#activeUploads().length\n })`\n }\n\n /**\n * @returns {HTMLProgressElement|undefined}\n */\n get progressElement() {\n return this.querySelector(\"sl-progress-bar\")\n }\n\n /**\n * get status of file progresses and accumulate the overall status\n * @returns {string}\n */\n get status() {\n const uploadsStatuses = this.#activeUploads().map(\n (upload) => upload.className\n )\n\n // mark as failed, if any upload failed\n if (uploadsStatuses.includes(\"failed\")) {\n return \"failed\"\n }\n\n // no active upload means that every upload was canceled\n if (uploadsStatuses.length === 0) {\n return \"canceled\"\n }\n\n // all uploads are successful or upload-finished or in-progress\n if (uploadsStatuses.every((entry) => entry === uploadsStatuses[0])) {\n return uploadsStatuses[0]\n }\n\n return \"in-progress\"\n }\n\n /**\n * @returns {number}\n */\n get totalProgress() {\n const totalSize = this.#activeUploads().reduce(\n (accumulator, upload) => accumulator + upload.file.size,\n 0\n )\n let totalProgress = Math.ceil(\n this.#activeUploads().reduce((accumulator, upload) => {\n const weight = upload.file.size / totalSize\n return upload.value * weight + accumulator\n }, 0)\n )\n // prevent rounding errors\n if (totalProgress > 100) {\n totalProgress = 100\n }\n return totalProgress\n }\n\n /**\n * @returns {boolean}\n */\n get visible() {\n return this.#visible\n }\n\n /**\n * @param {boolean} visible\n */\n set visible(visible) {\n this.classList.toggle(\"visible\", visible)\n this.#visible = visible\n }\n}\n\ncustomElements.define(\"alchemy-upload-progress\", Progress)\n","/**\n * @typedef {object} PersistedFile\n * @property {string} name\n * @property {number} size\n */\nimport { Progress } from \"alchemy_admin/components/uploader/progress\"\nimport { FileUpload } from \"alchemy_admin/components/uploader/file_upload\"\nimport { translate } from \"alchemy_admin/i18n\"\nimport { getToken } from \"alchemy_admin/utils/ajax\"\n\nexport class Uploader extends HTMLElement {\n #dropzoneElement = null\n #isDraggedOver = false\n\n connectedCallback() {\n this.fileInput.addEventListener(\"change\", this.#onFileInputChange)\n if (this.dropzone) {\n this.#setupDropZone()\n }\n this.addEventListener(\"Alchemy.upload.successful\", this)\n }\n\n disconnectedCallback() {\n this.fileInput?.removeEventListener(\"change\", this.#onFileInputChange)\n if (this.#dropzoneElement) {\n this.#dropzoneElement.removeEventListener(\n \"dragleave\",\n this.#onDropzoneDragleave\n )\n this.#dropzoneElement.removeEventListener(\"drop\", this.#onDropzoneDrop)\n this.#dropzoneElement.removeEventListener(\n \"dragover\",\n this.#onDropzoneDragover\n )\n this.#dropzoneElement = null\n }\n }\n\n handleEvent(evt) {\n switch (evt.type) {\n case \"Alchemy.upload.successful\":\n this.#handleUploadComplete()\n break\n }\n }\n\n #onFileInputChange = (event) => {\n this.uploadFiles(Array.from(event.target.files))\n }\n\n #toggleDropzoneClass = (enabled) => {\n if (this.#isDraggedOver !== enabled) {\n this.#isDraggedOver = enabled\n this.#dropzoneElement.classList.toggle(\"dragover\")\n }\n }\n\n #onDropzoneDragleave = () => this.#toggleDropzoneClass(false)\n\n #onDropzoneDrop = async (event) => {\n event.preventDefault()\n this.#toggleDropzoneClass(false)\n\n const files = [...event.dataTransfer.items].map((item) => item.getAsFile())\n\n this.uploadFiles(files)\n }\n\n #onDropzoneDragover = (event) => {\n event.preventDefault() // dragover has to be disabled to use the custom drop event\n this.#toggleDropzoneClass(true)\n }\n\n #handleUploadComplete() {\n setTimeout(() => {\n const url = this.redirectUrl\n const turboFrame = this.closest(\"turbo-frame\")\n this.uploadProgress.visible = false\n\n if (!url) return\n\n if (turboFrame) {\n turboFrame.setAttribute(\"src\", url)\n turboFrame.reload()\n } else {\n Turbo.visit(url)\n }\n }, 750)\n }\n\n /**\n * add dragover class to indicate, if the file is draggable\n * @private\n */\n #setupDropZone() {\n this.#dropzoneElement = document.querySelector(this.dropzone)\n if (!this.#dropzoneElement) return\n\n this.#dropzoneElement.addEventListener(\n \"dragleave\",\n this.#onDropzoneDragleave\n )\n this.#dropzoneElement.addEventListener(\"drop\", this.#onDropzoneDrop)\n this.#dropzoneElement.addEventListener(\"dragover\", this.#onDropzoneDragover)\n }\n\n /**\n * @param {File[]} files\n */\n uploadFiles(files) {\n // prepare file progress bars and server request\n let fileUploadCount = 0\n\n const fileUploads = files.map((file) => {\n const request = new XMLHttpRequest()\n const fileUpload = new FileUpload()\n fileUpload.initialize(file, request)\n\n if (Alchemy.uploader_defaults.upload_limit - 1 < fileUploadCount) {\n fileUpload.valid = false\n fileUpload.errorMessage = translate(\"Maximum number of files exceeded\")\n } else if (fileUpload.valid) {\n fileUploadCount++\n this.#submitFile(request, file)\n }\n\n return fileUpload\n })\n\n this.#createProgress(fileUploads)\n }\n\n /**\n * @param {XMLHttpRequest} request\n * @param {File} file\n * @private\n */\n #submitFile(request, file) {\n const form = this.querySelector(\"form\")\n const formData = new FormData(form)\n formData.set(this.fileInput.name, file)\n request.open(\"POST\", form.action)\n request.setRequestHeader(\"X-CSRF-Token\", getToken())\n request.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\")\n request.setRequestHeader(\"Accept\", \"application/json\")\n request.send(formData)\n }\n\n /**\n * create (and maybe remove the old) progress bar - component\n * @param {FileUpload[]} fileUploads\n * @private\n */\n #createProgress(fileUploads) {\n if (this.uploadProgress) {\n this.uploadProgress.cancel()\n document.body.removeChild(this.uploadProgress)\n }\n this.uploadProgress = new Progress()\n this.uploadProgress.initialize(fileUploads)\n this.uploadProgress.onComplete = (status) => {\n this.dispatchEvent(\n new CustomEvent(`Alchemy.upload.${status}`, { bubbles: true })\n )\n }\n\n document.body.append(this.uploadProgress)\n }\n\n get dropzone() {\n return this.getAttribute(\"dropzone\")\n }\n\n /**\n * @returns {HTMLInputElement}\n */\n get fileInput() {\n return this.querySelector(\"input[type='file']\")\n }\n\n get redirectUrl() {\n return this.getAttribute(\"redirect-url\")\n }\n}\n\ncustomElements.define(\"alchemy-uploader\", Uploader)\n","class Overlay extends HTMLElement {\n connectedCallback() {\n this.innerHTML = `\n <alchemy-spinner></alchemy-spinner>\n <div id=\"overlay_text_box\">\n <span id=\"overlay_text\">${this.getAttribute(\"text\") ?? \"\"}</span>\n </div>\n `\n }\n\n set show(value) {\n this.classList.toggle(\"visible\", value)\n }\n}\n\ncustomElements.define(\"alchemy-overlay\", Overlay)\n","import { patch } from \"alchemy_admin/utils/ajax\"\nimport { growl } from \"alchemy_admin/growler\"\nimport Spinner from \"alchemy_admin/spinner\"\n\nconst BUTTON = \"BUTTON\"\nconst SPAN = \"SPAN\"\n\n/**\n * Custom element for page nodes in the sitemap tree\n * Handles folding/unfolding of page children\n */\nexport class AlchemyPageNode extends HTMLElement {\n connectedCallback() {\n this.pageId = this.getAttribute(\"page-id\")\n this.folded = this.hasAttribute(\"folded\")\n\n this.folderButton?.addEventListener(\"click\", this)\n }\n\n disconnectedCallback() {\n this.folderButton?.removeEventListener(\"click\", this)\n }\n\n async handleEvent(event) {\n if (event.type === \"click\") {\n await this.handleFolderClick(event)\n }\n }\n\n async handleFolderClick(event) {\n event.preventDefault()\n event.stopPropagation()\n\n const folderButton = event.currentTarget\n folderButton.innerHTML = \"\"\n const spinner = new Spinner(\"small\")\n spinner.spin(folderButton)\n\n try {\n await patch(\n Alchemy.routes.fold_admin_page_path(this.pageId),\n null,\n \"text/vnd.turbo-stream.html\"\n )\n\n this.folded = !this.folded\n this.toggleAttribute(\"folded\", this.folded)\n this.toggleChildren()\n this.updateFolderIcon()\n } catch (error) {\n growl(error.message || error, \"error\")\n this.updateFolderIcon()\n } finally {\n spinner.stop()\n }\n }\n\n toggleChildren() {\n const childrenContainer = this.querySelector(\n `#page_${this.pageId}_children`\n )\n if (childrenContainer) {\n childrenContainer.classList.toggle(\"hidden\", this.folded)\n }\n }\n\n updateFolderIcon() {\n if (this.folderButton) {\n const iconName = this.folded ? \"arrow-right-s\" : \"arrow-down-s\"\n this.folderButton.innerHTML = `<alchemy-icon name=\"${iconName}\"></alchemy-icon>`\n }\n }\n\n /**\n * Updates the folder button state based on whether the node has children\n * Converts between button and span as needed\n */\n updateFolderButton() {\n const folderElement = this.querySelector(\".page_folder\")\n if (!folderElement) return\n\n const shouldShowButton = this.hasChildren || this.folded\n\n if (shouldShowButton && folderElement.tagName === SPAN) {\n // Convert span to button with icon\n const iconName = this.folded ? \"arrow-right-s\" : \"arrow-down-s\"\n folderElement.outerHTML = `<button class=\"page_folder icon_button\">\n <alchemy-icon name=\"${iconName}\"></alchemy-icon>\n </button>`\n\n // Re-attach event listener to the new button element\n this.folderButton?.addEventListener(\"click\", this)\n } else if (!shouldShowButton && folderElement.tagName === BUTTON) {\n // Convert button to empty span (no children and not folded)\n folderElement.outerHTML = '<span class=\"page_folder\"></span>'\n } else if (shouldShowButton && folderElement.tagName === BUTTON) {\n // Button exists, just update the icon direction\n this.updateFolderIcon()\n }\n }\n\n get hasChildren() {\n const childrenContainer = this.querySelector(\n `#page_${this.pageId}_children`\n )\n if (!childrenContainer) return false\n\n return (\n childrenContainer.querySelectorAll(\":scope > alchemy-page-node\").length >\n 0\n )\n }\n\n get folderButton() {\n return this.querySelector(\"button.page_folder\")\n }\n}\n\ncustomElements.define(\"alchemy-page-node\", AlchemyPageNode)\n","// Handles the page publication date fields\nexport class PagePublicationFields extends HTMLElement {\n connectedCallback() {\n this.publicField?.addEventListener(\"click\", this.#onClick)\n }\n\n disconnectedCallback() {\n this.publicField?.removeEventListener(\"click\", this.#onClick)\n }\n\n #onClick = (evt) => {\n const checkbox = evt.target\n const date = new Date()\n const now = new Date(\n date.getTime() - date.getTimezoneOffset() * 60000\n ).toISOString()\n\n if (checkbox.checked) {\n this.publicationDateFields.classList.remove(\"hidden\")\n this.publicOnPicker.value = now.substring(0, now.indexOf(\"T\") + 6)\n } else {\n this.publicationDateFields.classList.add(\"hidden\")\n this.publicOnPicker.value = \"\"\n }\n this.publicUntilPicker.value = \"\"\n }\n\n get publicField() {\n return this.querySelector(\"#page_public\")\n }\n\n get publicOnPicker() {\n return this.querySelector(\"input#page_public_on\")\n }\n\n get publicUntilPicker() {\n return this.querySelector(\"input#page_public_until\")\n }\n\n get publicationDateFields() {\n return this.querySelector(\".page-publication-date-fields\")\n }\n}\n\ncustomElements.define(\"alchemy-page-publication-fields\", PagePublicationFields)\n","import { RemoteSelect } from \"alchemy_admin/components/remote_select\"\n\nclass PageSelect extends RemoteSelect {\n get pageId() {\n return this.selection ? JSON.parse(this.selection)[\"id\"] : undefined\n }\n\n _searchQuery(term, page) {\n return {\n q: {\n name_cont: term,\n ...JSON.parse(this.queryParams)\n },\n page: page\n }\n }\n\n _parseResponse(response) {\n const meta = response.meta\n return {\n results: response.pages,\n more: meta.page * meta.per_page < meta.total_count\n }\n }\n\n /**\n * result which is visible if a page was selected\n * @param {object} page\n * @returns {string}\n * @private\n */\n _renderResult(page) {\n return page.text || page.name\n }\n\n /**\n * html template for each list entry\n * @param {object} page\n * @param {string} term\n * @returns {string}\n * @private\n */\n _renderListEntry(page, term) {\n return `\n <div class=\"page-select--page\">\n <div class=\"page-select--top\">\n <alchemy-icon name=\"file-3\"></alchemy-icon>\n <span class=\"page-select--page-name\">${this._hightlightTerm(page.name, term)}</span>\n <span class=\"page-select--site-name\">${page.site.name}</span>\n </div>\n <div class=\"page-select--bottom\">\n <span class=\"page-select--page-urlname\">${page.url_path}</span>\n <span class=\"page-select--language-code\">${page.language_code}</span>\n </div>\n </div>\n `\n }\n}\n\ncustomElements.define(\"alchemy-page-select\", PageSelect)\n","class PictureDescriptionSelect extends HTMLElement {\n connectedCallback() {\n this.addEventListener(\"change\", this)\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"change\", this)\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"change\":\n this.onChange()\n break\n }\n }\n\n onChange() {\n const url = new URL(this.getAttribute(\"url\"))\n const select = this.querySelector(\"select\")\n url.searchParams.set(\"language_id\", select.value)\n Turbo.visit(url, { frame: \"picture_descriptions\" })\n }\n}\n\ncustomElements.define(\n \"alchemy-picture-description-select\",\n PictureDescriptionSelect\n)\n","import debounce from \"alchemy_admin/utils/debounce\"\nimport max from \"alchemy_admin/utils/max\"\nimport { get } from \"alchemy_admin/utils/ajax\"\nimport { growl } from \"alchemy_admin/growler\"\n\nconst UPDATE_DELAY = 125\nconst IMAGE_PLACEHOLDER = '<alchemy-icon name=\"image\" size=\"xl\"></alchemy-icon>'\nconst THUMBNAIL_SIZE = \"160x120\"\n\nexport class PictureEditor extends HTMLElement {\n connectedCallback() {\n this.cropFromField = this.querySelector(\"[data-crop-from]\")\n this.cropSizeField = this.querySelector(\"[data-crop-size]\")\n this.pictureIdField = this.querySelector(\"[data-picture-id]\")\n this.targetSizeField = this.querySelector(\"[data-target-size]\")\n this.imageCropperField = this.querySelector(\"[data-image-cropper]\")\n this.image = this.querySelector(\"img\")\n this.pictureThumbnail = this.querySelector(\"alchemy-picture-thumbnail\")\n this.deleteButton = this.querySelector(\".picture_tool.delete\")\n this.cropLink = this.querySelector(\".crop_link\")\n\n this.targetSize = this.targetSizeField.dataset.targetSize\n this.pictureId = this.pictureIdField.value\n\n // The mutation observer is observing multiple fields that all get updated\n // simultaneously. We only want to update the image once, so we debounce.\n this.update = debounce(() => {\n this.updateImage()\n this.updateCropLink()\n }, UPDATE_DELAY)\n\n this.deleteButton?.addEventListener(\"click\", this.removeImage)\n\n this.observer = new MutationObserver(this.mutationCallback)\n this.observer.observe(this.cropFromField, { attributes: true })\n this.observer.observe(this.cropSizeField, { attributes: true })\n this.observer.observe(this.pictureIdField, { attributes: true })\n }\n\n disconnectedCallback() {\n this.observer.disconnect()\n }\n\n mutationCallback = (mutationsList) => {\n for (const mutation of mutationsList) {\n if (\"pictureId\" in mutation.target.dataset) {\n this.cropFromField.value = \"\"\n this.cropSizeField.value = \"\"\n this.pictureId = mutation.target.value\n }\n this.update()\n }\n }\n\n updateImage() {\n if (!this.pictureId) return\n\n this.pictureThumbnail.loading = true\n get(Alchemy.routes.url_admin_picture_path(this.pictureId), {\n crop: this.imageCropperEnabled,\n crop_from: this.cropFrom,\n crop_size: this.cropSize,\n flatten: true,\n size: THUMBNAIL_SIZE\n })\n .then(({ data }) => {\n this.pictureThumbnail.src = data.url\n this.pictureThumbnail.image.alt = data.alt\n this.pictureThumbnail.image.title = data.title\n this.setElementDirty()\n })\n .catch((error) => {\n console.error(error.message || error)\n growl(error.message || error, \"error\")\n })\n }\n\n removeImage = () => {\n this.pictureThumbnail.innerHTML = IMAGE_PLACEHOLDER\n this.pictureIdField.value = \"\"\n this.image = null\n this.cropLink.classList.add(\"disabled\")\n this.setElementDirty()\n }\n\n setElementDirty() {\n this.closest(\".element-editor\").setDirty(this)\n }\n\n updateCropLink() {\n if (!this.pictureId || !this.imageCropperEnabled) return\n\n this.cropLink.classList.remove(\"disabled\")\n\n if (this.cropLink.href.match(/(picture_id=)\\d+/)) {\n this.cropLink.href = this.cropLink.href.replace(\n /(picture_id=)\\d+/,\n \"$1\" + this.pictureId\n )\n } else {\n this.cropLink.href = this.cropLink.href + `&picture_id=${this.pictureId}`\n }\n }\n\n get cropFrom() {\n if (this.cropFromField.value === \"\") {\n return this.defaultCropFrom.join(\"x\")\n }\n return this.cropFromField.value\n }\n\n get cropSize() {\n if (this.cropSizeField.value === \"\") {\n return this.defaultCropSize.join(\"x\")\n }\n return this.cropSizeField.value\n }\n\n get defaultCropSize() {\n if (!this.imageCropperEnabled) return []\n\n const mask = this.targetSize.split(\"x\").map((n) => parseInt(n))\n const zoom = max(\n mask[0] / this.imageFileWidth,\n mask[1] / this.imageFileHeight\n )\n\n return [Math.round(mask[0] / zoom), Math.round(mask[1] / zoom)]\n }\n\n get defaultCropFrom() {\n if (!this.imageCropperEnabled) return []\n\n const dimensions = this.defaultCropSize\n\n return [\n Math.round((this.imageFileWidth - dimensions[0]) / 2),\n Math.round((this.imageFileHeight - dimensions[1]) / 2)\n ]\n }\n\n get imageFileWidth() {\n return parseInt(this.pictureIdField.dataset.imageFileWidth)\n }\n\n get imageFileHeight() {\n return parseInt(this.pictureIdField.dataset.imageFileHeight)\n }\n\n get imageCropperEnabled() {\n return this.targetSizeField.dataset.imageCropper === \"true\"\n }\n}\n\ncustomElements.define(\"alchemy-picture-editor\", PictureEditor)\n","export default function (func, delay) {\n let timeout\n\n return function (...args) {\n const that = this\n\n clearTimeout(timeout)\n timeout = setTimeout(() => func.apply(that, args), delay)\n }\n}\n","export default function (a, b) {\n return a >= b ? a : b\n}\n","// Shows spinner while loading images and\n// fades the image after its been loaded\n\nimport Spinner from \"alchemy_admin/spinner\"\n\nexport default class PictureThumbnail extends HTMLElement {\n constructor() {\n super()\n\n this.spinner = new Spinner(\"small\")\n }\n\n handleEvent(evt) {\n switch (evt.type) {\n case \"load\":\n this.#onLoaded()\n break\n case \"error\":\n this.#onError(evt)\n break\n default:\n break\n }\n }\n\n connectedCallback() {\n this.classList.add(\"thumbnail_background\")\n if (this.src && !this.image) {\n this.start()\n }\n this.#setImage()\n }\n\n disconnectedCallback() {\n this.image?.removeEventListener(\"load\", this)\n this.image?.removeEventListener(\"error\", this)\n this.stop()\n }\n\n createImage(src = this.src, alt = this.name) {\n this.image = new Image()\n this.image.src = src\n if (alt) {\n this.image.alt = alt\n }\n }\n\n start(src) {\n this.createImage(src)\n this.image.addEventListener(\"load\", this)\n this.image.addEventListener(\"error\", this)\n this.load()\n }\n\n load() {\n if (this.image?.complete) {\n return\n }\n this.setAttribute(\"loading\", \"loading\")\n this.innerHTML = \"\"\n this.spinner.spin(this)\n }\n\n stop() {\n this.classList.remove(\"loading\")\n this.spinner.stop()\n }\n\n #onLoaded() {\n this.spinner.stop()\n this.removeAttribute(\"loading\")\n }\n\n #onError(evt) {\n const message = `Could not load ${this.image.src}`\n const hoist = this.closest(\".ingredient-editor\")\n this.spinner.stop()\n this.innerHTML = `\n <sl-tooltip content=\"${message}\" ${hoist ? \"hoist\" : \"\"}>\n <alchemy-icon name=\"alert\" class=\"error\"></alchemy-icon>\n </sl-tooltip>\n `\n console.error(message, evt)\n }\n\n #setImage() {\n if (this.image?.complete) {\n this.replaceChildren(this.image)\n } else if (this.image) {\n this.append(this.image)\n }\n }\n\n set loading(value) {\n value ? this.load() : this.stop()\n }\n\n set src(src) {\n this.start(src)\n this.#setImage()\n }\n\n get name() {\n return this.getAttribute(\"name\")\n }\n\n get src() {\n return this.getAttribute(\"src\")\n }\n}\n\ncustomElements.define(\"alchemy-picture-thumbnail\", PictureThumbnail)\n","class PublishPageButton extends HTMLElement {\n connectedCallback() {\n this.addEventListener(\"submit\", this)\n document.addEventListener(\"alchemy:page-dirty\", this)\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"submit\", this)\n document.removeEventListener(\"alchemy:page-dirty\", this)\n }\n\n handleEvent(event) {\n switch (event.type) {\n case \"alchemy:page-dirty\":\n this.markDirty(event.detail)\n break\n case \"submit\":\n this.button.loading = true\n break\n }\n }\n\n markDirty(detail) {\n this.button.variant = \"primary\"\n this.button.disabled = false\n this.tooltip.content = detail.tooltip\n }\n\n get button() {\n return this.querySelector(\"sl-button\")\n }\n\n get tooltip() {\n return this.querySelector(\"sl-tooltip\")\n }\n}\n\ncustomElements.define(\"alchemy-publish-page-button\", PublishPageButton)\n","/**\n * MicroEvent - to make any js object an event emitter\n *\n * - pure javascript - server compatible, browser compatible\n * - dont rely on the browser doms\n * - super simple - you get it immediatly, no mistery, no magic involved\n *\n * @author Jerome Etienne (https://github.com/jeromeetienne)\n */\n/**\n * Execute callback for each event in space separated list of event names\n *\n */\nfunction forEvents(events, callback) {\n events.split(/\\s+/).forEach((event) => {\n callback(event);\n });\n}\nexport default class MicroEvent {\n constructor() {\n this._events = {};\n }\n on(events, fct) {\n forEvents(events, (event) => {\n const event_array = this._events[event] || [];\n event_array.push(fct);\n this._events[event] = event_array;\n });\n }\n off(events, fct) {\n var n = arguments.length;\n if (n === 0) {\n this._events = {};\n return;\n }\n forEvents(events, (event) => {\n if (n === 1) {\n delete this._events[event];\n return;\n }\n const event_array = this._events[event];\n if (event_array === undefined)\n return;\n event_array.splice(event_array.indexOf(fct), 1);\n this._events[event] = event_array;\n });\n }\n trigger(events, ...args) {\n var self = this;\n forEvents(events, (event) => {\n const event_array = self._events[event];\n if (event_array === undefined)\n return;\n event_array.forEach(fct => {\n fct.apply(self, args);\n });\n });\n }\n}\n;\n//# sourceMappingURL=microevent.js.map","/**\n * Convert array of strings to a regular expression\n *\tex ['ab','a'] => (?:ab|a)\n * \tex ['a','b'] => [ab]\n */\nexport const arrayToPattern = (chars) => {\n chars = chars.filter(Boolean);\n if (chars.length < 2) {\n return chars[0] || '';\n }\n return (maxValueLength(chars) == 1) ? '[' + chars.join('') + ']' : '(?:' + chars.join('|') + ')';\n};\nexport const sequencePattern = (array) => {\n if (!hasDuplicates(array)) {\n return array.join('');\n }\n let pattern = '';\n let prev_char_count = 0;\n const prev_pattern = () => {\n if (prev_char_count > 1) {\n pattern += '{' + prev_char_count + '}';\n }\n };\n array.forEach((char, i) => {\n if (char === array[i - 1]) {\n prev_char_count++;\n return;\n }\n prev_pattern();\n pattern += char;\n prev_char_count = 1;\n });\n prev_pattern();\n return pattern;\n};\n/**\n * Convert array of strings to a regular expression\n *\tex ['ab','a'] => (?:ab|a)\n * \tex ['a','b'] => [ab]\n */\nexport const setToPattern = (chars) => {\n let array = Array.from(chars);\n return arrayToPattern(array);\n};\n/**\n * https://stackoverflow.com/questions/7376598/in-javascript-how-do-i-check-if-an-array-has-duplicate-values\n */\nexport const hasDuplicates = (array) => {\n return (new Set(array)).size !== array.length;\n};\n/**\n * https://stackoverflow.com/questions/63006601/why-does-u-throw-an-invalid-escape-error\n */\nexport const escape_regex = (str) => {\n return (str + '').replace(/([\\$\\(\\)\\*\\+\\.\\?\\[\\]\\^\\{\\|\\}\\\\])/gu, '\\\\$1');\n};\n/**\n * Return the max length of array values\n */\nexport const maxValueLength = (array) => {\n return array.reduce((longest, value) => Math.max(longest, unicodeLength(value)), 0);\n};\nexport const unicodeLength = (str) => {\n return Array.from(str).length;\n};\n//# sourceMappingURL=regex.js.map","/**\n * Get all possible combinations of substrings that add up to the given string\n * https://stackoverflow.com/questions/30169587/find-all-the-combination-of-substrings-that-add-up-to-the-given-string\n */\nexport const allSubstrings = (input) => {\n if (input.length === 1)\n return [[input]];\n let result = [];\n const start = input.substring(1);\n const suba = allSubstrings(start);\n suba.forEach(function (subresult) {\n let tmp = subresult.slice(0);\n tmp[0] = input.charAt(0) + tmp[0];\n result.push(tmp);\n tmp = subresult.slice(0);\n tmp.unshift(input.charAt(0));\n result.push(tmp);\n });\n return result;\n};\n//# sourceMappingURL=strings.js.map","import { setToPattern, arrayToPattern, escape_regex, sequencePattern } from \"./regex.js\";\nimport { allSubstrings } from \"./strings.js\";\nexport const code_points = [[0, 65535]];\nconst accent_pat = '[\\u0300-\\u036F\\u{b7}\\u{2be}\\u{2bc}]';\nexport let unicode_map;\nlet multi_char_reg;\nconst max_char_length = 3;\nconst latin_convert = {};\nconst latin_condensed = {\n '/': '⁄∕',\n '0': '߀',\n \"a\": \"ⱥɐɑ\",\n \"aa\": \"ꜳ\",\n \"ae\": \"æǽǣ\",\n \"ao\": \"ꜵ\",\n \"au\": \"ꜷ\",\n \"av\": \"ꜹꜻ\",\n \"ay\": \"ꜽ\",\n \"b\": \"ƀɓƃ\",\n \"c\": \"ꜿƈȼↄ\",\n \"d\": \"đɗɖᴅƌꮷԁɦ\",\n \"e\": \"ɛǝᴇɇ\",\n \"f\": \"ꝼƒ\",\n \"g\": \"ǥɠꞡᵹꝿɢ\",\n \"h\": \"ħⱨⱶɥ\",\n \"i\": \"ɨı\",\n \"j\": \"ɉȷ\",\n \"k\": \"ƙⱪꝁꝃꝅꞣ\",\n \"l\": \"łƚɫⱡꝉꝇꞁɭ\",\n \"m\": \"ɱɯϻ\",\n \"n\": \"ꞥƞɲꞑᴎлԉ\",\n \"o\": \"øǿɔɵꝋꝍᴑ\",\n \"oe\": \"œ\",\n \"oi\": \"ƣ\",\n \"oo\": \"ꝏ\",\n \"ou\": \"ȣ\",\n \"p\": \"ƥᵽꝑꝓꝕρ\",\n \"q\": \"ꝗꝙɋ\",\n \"r\": \"ɍɽꝛꞧꞃ\",\n \"s\": \"ßȿꞩꞅʂ\",\n \"t\": \"ŧƭʈⱦꞇ\",\n \"th\": \"þ\",\n \"tz\": \"ꜩ\",\n \"u\": \"ʉ\",\n \"v\": \"ʋꝟʌ\",\n \"vy\": \"ꝡ\",\n \"w\": \"ⱳ\",\n \"y\": \"ƴɏỿ\",\n \"z\": \"ƶȥɀⱬꝣ\",\n \"hv\": \"ƕ\"\n};\nfor (let latin in latin_condensed) {\n let unicode = latin_condensed[latin] || '';\n for (let i = 0; i < unicode.length; i++) {\n let char = unicode.substring(i, i + 1);\n latin_convert[char] = latin;\n }\n}\nconst convert_pat = new RegExp(Object.keys(latin_convert).join('|') + '|' + accent_pat, 'gu');\n/**\n * Initialize the unicode_map from the give code point ranges\n */\nexport const initialize = (_code_points) => {\n if (unicode_map !== undefined)\n return;\n unicode_map = generateMap(_code_points || code_points);\n};\n/**\n * Helper method for normalize a string\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize\n */\nexport const normalize = (str, form = 'NFKD') => str.normalize(form);\n/**\n * Remove accents without reordering string\n * calling str.normalize('NFKD') on \\u{594}\\u{595}\\u{596} becomes \\u{596}\\u{594}\\u{595}\n * via https://github.com/krisk/Fuse/issues/133#issuecomment-318692703\n */\nexport const asciifold = (str) => {\n return Array.from(str).reduce(\n /**\n * @param {string} result\n * @param {string} char\n */\n (result, char) => {\n return result + _asciifold(char);\n }, '');\n};\nexport const _asciifold = (str) => {\n str = normalize(str)\n .toLowerCase()\n .replace(convert_pat, (/** @type {string} */ char) => {\n return latin_convert[char] || '';\n });\n //return str;\n return normalize(str, 'NFC');\n};\n/**\n * Generate a list of unicode variants from the list of code points\n */\nexport function* generator(code_points) {\n for (const [code_point_min, code_point_max] of code_points) {\n for (let i = code_point_min; i <= code_point_max; i++) {\n let composed = String.fromCharCode(i);\n let folded = asciifold(composed);\n if (folded == composed.toLowerCase()) {\n continue;\n }\n // skip when folded is a string longer than 3 characters long\n // bc the resulting regex patterns will be long\n // eg:\n // folded صلى الله عليه وسلم length 18 code point 65018\n // folded جل جلاله length 8 code point 65019\n if (folded.length > max_char_length) {\n continue;\n }\n if (folded.length == 0) {\n continue;\n }\n yield { folded: folded, composed: composed, code_point: i };\n }\n }\n}\n/**\n * Generate a unicode map from the list of code points\n */\nexport const generateSets = (code_points) => {\n const unicode_sets = {};\n const addMatching = (folded, to_add) => {\n /** @type {Set<string>} */\n const folded_set = unicode_sets[folded] || new Set();\n const patt = new RegExp('^' + setToPattern(folded_set) + '$', 'iu');\n if (to_add.match(patt)) {\n return;\n }\n folded_set.add(escape_regex(to_add));\n unicode_sets[folded] = folded_set;\n };\n for (let value of generator(code_points)) {\n addMatching(value.folded, value.folded);\n addMatching(value.folded, value.composed);\n }\n return unicode_sets;\n};\n/**\n * Generate a unicode map from the list of code points\n * ae => (?:(?:ae|Æ|Ǽ|Ǣ)|(?:A|Ⓐ|A...)(?:E|ɛ|Ⓔ...))\n */\nexport const generateMap = (code_points) => {\n const unicode_sets = generateSets(code_points);\n const unicode_map = {};\n let multi_char = [];\n for (let folded in unicode_sets) {\n let set = unicode_sets[folded];\n if (set) {\n unicode_map[folded] = setToPattern(set);\n }\n if (folded.length > 1) {\n multi_char.push(escape_regex(folded));\n }\n }\n multi_char.sort((a, b) => b.length - a.length);\n const multi_char_patt = arrayToPattern(multi_char);\n multi_char_reg = new RegExp('^' + multi_char_patt, 'u');\n return unicode_map;\n};\n/**\n * Map each element of an array from its folded value to all possible unicode matches\n */\nexport const mapSequence = (strings, min_replacement = 1) => {\n let chars_replaced = 0;\n strings = strings.map((str) => {\n if (unicode_map[str]) {\n chars_replaced += str.length;\n }\n return unicode_map[str] || str;\n });\n if (chars_replaced >= min_replacement) {\n return sequencePattern(strings);\n }\n return '';\n};\n/**\n * Convert a short string and split it into all possible patterns\n * Keep a pattern only if min_replacement is met\n *\n * 'abc'\n * \t\t=> [['abc'],['ab','c'],['a','bc'],['a','b','c']]\n *\t\t=> ['abc-pattern','ab-c-pattern'...]\n */\nexport const substringsToPattern = (str, min_replacement = 1) => {\n min_replacement = Math.max(min_replacement, str.length - 1);\n return arrayToPattern(allSubstrings(str).map((sub_pat) => {\n return mapSequence(sub_pat, min_replacement);\n }));\n};\n/**\n * Convert an array of sequences into a pattern\n * [{start:0,end:3,length:3,substr:'iii'}...] => (?:iii...)\n */\nconst sequencesToPattern = (sequences, all = true) => {\n let min_replacement = sequences.length > 1 ? 1 : 0;\n return arrayToPattern(sequences.map((sequence) => {\n let seq = [];\n const len = all ? sequence.length() : sequence.length() - 1;\n for (let j = 0; j < len; j++) {\n seq.push(substringsToPattern(sequence.substrs[j] || '', min_replacement));\n }\n return sequencePattern(seq);\n }));\n};\n/**\n * Return true if the sequence is already in the sequences\n */\nconst inSequences = (needle_seq, sequences) => {\n for (const seq of sequences) {\n if (seq.start != needle_seq.start || seq.end != needle_seq.end) {\n continue;\n }\n if (seq.substrs.join('') !== needle_seq.substrs.join('')) {\n continue;\n }\n let needle_parts = needle_seq.parts;\n const filter = (part) => {\n for (const needle_part of needle_parts) {\n if (needle_part.start === part.start && needle_part.substr === part.substr) {\n return false;\n }\n if (part.length == 1 || needle_part.length == 1) {\n continue;\n }\n // check for overlapping parts\n // a = ['::=','==']\n // b = ['::','===']\n // a = ['r','sm']\n // b = ['rs','m']\n if (part.start < needle_part.start && part.end > needle_part.start) {\n return true;\n }\n if (needle_part.start < part.start && needle_part.end > part.start) {\n return true;\n }\n }\n return false;\n };\n let filtered = seq.parts.filter(filter);\n if (filtered.length > 0) {\n continue;\n }\n return true;\n }\n return false;\n};\nclass Sequence {\n parts;\n substrs;\n start;\n end;\n constructor() {\n this.parts = [];\n this.substrs = [];\n this.start = 0;\n this.end = 0;\n }\n add(part) {\n if (part) {\n this.parts.push(part);\n this.substrs.push(part.substr);\n this.start = Math.min(part.start, this.start);\n this.end = Math.max(part.end, this.end);\n }\n }\n last() {\n return this.parts[this.parts.length - 1];\n }\n length() {\n return this.parts.length;\n }\n clone(position, last_piece) {\n let clone = new Sequence();\n let parts = JSON.parse(JSON.stringify(this.parts));\n let last_part = parts.pop();\n for (const part of parts) {\n clone.add(part);\n }\n let last_substr = last_piece.substr.substring(0, position - last_part.start);\n let clone_last_len = last_substr.length;\n clone.add({ start: last_part.start, end: last_part.start + clone_last_len, length: clone_last_len, substr: last_substr });\n return clone;\n }\n}\n/**\n * Expand a regular expression pattern to include unicode variants\n * \teg /a/ becomes /aⓐaẚàáâầấẫẩãāăằắẵẳȧǡäǟảåǻǎȁȃạậặḁąⱥɐɑAⒶAÀÁÂẦẤẪẨÃĀĂẰẮẴẲȦǠÄǞẢÅǺǍȀȂẠẬẶḀĄȺⱯ/\n *\n * Issue:\n * ﺊﺋ [ 'ﺊ = \\\\u{fe8a}', 'ﺋ = \\\\u{fe8b}' ]\n *\tbecomes:\tئئ [ 'ي = \\\\u{64a}', 'ٔ = \\\\u{654}', 'ي = \\\\u{64a}', 'ٔ = \\\\u{654}' ]\n *\n *\tİIJ = IIJ = ⅡJ\n *\n * \t1/2/4\n */\nexport const getPattern = (str) => {\n initialize();\n str = asciifold(str);\n let pattern = '';\n let sequences = [new Sequence()];\n for (let i = 0; i < str.length; i++) {\n let substr = str.substring(i);\n let match = substr.match(multi_char_reg);\n const char = str.substring(i, i + 1);\n const match_str = match ? match[0] : null;\n // loop through sequences\n // add either the char or multi_match\n let overlapping = [];\n let added_types = new Set();\n for (const sequence of sequences) {\n const last_piece = sequence.last();\n if (!last_piece || last_piece.length == 1 || last_piece.end <= i) {\n // if we have a multi match\n if (match_str) {\n const len = match_str.length;\n sequence.add({ start: i, end: i + len, length: len, substr: match_str });\n added_types.add('1');\n }\n else {\n sequence.add({ start: i, end: i + 1, length: 1, substr: char });\n added_types.add('2');\n }\n }\n else if (match_str) {\n let clone = sequence.clone(i, last_piece);\n const len = match_str.length;\n clone.add({ start: i, end: i + len, length: len, substr: match_str });\n overlapping.push(clone);\n }\n else {\n // don't add char\n // adding would create invalid patterns: 234 => [2,34,4]\n added_types.add('3');\n }\n }\n // if we have overlapping\n if (overlapping.length > 0) {\n // ['ii','iii'] before ['i','i','iii']\n overlapping = overlapping.sort((a, b) => {\n return a.length() - b.length();\n });\n for (let clone of overlapping) {\n // don't add if we already have an equivalent sequence\n if (inSequences(clone, sequences)) {\n continue;\n }\n sequences.push(clone);\n }\n continue;\n }\n // if we haven't done anything unique\n // clean up the patterns\n // helps keep patterns smaller\n // if str = 'r₨㎧aarss', pattern will be 446 instead of 655\n if (i > 0 && added_types.size == 1 && !added_types.has('3')) {\n pattern += sequencesToPattern(sequences, false);\n let new_seq = new Sequence();\n const old_seq = sequences[0];\n if (old_seq) {\n new_seq.add(old_seq.last());\n }\n sequences = [new_seq];\n }\n }\n pattern += sequencesToPattern(sequences, true);\n return pattern;\n};\nexport { escape_regex };\n//# sourceMappingURL=index.js.map","import { asciifold } from '@orchidjs/unicode-variants';\n/**\n * A property getter resolving dot-notation\n * @param {Object} obj The root object to fetch property on\n * @param {String} name The optionally dotted property name to fetch\n * @return {Object} The resolved property value\n */\nexport const getAttr = (obj, name) => {\n if (!obj)\n return;\n return obj[name];\n};\n/**\n * A property getter resolving dot-notation\n * @param {Object} obj The root object to fetch property on\n * @param {String} name The optionally dotted property name to fetch\n * @return {Object} The resolved property value\n */\nexport const getAttrNesting = (obj, name) => {\n if (!obj)\n return;\n var part, names = name.split(\".\");\n while ((part = names.shift()) && (obj = obj[part]))\n ;\n return obj;\n};\n/**\n * Calculates how close of a match the\n * given value is against a search token.\n *\n */\nexport const scoreValue = (value, token, weight) => {\n var score, pos;\n if (!value)\n return 0;\n value = value + '';\n if (token.regex == null)\n return 0;\n pos = value.search(token.regex);\n if (pos === -1)\n return 0;\n score = token.string.length / value.length;\n if (pos === 0)\n score += 0.5;\n return score * weight;\n};\n/**\n * Cast object property to an array if it exists and has a value\n *\n */\nexport const propToArray = (obj, key) => {\n var value = obj[key];\n if (typeof value == 'function')\n return value;\n if (value && !Array.isArray(value)) {\n obj[key] = [value];\n }\n};\n/**\n * Iterates over arrays and hashes.\n *\n * ```\n * iterate(this.items, function(item, id) {\n * // invoked for each item\n * });\n * ```\n *\n */\nexport const iterate = (object, callback) => {\n if (Array.isArray(object)) {\n object.forEach(callback);\n }\n else {\n for (var key in object) {\n if (object.hasOwnProperty(key)) {\n callback(object[key], key);\n }\n }\n }\n};\nexport const cmp = (a, b) => {\n if (typeof a === 'number' && typeof b === 'number') {\n return a > b ? 1 : (a < b ? -1 : 0);\n }\n a = asciifold(a + '').toLowerCase();\n b = asciifold(b + '').toLowerCase();\n if (a > b)\n return 1;\n if (b > a)\n return -1;\n return 0;\n};\n//# sourceMappingURL=utils.js.map","/**\n * sifter.js\n * Copyright (c) 2013–2020 Brian Reavis & contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n * @author Brian Reavis <brian@thirdroute.com>\n */\nimport { scoreValue, getAttr, getAttrNesting, propToArray, iterate, cmp } from \"./utils.js\";\nimport { getPattern, escape_regex } from '@orchidjs/unicode-variants';\nclass Sifter {\n items; // []|{};\n settings;\n /**\n * Textually searches arrays and hashes of objects\n * by property (or multiple properties). Designed\n * specifically for autocomplete.\n *\n */\n constructor(items, settings) {\n this.items = items;\n this.settings = settings || { diacritics: true };\n }\n ;\n /**\n * Splits a search string into an array of individual\n * regexps to be used to match results.\n *\n */\n tokenize(query, respect_word_boundaries, weights) {\n if (!query || !query.length)\n return [];\n const tokens = [];\n const words = query.split(/\\s+/);\n var field_regex;\n if (weights) {\n field_regex = new RegExp('^(' + Object.keys(weights).map(escape_regex).join('|') + ')\\:(.*)$');\n }\n words.forEach((word) => {\n let field_match;\n let field = null;\n let regex = null;\n // look for \"field:query\" tokens\n if (field_regex && (field_match = word.match(field_regex))) {\n field = field_match[1];\n word = field_match[2];\n }\n if (word.length > 0) {\n if (this.settings.diacritics) {\n regex = getPattern(word) || null;\n }\n else {\n regex = escape_regex(word);\n }\n if (regex && respect_word_boundaries)\n regex = \"\\\\b\" + regex;\n }\n tokens.push({\n string: word,\n regex: regex ? new RegExp(regex, 'iu') : null,\n field: field,\n });\n });\n return tokens;\n }\n ;\n /**\n * Returns a function to be used to score individual results.\n *\n * Good matches will have a higher score than poor matches.\n * If an item is not a match, 0 will be returned by the function.\n *\n * @returns {T.ScoreFn}\n */\n getScoreFunction(query, options) {\n var search = this.prepareSearch(query, options);\n return this._getScoreFunction(search);\n }\n /**\n * @returns {T.ScoreFn}\n *\n */\n _getScoreFunction(search) {\n const tokens = search.tokens, token_count = tokens.length;\n if (!token_count) {\n return function () { return 0; };\n }\n const fields = search.options.fields, weights = search.weights, field_count = fields.length, getAttrFn = search.getAttrFn;\n if (!field_count) {\n return function () { return 1; };\n }\n /**\n * Calculates the score of an object\n * against the search query.\n *\n */\n const scoreObject = (function () {\n if (field_count === 1) {\n return function (token, data) {\n const field = fields[0].field;\n return scoreValue(getAttrFn(data, field), token, weights[field] || 1);\n };\n }\n return function (token, data) {\n var sum = 0;\n // is the token specific to a field?\n if (token.field) {\n const value = getAttrFn(data, token.field);\n if (!token.regex && value) {\n sum += (1 / field_count);\n }\n else {\n sum += scoreValue(value, token, 1);\n }\n }\n else {\n iterate(weights, (weight, field) => {\n sum += scoreValue(getAttrFn(data, field), token, weight);\n });\n }\n return sum / field_count;\n };\n })();\n if (token_count === 1) {\n return function (data) {\n return scoreObject(tokens[0], data);\n };\n }\n if (search.options.conjunction === 'and') {\n return function (data) {\n var score, sum = 0;\n for (let token of tokens) {\n score = scoreObject(token, data);\n if (score <= 0)\n return 0;\n sum += score;\n }\n return sum / token_count;\n };\n }\n else {\n return function (data) {\n var sum = 0;\n iterate(tokens, (token) => {\n sum += scoreObject(token, data);\n });\n return sum / token_count;\n };\n }\n }\n ;\n /**\n * Returns a function that can be used to compare two\n * results, for sorting purposes. If no sorting should\n * be performed, `null` will be returned.\n *\n * @return function(a,b)\n */\n getSortFunction(query, options) {\n var search = this.prepareSearch(query, options);\n return this._getSortFunction(search);\n }\n _getSortFunction(search) {\n var implicit_score, sort_flds = [];\n const self = this, options = search.options, sort = (!search.query && options.sort_empty) ? options.sort_empty : options.sort;\n if (typeof sort == 'function') {\n return sort.bind(this);\n }\n /**\n * Fetches the specified sort field value\n * from a search result item.\n *\n */\n const get_field = function (name, result) {\n if (name === '$score')\n return result.score;\n return search.getAttrFn(self.items[result.id], name);\n };\n // parse options\n if (sort) {\n for (let s of sort) {\n if (search.query || s.field !== '$score') {\n sort_flds.push(s);\n }\n }\n }\n // the \"$score\" field is implied to be the primary\n // sort field, unless it's manually specified\n if (search.query) {\n implicit_score = true;\n for (let fld of sort_flds) {\n if (fld.field === '$score') {\n implicit_score = false;\n break;\n }\n }\n if (implicit_score) {\n sort_flds.unshift({ field: '$score', direction: 'desc' });\n }\n // without a search.query, all items will have the same score\n }\n else {\n sort_flds = sort_flds.filter((fld) => fld.field !== '$score');\n }\n // build function\n const sort_flds_count = sort_flds.length;\n if (!sort_flds_count) {\n return null;\n }\n return function (a, b) {\n var result, field;\n for (let sort_fld of sort_flds) {\n field = sort_fld.field;\n let multiplier = sort_fld.direction === 'desc' ? -1 : 1;\n result = multiplier * cmp(get_field(field, a), get_field(field, b));\n if (result)\n return result;\n }\n return 0;\n };\n }\n ;\n /**\n * Parses a search query and returns an object\n * with tokens and fields ready to be populated\n * with results.\n *\n */\n prepareSearch(query, optsUser) {\n const weights = {};\n var options = Object.assign({}, optsUser);\n propToArray(options, 'sort');\n propToArray(options, 'sort_empty');\n // convert fields to new format\n if (options.fields) {\n propToArray(options, 'fields');\n const fields = [];\n options.fields.forEach((field) => {\n if (typeof field == 'string') {\n field = { field: field, weight: 1 };\n }\n fields.push(field);\n weights[field.field] = ('weight' in field) ? field.weight : 1;\n });\n options.fields = fields;\n }\n return {\n options: options,\n query: query.toLowerCase().trim(),\n tokens: this.tokenize(query, options.respect_word_boundaries, weights),\n total: 0,\n items: [],\n weights: weights,\n getAttrFn: (options.nesting) ? getAttrNesting : getAttr,\n };\n }\n ;\n /**\n * Searches through all items and returns a sorted array of matches.\n *\n */\n search(query, options) {\n var self = this, score, search;\n search = this.prepareSearch(query, options);\n options = search.options;\n query = search.query;\n // generate result scoring function\n const fn_score = options.score || self._getScoreFunction(search);\n // perform search and sort\n if (query.length) {\n iterate(self.items, (item, id) => {\n score = fn_score(item);\n if (options.filter === false || score > 0) {\n search.items.push({ 'score': score, 'id': id });\n }\n });\n }\n else {\n iterate(self.items, (_, id) => {\n search.items.push({ 'score': 1, 'id': id });\n });\n }\n const fn_sort = self._getSortFunction(search);\n if (fn_sort)\n search.items.sort(fn_sort);\n // apply limits\n search.total = search.items.length;\n if (typeof options.limit === 'number') {\n search.items = search.items.slice(0, options.limit);\n }\n return search;\n }\n ;\n}\nexport { Sifter, scoreValue, getAttr, getAttrNesting, propToArray, iterate, cmp, getPattern };\nexport * from \"./types.js\";\n//# sourceMappingURL=sifter.js.map","/**\n * Converts a scalar to its best string representation\n * for hash keys and HTML attribute values.\n *\n * Transformations:\n * 'str' -> 'str'\n * null -> ''\n * undefined -> ''\n * true -> '1'\n * false -> '0'\n * 0 -> '0'\n * 1 -> '1'\n *\n */\nexport const hash_key = (value) => {\n if (typeof value === 'undefined' || value === null)\n return null;\n return get_hash(value);\n};\nexport const get_hash = (value) => {\n if (typeof value === 'boolean')\n return value ? '1' : '0';\n return value + '';\n};\n/**\n * Escapes a string for use within HTML.\n *\n */\nexport const escape_html = (str) => {\n return (str + '')\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n};\n/**\n * use setTimeout if timeout > 0\n */\nexport const timeout = (fn, timeout) => {\n if (timeout > 0) {\n return window.setTimeout(fn, timeout);\n }\n fn.call(null);\n return null;\n};\n/**\n * Debounce the user provided load function\n *\n */\nexport const loadDebounce = (fn, delay) => {\n var timeout;\n return function (value, callback) {\n var self = this;\n if (timeout) {\n self.loading = Math.max(self.loading - 1, 0);\n clearTimeout(timeout);\n }\n timeout = setTimeout(function () {\n timeout = null;\n self.loadedSearches[value] = true;\n fn.call(self, value, callback);\n }, delay);\n };\n};\n/**\n * Debounce all fired events types listed in `types`\n * while executing the provided `fn`.\n *\n */\nexport const debounce_events = (self, types, fn) => {\n var type;\n var trigger = self.trigger;\n var event_args = {};\n // override trigger method\n self.trigger = function () {\n var type = arguments[0];\n if (types.indexOf(type) !== -1) {\n event_args[type] = arguments;\n }\n else {\n return trigger.apply(self, arguments);\n }\n };\n // invoke provided function\n fn.apply(self, []);\n self.trigger = trigger;\n // trigger queued events\n for (type of types) {\n if (type in event_args) {\n trigger.apply(self, event_args[type]);\n }\n }\n};\n/**\n * Determines the current selection within a text input control.\n * Returns an object containing:\n * - start\n * - length\n *\n * Note: \"selectionStart, selectionEnd ... apply only to inputs of types text, search, URL, tel and password\"\n * \t- https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange\n */\nexport const getSelection = (input) => {\n return {\n start: input.selectionStart || 0,\n length: (input.selectionEnd || 0) - (input.selectionStart || 0),\n };\n};\n/**\n * Prevent default\n *\n */\nexport const preventDefault = (evt, stop = false) => {\n if (evt) {\n evt.preventDefault();\n if (stop) {\n evt.stopPropagation();\n }\n }\n};\n/**\n * Add event helper\n *\n */\nexport const addEvent = (target, type, callback, options) => {\n target.addEventListener(type, callback, options);\n};\n/**\n * Return true if the requested key is down\n * Will return false if more than one control character is pressed ( when [ctrl+shift+a] != [ctrl+a] )\n * The current evt may not always set ( eg calling advanceSelection() )\n *\n */\nexport const isKeyDown = (key_name, evt) => {\n if (!evt) {\n return false;\n }\n if (!evt[key_name]) {\n return false;\n }\n var count = (evt.altKey ? 1 : 0) + (evt.ctrlKey ? 1 : 0) + (evt.shiftKey ? 1 : 0) + (evt.metaKey ? 1 : 0);\n if (count === 1) {\n return true;\n }\n return false;\n};\n/**\n * Get the id of an element\n * If the id attribute is not set, set the attribute with the given id\n *\n */\nexport const getId = (el, id) => {\n const existing_id = el.getAttribute('id');\n if (existing_id) {\n return existing_id;\n }\n el.setAttribute('id', id);\n return id;\n};\n/**\n * Returns a string with backslashes added before characters that need to be escaped.\n */\nexport const addSlashes = (str) => {\n return str.replace(/[\\\\\"']/g, '\\\\$&');\n};\n/**\n *\n */\nexport const append = (parent, node) => {\n if (node)\n parent.append(node);\n};\n/**\n * Iterates over arrays and hashes.\n *\n * ```\n * iterate(this.items, function(item, id) {\n * // invoked for each item\n * });\n * ```\n *\n */\nexport const iterate = (object, callback) => {\n if (Array.isArray(object)) {\n object.forEach(callback);\n }\n else {\n for (var key in object) {\n if (object.hasOwnProperty(key)) {\n callback(object[key], key);\n }\n }\n }\n};\n//# sourceMappingURL=utils.js.map","import { iterate } from \"./utils.js\";\n/**\n * Return a dom element from either a dom query string, jQuery object, a dom element or html string\n * https://stackoverflow.com/questions/494143/creating-a-new-dom-element-from-an-html-string-using-built-in-dom-methods-or-pro/35385518#35385518\n *\n * param query should be {}\n */\nexport const getDom = (query) => {\n if (query.jquery) {\n return query[0];\n }\n if (query instanceof HTMLElement) {\n return query;\n }\n if (isHtmlString(query)) {\n var tpl = document.createElement('template');\n tpl.innerHTML = query.trim(); // Never return a text node of whitespace as the result\n return tpl.content.firstChild;\n }\n return document.querySelector(query);\n};\nexport const isHtmlString = (arg) => {\n if (typeof arg === 'string' && arg.indexOf('<') > -1) {\n return true;\n }\n return false;\n};\nexport const escapeQuery = (query) => {\n return query.replace(/['\"\\\\]/g, '\\\\$&');\n};\n/**\n * Dispatch an event\n *\n */\nexport const triggerEvent = (dom_el, event_name) => {\n var event = document.createEvent('HTMLEvents');\n event.initEvent(event_name, true, false);\n dom_el.dispatchEvent(event);\n};\n/**\n * Apply CSS rules to a dom element\n *\n */\nexport const applyCSS = (dom_el, css) => {\n Object.assign(dom_el.style, css);\n};\n/**\n * Add css classes\n *\n */\nexport const addClasses = (elmts, ...classes) => {\n var norm_classes = classesArray(classes);\n elmts = castAsArray(elmts);\n elmts.map(el => {\n norm_classes.map(cls => {\n el.classList.add(cls);\n });\n });\n};\n/**\n * Remove css classes\n *\n */\nexport const removeClasses = (elmts, ...classes) => {\n var norm_classes = classesArray(classes);\n elmts = castAsArray(elmts);\n elmts.map(el => {\n norm_classes.map(cls => {\n el.classList.remove(cls);\n });\n });\n};\n/**\n * Return arguments\n *\n */\nexport const classesArray = (args) => {\n var classes = [];\n iterate(args, (_classes) => {\n if (typeof _classes === 'string') {\n _classes = _classes.trim().split(/[\\t\\n\\f\\r\\s]/);\n }\n if (Array.isArray(_classes)) {\n classes = classes.concat(_classes);\n }\n });\n return classes.filter(Boolean);\n};\n/**\n * Create an array from arg if it's not already an array\n *\n */\nexport const castAsArray = (arg) => {\n if (!Array.isArray(arg)) {\n arg = [arg];\n }\n return arg;\n};\n/**\n * Get the closest node to the evt.target matching the selector\n * Stops at wrapper\n *\n */\nexport const parentMatch = (target, selector, wrapper) => {\n if (wrapper && !wrapper.contains(target)) {\n return;\n }\n while (target && target.matches) {\n if (target.matches(selector)) {\n return target;\n }\n target = target.parentNode;\n }\n};\n/**\n * Get the first or last item from an array\n *\n * > 0 - right (last)\n * <= 0 - left (first)\n *\n */\nexport const getTail = (list, direction = 0) => {\n if (direction > 0) {\n return list[list.length - 1];\n }\n return list[0];\n};\n/**\n * Return true if an object is empty\n *\n */\nexport const isEmptyObject = (obj) => {\n return (Object.keys(obj).length === 0);\n};\n/**\n * Get the index of an element amongst sibling nodes of the same type\n *\n */\nexport const nodeIndex = (el, amongst) => {\n if (!el)\n return -1;\n amongst = amongst || el.nodeName;\n var i = 0;\n while (el = el.previousElementSibling) {\n if (el.matches(amongst)) {\n i++;\n }\n }\n return i;\n};\n/**\n * Set attributes of an element\n *\n */\nexport const setAttr = (el, attrs) => {\n iterate(attrs, (val, attr) => {\n if (val == null) {\n el.removeAttribute(attr);\n }\n else {\n el.setAttribute(attr, '' + val);\n }\n });\n};\n/**\n * Replace a node\n */\nexport const replaceNode = (existing, replacement) => {\n if (existing.parentNode)\n existing.parentNode.replaceChild(replacement, existing);\n};\n//# sourceMappingURL=vanilla.js.map","/**\n * highlight v3 | MIT license | Johann Burkard <jb@eaio.com>\n * Highlights arbitrary terms in a node.\n *\n * - Modified by Marshal <beatgates@gmail.com> 2011-6-24 (added regex)\n * - Modified by Brian Reavis <brian@thirdroute.com> 2012-8-27 (cleanup)\n */\nimport { replaceNode } from \"../vanilla.js\";\nexport const highlight = (element, regex) => {\n if (regex === null)\n return;\n // convet string to regex\n if (typeof regex === 'string') {\n if (!regex.length)\n return;\n regex = new RegExp(regex, 'i');\n }\n // Wrap matching part of text node with highlighting <span>, e.g.\n // Soccer -> <span class=\"highlight\">Soc</span>cer for regex = /soc/i\n const highlightText = (node) => {\n var match = node.data.match(regex);\n if (match && node.data.length > 0) {\n var spannode = document.createElement('span');\n spannode.className = 'highlight';\n var middlebit = node.splitText(match.index);\n middlebit.splitText(match[0].length);\n var middleclone = middlebit.cloneNode(true);\n spannode.appendChild(middleclone);\n replaceNode(middlebit, spannode);\n return 1;\n }\n return 0;\n };\n // Recurse element node, looking for child text nodes to highlight, unless element\n // is childless, <script>, <style>, or already highlighted: <span class=\"hightlight\">\n const highlightChildren = (node) => {\n if (node.nodeType === 1 && node.childNodes && !/(script|style)/i.test(node.tagName) && (node.className !== 'highlight' || node.tagName !== 'SPAN')) {\n Array.from(node.childNodes).forEach(element => {\n highlightRecursive(element);\n });\n }\n };\n const highlightRecursive = (node) => {\n if (node.nodeType === 3) {\n return highlightText(node);\n }\n highlightChildren(node);\n return 0;\n };\n highlightRecursive(element);\n};\n/**\n * removeHighlight fn copied from highlight v5 and\n * edited to remove with(), pass js strict mode, and use without jquery\n */\nexport const removeHighlight = (el) => {\n var elements = el.querySelectorAll(\"span.highlight\");\n Array.prototype.forEach.call(elements, function (el) {\n var parent = el.parentNode;\n parent.replaceChild(el.firstChild, el);\n parent.normalize();\n });\n};\n//# sourceMappingURL=highlight.js.map","export const KEY_A = 65;\nexport const KEY_RETURN = 13;\nexport const KEY_ESC = 27;\nexport const KEY_LEFT = 37;\nexport const KEY_UP = 38;\nexport const KEY_RIGHT = 39;\nexport const KEY_DOWN = 40;\nexport const KEY_BACKSPACE = 8;\nexport const KEY_DELETE = 46;\nexport const KEY_TAB = 9;\nexport const IS_MAC = typeof navigator === 'undefined' ? false : /Mac/.test(navigator.userAgent);\nexport const KEY_SHORTCUT = IS_MAC ? 'metaKey' : 'ctrlKey'; // ctrl key or apple key for ma\n//# sourceMappingURL=constants.js.map","export default {\n options: [],\n optgroups: [],\n plugins: [],\n delimiter: ',',\n splitOn: null, // regexp or string for splitting up values from a paste command\n persist: true,\n diacritics: true,\n create: null,\n createOnBlur: false,\n createFilter: null,\n clearAfterSelect: false,\n highlight: true,\n openOnFocus: true,\n shouldOpen: null,\n maxOptions: 50,\n maxItems: null,\n hideSelected: null,\n duplicates: false,\n addPrecedence: false,\n selectOnTab: false,\n preload: null,\n allowEmptyOption: false,\n //closeAfterSelect: false,\n refreshThrottle: 300,\n loadThrottle: 300,\n loadingClass: 'loading',\n dataAttr: null, //'data-data',\n optgroupField: 'optgroup',\n valueField: 'value',\n labelField: 'text',\n disabledField: 'disabled',\n optgroupLabelField: 'label',\n optgroupValueField: 'value',\n lockOptgroupOrder: false,\n sortField: '$order',\n searchField: ['text'],\n searchConjunction: 'and',\n mode: null,\n wrapperClass: 'ts-wrapper',\n controlClass: 'ts-control',\n dropdownClass: 'ts-dropdown',\n dropdownContentClass: 'ts-dropdown-content',\n itemClass: 'item',\n optionClass: 'option',\n dropdownParent: null,\n controlInput: '<input type=\"text\" autocomplete=\"off\" size=\"1\" />',\n copyClassesToDropdown: false,\n placeholder: null,\n hidePlaceholder: null,\n shouldLoad: function (query) {\n return query.length > 0;\n },\n /*\n load : null, // function(query, callback) { ... }\n score : null, // function(search) { ... }\n onInitialize : null, // function() { ... }\n onChange : null, // function(value) { ... }\n onItemAdd : null, // function(value, $item) { ... }\n onItemRemove : null, // function(value) { ... }\n onClear : null, // function() { ... }\n onOptionAdd : null, // function(value, data) { ... }\n onOptionRemove : null, // function(value) { ... }\n onOptionClear : null, // function() { ... }\n onOptionGroupAdd : null, // function(id, data) { ... }\n onOptionGroupRemove : null, // function(id) { ... }\n onOptionGroupClear : null, // function() { ... }\n onDropdownOpen : null, // function(dropdown) { ... }\n onDropdownClose : null, // function(dropdown) { ... }\n onType : null, // function(str) { ... }\n onDelete : null, // function(values) { ... }\n */\n render: {\n /*\n item: null,\n optgroup: null,\n optgroup_header: null,\n option: null,\n option_create: null\n */\n }\n};\n//# sourceMappingURL=defaults.js.map","import defaults from \"./defaults.js\";\nimport { hash_key, iterate } from \"./utils.js\";\nexport default function getSettings(input, settings_user) {\n var settings = Object.assign({}, defaults, settings_user);\n var attr_data = settings.dataAttr;\n var field_label = settings.labelField;\n var field_value = settings.valueField;\n var field_disabled = settings.disabledField;\n var field_optgroup = settings.optgroupField;\n var field_optgroup_label = settings.optgroupLabelField;\n var field_optgroup_value = settings.optgroupValueField;\n var tag_name = input.tagName.toLowerCase();\n var placeholder = input.getAttribute('placeholder') || input.getAttribute('data-placeholder');\n if (!placeholder && !settings.allowEmptyOption) {\n let option = input.querySelector('option[value=\"\"]');\n if (option) {\n placeholder = option.textContent;\n }\n }\n var settings_element = {\n placeholder: placeholder,\n options: [],\n optgroups: [],\n items: [],\n maxItems: null,\n };\n /**\n * Initialize from a <select> element.\n *\n */\n var init_select = () => {\n var tagName;\n var options = settings_element.options;\n var optionsMap = {};\n var group_count = 1;\n let $order = 0;\n var readData = (el) => {\n var data = Object.assign({}, el.dataset); // get plain object from DOMStringMap\n var json = attr_data && data[attr_data];\n if (typeof json === 'string' && json.length) {\n data = Object.assign(data, JSON.parse(json));\n }\n return data;\n };\n var addOption = (option, group) => {\n var value = hash_key(option.value);\n if (value == null)\n return;\n if (!value && !settings.allowEmptyOption)\n return;\n // if the option already exists, it's probably been\n // duplicated in another optgroup. in this case, push\n // the current group to the \"optgroup\" property on the\n // existing option so that it's rendered in both places.\n if (optionsMap.hasOwnProperty(value)) {\n if (group) {\n var arr = optionsMap[value][field_optgroup];\n if (!arr) {\n optionsMap[value][field_optgroup] = group;\n }\n else if (!Array.isArray(arr)) {\n optionsMap[value][field_optgroup] = [arr, group];\n }\n else {\n arr.push(group);\n }\n }\n }\n else {\n var option_data = readData(option);\n option_data[field_label] = option_data[field_label] || option.textContent;\n option_data[field_value] = option_data[field_value] || value;\n option_data[field_disabled] = option_data[field_disabled] || option.disabled;\n option_data[field_optgroup] = option_data[field_optgroup] || group;\n option_data.$option = option;\n option_data.$order = option_data.$order || ++$order;\n optionsMap[value] = option_data;\n options.push(option_data);\n }\n if (option.selected) {\n settings_element.items.push(value);\n }\n };\n var addGroup = (optgroup) => {\n var id, optgroup_data;\n optgroup_data = readData(optgroup);\n optgroup_data[field_optgroup_label] = optgroup_data[field_optgroup_label] || optgroup.getAttribute('label') || '';\n optgroup_data[field_optgroup_value] = optgroup_data[field_optgroup_value] || group_count++;\n optgroup_data[field_disabled] = optgroup_data[field_disabled] || optgroup.disabled;\n optgroup_data.$order = optgroup_data.$order || ++$order;\n settings_element.optgroups.push(optgroup_data);\n id = optgroup_data[field_optgroup_value];\n iterate(optgroup.children, (option) => {\n addOption(option, id);\n });\n };\n settings_element.maxItems = input.hasAttribute('multiple') ? null : 1;\n iterate(input.children, (child) => {\n tagName = child.tagName.toLowerCase();\n if (tagName === 'optgroup') {\n addGroup(child);\n }\n else if (tagName === 'option') {\n addOption(child);\n }\n });\n };\n /**\n * Initialize from a <input type=\"text\"> element.\n *\n */\n var init_textbox = () => {\n var _a, _b;\n const data_raw = input.getAttribute(attr_data);\n if (!data_raw) {\n var value = (_b = (_a = input === null || input === void 0 ? void 0 : input.value) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : '';\n if (!settings.allowEmptyOption && !value.length)\n return;\n const values = value.split(settings.delimiter);\n iterate(values, (value) => {\n const option = {};\n option[field_label] = value;\n option[field_value] = value;\n settings_element.options.push(option);\n });\n settings_element.items = values;\n }\n else {\n settings_element.options = JSON.parse(data_raw);\n iterate(settings_element.options, (opt) => {\n settings_element.items.push(opt[field_value]);\n });\n }\n };\n if (tag_name === 'select') {\n init_select();\n }\n else {\n init_textbox();\n }\n return Object.assign({}, defaults, settings_element, settings_user);\n}\n;\n//# sourceMappingURL=getSettings.js.map","import MicroEvent from \"./contrib/microevent.js\";\nimport MicroPlugin from \"./contrib/microplugin.js\";\nimport { Sifter } from '@orchidjs/sifter';\nimport { escape_regex } from '@orchidjs/unicode-variants';\nimport { highlight, removeHighlight } from \"./contrib/highlight.js\";\nimport * as constants from \"./constants.js\";\nimport getSettings from \"./getSettings.js\";\nimport { hash_key, get_hash, escape_html, debounce_events, getSelection, preventDefault, addEvent, loadDebounce, timeout, isKeyDown, getId, addSlashes, append, iterate } from \"./utils.js\";\nimport { getDom, isHtmlString, escapeQuery, triggerEvent, applyCSS, addClasses, removeClasses, parentMatch, getTail, isEmptyObject, nodeIndex, setAttr, replaceNode } from \"./vanilla.js\";\nvar instance_i = 0;\nexport default class TomSelect extends MicroPlugin(MicroEvent) {\n constructor(input_arg, user_settings) {\n super();\n this.order = 0;\n this.isOpen = false;\n this.isDisabled = false;\n this.isReadOnly = false;\n this.isInvalid = false; // @deprecated 1.8\n this.isValid = true;\n this.isLocked = false;\n this.isFocused = false;\n this.isInputHidden = false;\n this.isSetup = false;\n this.isDropdownContentStale = true;\n this.ignoreFocus = false;\n this.ignoreHover = false;\n this.hasOptions = false;\n this.lastValue = '';\n this.caretPos = 0;\n this.loading = 0;\n this.loadedSearches = {};\n this.activeOption = null;\n this.activeItems = [];\n this.optgroups = {};\n this.options = {};\n this.userOptions = {};\n this.items = [];\n this.refreshTimeout = null;\n instance_i++;\n var dir;\n var input = getDom(input_arg);\n if (input.tomselect) {\n throw new Error('Tom Select already initialized on this element');\n }\n input.tomselect = this;\n // detect rtl environment\n var computedStyle = window.getComputedStyle && window.getComputedStyle(input, null);\n dir = computedStyle.getPropertyValue('direction');\n // setup default state\n const settings = getSettings(input, user_settings);\n this.settings = settings;\n this.input = input;\n this.tabIndex = input.tabIndex || 0;\n this.is_select_tag = input.tagName.toLowerCase() === 'select';\n this.rtl = /rtl/i.test(dir);\n this.inputId = getId(input, 'tomselect-' + instance_i);\n this.isRequired = input.required;\n // search system\n this.sifter = new Sifter(this.options, { diacritics: settings.diacritics });\n // option-dependent defaults\n settings.mode = settings.mode || (settings.maxItems === 1 ? 'single' : 'multi');\n if (typeof settings.hideSelected !== 'boolean') {\n settings.hideSelected = settings.mode === 'multi';\n }\n if (typeof settings.hidePlaceholder !== 'boolean') {\n settings.hidePlaceholder = settings.mode !== 'multi';\n }\n // set up createFilter callback\n var filter = settings.createFilter;\n if (typeof filter !== 'function') {\n if (typeof filter === 'string') {\n filter = new RegExp(filter);\n }\n if (filter instanceof RegExp) {\n settings.createFilter = (input) => filter.test(input);\n }\n else {\n settings.createFilter = (value) => {\n return this.settings.duplicates || !this.options[value];\n };\n }\n }\n this.initializePlugins(settings.plugins);\n this.setupCallbacks();\n this.setupTemplates();\n // Create all elements\n const wrapper = getDom('<div>');\n const control = getDom('<div>');\n const dropdown = this._render('dropdown');\n const dropdown_content = getDom(`<div role=\"listbox\" tabindex=\"-1\">`);\n const classes = this.input.getAttribute('class') || '';\n const inputMode = settings.mode;\n var control_input;\n addClasses(wrapper, settings.wrapperClass, classes, inputMode);\n addClasses(control, settings.controlClass);\n append(wrapper, control);\n addClasses(dropdown, settings.dropdownClass, inputMode);\n if (settings.copyClassesToDropdown) {\n addClasses(dropdown, classes);\n }\n addClasses(dropdown_content, settings.dropdownContentClass);\n append(dropdown, dropdown_content);\n getDom(settings.dropdownParent || wrapper).appendChild(dropdown);\n // default controlInput\n if (isHtmlString(settings.controlInput)) {\n control_input = getDom(settings.controlInput);\n // set attributes\n var attrs = ['autocorrect', 'autocapitalize', 'autocomplete', 'spellcheck', 'aria-label'];\n iterate(attrs, (attr) => {\n if (input.getAttribute(attr)) {\n setAttr(control_input, { [attr]: input.getAttribute(attr) });\n }\n });\n control_input.tabIndex = -1;\n control.appendChild(control_input);\n this.focus_node = control_input;\n // dom element\n }\n else if (settings.controlInput) {\n control_input = getDom(settings.controlInput);\n this.focus_node = control_input;\n }\n else {\n control_input = getDom('<input/>');\n this.focus_node = control;\n }\n this.wrapper = wrapper;\n this.dropdown = dropdown;\n this.dropdown_content = dropdown_content;\n this.control = control;\n this.control_input = control_input;\n this.setup();\n }\n /**\n * set up event bindings.\n *\n */\n setup() {\n const self = this;\n const settings = self.settings;\n const control_input = self.control_input;\n const dropdown = self.dropdown;\n const dropdown_content = self.dropdown_content;\n const wrapper = self.wrapper;\n const control = self.control;\n const input = self.input;\n const focus_node = self.focus_node;\n const passive_event = { passive: true };\n const listboxId = self.inputId + '-ts-dropdown';\n setAttr(dropdown_content, {\n id: listboxId\n });\n setAttr(focus_node, {\n role: 'combobox',\n 'aria-haspopup': 'listbox',\n 'aria-expanded': 'false',\n 'aria-controls': listboxId\n });\n const control_id = getId(focus_node, self.inputId + '-ts-control');\n const query = \"label[for='\" + escapeQuery(self.inputId) + \"']\";\n const label = document.querySelector(query);\n const label_click = self.focus.bind(self);\n if (label) {\n addEvent(label, 'click', label_click);\n setAttr(label, { for: control_id });\n const label_id = getId(label, self.inputId + '-ts-label');\n setAttr(focus_node, { 'aria-labelledby': label_id });\n setAttr(dropdown_content, { 'aria-labelledby': label_id });\n }\n wrapper.style.width = input.style.width;\n wrapper.style.minWidth = input.style.minWidth;\n wrapper.style.maxWidth = input.style.maxWidth;\n if (self.plugins.names.length) {\n const classes_plugins = 'plugin-' + self.plugins.names.join(' plugin-');\n addClasses([wrapper, dropdown], classes_plugins);\n }\n if ((settings.maxItems === null || settings.maxItems > 1) && self.is_select_tag) {\n setAttr(input, { multiple: 'multiple' });\n }\n if (settings.placeholder) {\n setAttr(control_input, { placeholder: settings.placeholder });\n }\n // if splitOn was not passed in, construct it from the delimiter to allow pasting universally\n if (!settings.splitOn && settings.delimiter) {\n settings.splitOn = new RegExp('\\\\s*' + escape_regex(settings.delimiter) + '+\\\\s*');\n }\n // debounce user defined load() if loadThrottle > 0\n // after initializePlugins() so plugins can create/modify user defined loaders\n if (settings.load && settings.loadThrottle) {\n settings.load = loadDebounce(settings.load, settings.loadThrottle);\n }\n addEvent(dropdown, 'mousemove', () => {\n self.ignoreHover = false;\n });\n addEvent(dropdown, 'mouseenter', (e) => {\n var target_match = parentMatch(e.target, '[data-selectable]', dropdown);\n if (target_match)\n self.onOptionHover(e, target_match);\n }, { capture: true });\n // clicking on an option should select it\n addEvent(dropdown, 'click', (evt) => {\n const option = parentMatch(evt.target, '[data-selectable]');\n if (option) {\n self.onOptionSelect(evt, option);\n preventDefault(evt, true);\n }\n });\n addEvent(control, 'click', (evt) => {\n var target_match = parentMatch(evt.target, '[data-ts-item]', control);\n if (target_match && self.onItemSelect(evt, target_match)) {\n preventDefault(evt, true);\n return;\n }\n // retain focus (see control_input mousedown)\n if (control_input.value != '') {\n return;\n }\n self.onClick();\n preventDefault(evt, true);\n });\n // keydown on focus_node for arrow_down/arrow_up\n addEvent(focus_node, 'keydown', (e) => self.onKeyDown(e));\n // keypress and input/keyup\n addEvent(control_input, 'keypress', (e) => self.onKeyPress(e));\n addEvent(control_input, 'input', (e) => self.onInput(e));\n addEvent(focus_node, 'blur', (e) => self.onBlur(e));\n addEvent(focus_node, 'focus', (e) => self.onFocus(e));\n addEvent(control_input, 'paste', (e) => self.onPaste(e));\n const doc_mousedown = (evt) => {\n // blur if target is outside of this instance\n // dropdown is not always inside wrapper\n const target = evt.composedPath()[0];\n if (!wrapper.contains(target) && !dropdown.contains(target)) {\n if (self.isFocused) {\n self.blur();\n }\n self.inputState();\n return;\n }\n // retain focus by preventing native handling. if the\n // event target is the input it should not be modified.\n // otherwise, text selection within the input won't work.\n // Fixes bug #212 which is no covered by tests\n if (target == control_input && self.isOpen) {\n evt.stopPropagation();\n // clicking anywhere in the control should not blur the control_input (which would close the dropdown)\n }\n else {\n preventDefault(evt, true);\n }\n };\n const win_scroll = () => {\n if (self.isOpen) {\n self.positionDropdown();\n }\n };\n const input_invalid = () => {\n if (self.isValid) {\n self.isValid = false;\n self.isInvalid = true;\n self.refreshState();\n }\n };\n addEvent(input, 'invalid', input_invalid);\n addEvent(document, 'mousedown', doc_mousedown);\n addEvent(window, 'scroll', win_scroll, passive_event);\n addEvent(window, 'resize', win_scroll, passive_event);\n this._destroy = () => {\n input.removeEventListener('invalid', input_invalid);\n document.removeEventListener('mousedown', doc_mousedown);\n window.removeEventListener('scroll', win_scroll);\n window.removeEventListener('resize', win_scroll);\n if (label)\n label.removeEventListener('click', label_click);\n };\n // store original html and tab index so that they can be\n // restored when the destroy() method is called.\n this.revertSettings = {\n innerHTML: input.innerHTML,\n tabIndex: input.tabIndex\n };\n input.tabIndex = -1;\n input.insertAdjacentElement('afterend', self.wrapper);\n self.sync(false);\n settings.items = [];\n delete settings.optgroups;\n delete settings.options;\n self.refreshItems();\n self.close(false);\n self.inputState();\n self.isSetup = true;\n self.on('change', this.onChange);\n addClasses(input, 'tomselected', 'ts-hidden-accessible');\n self.trigger('initialize');\n // preload options\n if (settings.preload === true) {\n self.preload();\n }\n }\n /**\n * Register options and optgroups\n *\n */\n setupOptions(options = [], optgroups = []) {\n // build options table\n this.addOptions(options);\n // build optgroup table\n iterate(optgroups, (optgroup) => {\n this.registerOptionGroup(optgroup);\n });\n }\n /**\n * Sets up default rendering functions.\n */\n setupTemplates() {\n var self = this;\n var field_label = self.settings.labelField;\n var field_optgroup = self.settings.optgroupLabelField;\n var templates = {\n 'optgroup': (data) => {\n let optgroup = document.createElement('div');\n optgroup.className = 'optgroup';\n optgroup.appendChild(data.options);\n return optgroup;\n },\n 'optgroup_header': (data, escape) => {\n return '<div class=\"optgroup-header\">' + escape(data[field_optgroup]) + '</div>';\n },\n 'option': (data, escape) => {\n return '<div>' + escape(data[field_label]) + '</div>';\n },\n 'item': (data, escape) => {\n return '<div>' + escape(data[field_label]) + '</div>';\n },\n 'option_create': (data, escape) => {\n return '<div class=\"create\">Add <strong>' + escape(data.input) + '</strong>&hellip;</div>';\n },\n 'no_results': () => {\n return '<div class=\"no-results\">No results found</div>';\n },\n 'loading': () => {\n return '<div class=\"spinner\"></div>';\n },\n 'not_loading': () => { },\n 'dropdown': () => {\n return '<div></div>';\n }\n };\n self.settings.render = Object.assign({}, templates, self.settings.render);\n }\n /**\n * Maps fired events to callbacks provided\n * in the settings used when creating the control.\n */\n setupCallbacks() {\n var key, fn;\n var callbacks = {\n 'initialize': 'onInitialize',\n 'change': 'onChange',\n 'item_add': 'onItemAdd',\n 'item_remove': 'onItemRemove',\n 'item_select': 'onItemSelect',\n 'clear': 'onClear',\n 'option_add': 'onOptionAdd',\n 'option_remove': 'onOptionRemove',\n 'option_clear': 'onOptionClear',\n 'optgroup_add': 'onOptionGroupAdd',\n 'optgroup_remove': 'onOptionGroupRemove',\n 'optgroup_clear': 'onOptionGroupClear',\n 'dropdown_open': 'onDropdownOpen',\n 'dropdown_close': 'onDropdownClose',\n 'type': 'onType',\n 'load': 'onLoad',\n 'focus': 'onFocus',\n 'blur': 'onBlur'\n };\n for (key in callbacks) {\n fn = this.settings[callbacks[key]];\n if (fn)\n this.on(key, fn);\n }\n }\n /**\n * Sync the Tom Select instance with the original input or select\n *\n */\n sync(get_settings = true) {\n const self = this;\n const settings = get_settings ? getSettings(self.input, { delimiter: self.settings.delimiter, allowEmptyOption: self.settings.allowEmptyOption }) : self.settings;\n self.setupOptions(settings.options, settings.optgroups);\n self.setValue(settings.items || [], true); // silent prevents recursion\n if (self.input.disabled) {\n self.disable();\n }\n else if (self.input.readOnly) {\n self.setReadOnly(true);\n }\n else {\n self.enable(); //sets tabIndex\n }\n self.lastQuery = null; // so updated options will be displayed in dropdown\n }\n /**\n * Triggered when the main control element\n * has a click event.\n *\n */\n onClick() {\n var self = this;\n if (self.activeItems.length > 0) {\n self.clearActiveItems();\n self.focus();\n return;\n }\n if (self.isFocused && self.isOpen) {\n self.blur();\n }\n else {\n self.focus();\n }\n }\n /**\n * @deprecated v1.7\n *\n */\n onMouseDown() { }\n /**\n * Triggered when the value of the control has been changed.\n * This should propagate the event to the original DOM\n * input / select element.\n */\n onChange() {\n triggerEvent(this.input, 'input');\n triggerEvent(this.input, 'change');\n }\n /**\n * Triggered on <input> paste.\n *\n */\n onPaste(e) {\n var self = this;\n if (self.isInputHidden || self.isLocked) {\n preventDefault(e);\n return;\n }\n // If a regex or string is included, this will split the pasted\n // input and create Items for each separate value\n if (!self.settings.splitOn) {\n return;\n }\n // Wait for pasted text to be recognized in value\n setTimeout(() => {\n var pastedText = self.inputValue();\n if (!pastedText.match(self.settings.splitOn)) {\n return;\n }\n var splitInput = pastedText.trim().split(self.settings.splitOn);\n iterate(splitInput, (piece) => {\n const hash = hash_key(piece);\n if (hash) {\n if (this.options[piece]) {\n self.addItem(piece);\n }\n else {\n self.createItem(piece);\n }\n }\n });\n }, 0);\n }\n /**\n * Triggered on <input> keypress.\n *\n */\n onKeyPress(e) {\n var self = this;\n if (self.isLocked) {\n preventDefault(e);\n return;\n }\n var character = String.fromCharCode(e.keyCode || e.which);\n if (self.settings.create && self.settings.mode === 'multi' && character === self.settings.delimiter) {\n self.createItem();\n preventDefault(e);\n return;\n }\n }\n /**\n * Triggered on <input> keydown.\n *\n */\n onKeyDown(e) {\n var self = this;\n self.ignoreHover = true;\n if (self.isLocked) {\n if (e.keyCode !== constants.KEY_TAB) {\n preventDefault(e);\n }\n return;\n }\n switch (e.keyCode) {\n // ctrl+A: select all\n case constants.KEY_A:\n if (isKeyDown(constants.KEY_SHORTCUT, e)) {\n if (self.control_input.value == '') {\n preventDefault(e);\n self.selectAll();\n return;\n }\n }\n break;\n // esc: close dropdown\n case constants.KEY_ESC:\n if (self.isOpen) {\n preventDefault(e, true);\n self.close();\n }\n self.clearActiveItems();\n return;\n // down: open dropdown or move selection down\n case constants.KEY_DOWN:\n if (!self.isOpen && self.hasOptions) {\n self.open();\n }\n else if (self.activeOption) {\n let next = self.getAdjacent(self.activeOption, 1);\n if (next)\n self.setActiveOption(next);\n }\n preventDefault(e);\n return;\n // up: move selection up\n case constants.KEY_UP:\n if (self.activeOption) {\n let prev = self.getAdjacent(self.activeOption, -1);\n if (prev)\n self.setActiveOption(prev);\n }\n preventDefault(e);\n return;\n // return: select active option\n case constants.KEY_RETURN:\n if (self.canSelect(self.activeOption)) {\n self.onOptionSelect(e, self.activeOption);\n preventDefault(e);\n // if the option_create=null, the dropdown might be closed\n }\n else if (self.settings.create && self.createItem()) {\n preventDefault(e);\n // don't submit form when searching for a value\n }\n else if (document.activeElement == self.control_input && self.isOpen) {\n preventDefault(e);\n }\n return;\n // left: modifiy item selection to the left\n case constants.KEY_LEFT:\n self.advanceSelection(-1, e);\n return;\n // right: modifiy item selection to the right\n case constants.KEY_RIGHT:\n self.advanceSelection(1, e);\n return;\n // tab: select active option and/or create item\n case constants.KEY_TAB:\n if (self.settings.selectOnTab) {\n if (self.canSelect(self.activeOption)) {\n self.onOptionSelect(e, self.activeOption);\n // prevent default [tab] behaviour of jump to the next field\n // if select isFull, then the dropdown won't be open and [tab] will work normally\n preventDefault(e);\n }\n else if (self.settings.create && self.createItem()) {\n preventDefault(e);\n }\n }\n return;\n // delete|backspace: delete items\n case constants.KEY_BACKSPACE:\n case constants.KEY_DELETE:\n self.deleteSelection(e);\n return;\n }\n // don't enter text in the control_input when active items are selected\n if (self.isInputHidden && !isKeyDown(constants.KEY_SHORTCUT, e)) {\n preventDefault(e);\n }\n }\n /**\n * Triggered on <input> keyup.\n *\n */\n onInput(e) {\n if (this.isLocked) {\n return;\n }\n const value = this.inputValue();\n if (this.lastValue === value)\n return;\n this.lastValue = value;\n if (value == '') {\n this._onInput();\n return;\n }\n if (this.refreshTimeout) {\n window.clearTimeout(this.refreshTimeout);\n }\n this.refreshTimeout = timeout(() => {\n this.refreshTimeout = null;\n this._onInput();\n }, this.settings.refreshThrottle);\n }\n _onInput() {\n const value = this.lastValue;\n if (this.settings.shouldLoad.call(this, value)) {\n this.load(value);\n }\n this.refreshOptions();\n this.trigger('type', value);\n }\n /**\n * Triggered when the user rolls over\n * an option in the autocomplete dropdown menu.\n *\n */\n onOptionHover(evt, option) {\n if (this.ignoreHover)\n return;\n this.setActiveOption(option, false);\n }\n /**\n * Triggered on <input> focus.\n *\n */\n onFocus(e) {\n var self = this;\n var wasFocused = self.isFocused;\n if (self.isDisabled || self.isReadOnly) {\n self.blur();\n preventDefault(e);\n return;\n }\n if (self.ignoreFocus)\n return;\n self.isFocused = true;\n if (self.settings.preload === 'focus')\n self.preload();\n if (!wasFocused)\n self.trigger('focus');\n if (!self.activeItems.length) {\n self.inputState();\n self.refreshOptions(!!self.settings.openOnFocus);\n }\n self.refreshState();\n }\n /**\n * Triggered on <input> blur.\n *\n */\n onBlur(e) {\n if (document.hasFocus() === false)\n return;\n var self = this;\n if (!self.isFocused)\n return;\n self.isFocused = false;\n self.ignoreFocus = false;\n var deactivate = () => {\n self.close();\n self.setActiveItem();\n self.setCaret(self.items.length);\n self.trigger('blur');\n };\n if (self.settings.create && self.settings.createOnBlur) {\n self.createItem(null, deactivate);\n }\n else {\n deactivate();\n }\n }\n /**\n * Triggered when the user clicks on an option\n * in the autocomplete dropdown menu.\n *\n */\n onOptionSelect(evt, option) {\n var value, self = this;\n // should not be possible to trigger a option under a disabled optgroup\n if (option.parentElement && option.parentElement.matches('[data-disabled]')) {\n return;\n }\n if (option.classList.contains('create')) {\n self.createItem(null, () => {\n if (self.settings.closeAfterSelect) {\n self.close();\n }\n else if (self.settings.clearAfterSelect) {\n self.setTextboxValue();\n }\n });\n }\n else {\n value = option.dataset.value;\n if (typeof value !== 'undefined') {\n self.isDropdownContentStale = self.settings.hideSelected;\n self.addItem(value);\n if (self.settings.closeAfterSelect) {\n self.close();\n }\n else if (self.settings.clearAfterSelect) {\n self.setTextboxValue();\n }\n if (!self.settings.hideSelected && evt.type && /click/.test(evt.type)) {\n self.setActiveOption(option);\n }\n }\n }\n }\n /**\n * Return true if the given option can be selected\n *\n */\n canSelect(option) {\n if (this.isOpen && option && this.dropdown_content.contains(option)) {\n return true;\n }\n return false;\n }\n /**\n * Triggered when the user clicks on an item\n * that has been selected.\n *\n */\n onItemSelect(evt, item) {\n var self = this;\n if (!self.isLocked && self.settings.mode === 'multi') {\n preventDefault(evt);\n self.setActiveItem(item, evt);\n return true;\n }\n return false;\n }\n /**\n * Determines whether or not to invoke\n * the user-provided option provider / loader\n *\n * Note, there is a subtle difference between\n * this.canLoad() and this.settings.shouldLoad();\n *\n *\t- settings.shouldLoad() is a user-input validator.\n *\tWhen false is returned, the not_loading template\n *\twill be added to the dropdown\n *\n *\t- canLoad() is lower level validator that checks\n * \tthe Tom Select instance. There is no inherent user\n *\tfeedback when canLoad returns false\n *\n */\n canLoad(value) {\n if (!this.settings.load)\n return false;\n if (this.loadedSearches.hasOwnProperty(value))\n return false;\n return true;\n }\n /**\n * Invokes the user-provided option provider / loader.\n *\n */\n load(value) {\n const self = this;\n if (!self.canLoad(value))\n return;\n addClasses(self.wrapper, self.settings.loadingClass);\n self.loading++;\n const callback = self.loadCallback.bind(self);\n self.settings.load.call(self, value, callback);\n }\n /**\n * Invoked by the user-provided option provider\n *\n */\n loadCallback(options, optgroups) {\n const self = this;\n self.loading = Math.max(self.loading - 1, 0);\n self.isDropdownContentStale = true;\n self.clearActiveOption(); // when new results load, focus should be on first option\n self.setupOptions(options, optgroups);\n self.refreshOptions(self.isFocused && !self.isInputHidden);\n if (!self.loading) {\n removeClasses(self.wrapper, self.settings.loadingClass);\n }\n self.trigger('load', options, optgroups);\n }\n preload() {\n var classList = this.wrapper.classList;\n if (classList.contains('preloaded'))\n return;\n classList.add('preloaded');\n this.load('');\n }\n /**\n * Sets the input field of the control to the specified value.\n *\n */\n setTextboxValue(value = '') {\n var input = this.control_input;\n var changed = input.value !== value;\n if (changed) {\n input.value = value;\n triggerEvent(input, 'update');\n this.lastValue = value;\n }\n }\n /**\n * Returns the value of the control. If multiple items\n * can be selected (e.g. <select multiple>), this returns\n * an array. If only one item can be selected, this\n * returns a string.\n *\n */\n getValue() {\n if (this.is_select_tag && this.input.hasAttribute('multiple')) {\n return this.items;\n }\n return this.items.join(this.settings.delimiter);\n }\n /**\n * Resets the selected items to the given value.\n *\n */\n setValue(value, silent) {\n var events = silent ? [] : ['change'];\n debounce_events(this, events, () => {\n this.clear(silent);\n this.addItems(value, silent);\n });\n }\n /**\n * Resets the number of max items to the given value\n *\n */\n setMaxItems(value) {\n if (value === 0)\n value = null; //reset to unlimited items.\n this.settings.maxItems = value;\n this.refreshState();\n }\n /**\n * Sets the selected item.\n *\n */\n setActiveItem(item, e) {\n var self = this;\n var eventName;\n var i, begin, end, swap;\n var last;\n if (self.settings.mode === 'single')\n return;\n // clear the active selection\n if (!item) {\n self.clearActiveItems();\n if (self.isFocused) {\n self.inputState();\n }\n return;\n }\n // modify selection\n eventName = e && e.type.toLowerCase();\n if (eventName === 'click' && isKeyDown('shiftKey', e) && self.activeItems.length) {\n last = self.getLastActive();\n begin = Array.prototype.indexOf.call(self.control.children, last);\n end = Array.prototype.indexOf.call(self.control.children, item);\n if (begin > end) {\n swap = begin;\n begin = end;\n end = swap;\n }\n for (i = begin; i <= end; i++) {\n item = self.control.children[i];\n if (self.activeItems.indexOf(item) === -1) {\n self.setActiveItemClass(item);\n }\n }\n preventDefault(e);\n }\n else if ((eventName === 'click' && isKeyDown(constants.KEY_SHORTCUT, e)) || (eventName === 'keydown' && isKeyDown('shiftKey', e))) {\n if (item.classList.contains('active')) {\n self.removeActiveItem(item);\n }\n else {\n self.setActiveItemClass(item);\n }\n }\n else {\n self.clearActiveItems();\n self.setActiveItemClass(item);\n }\n // ensure control has focus\n self.inputState();\n if (!self.isFocused) {\n self.focus();\n }\n }\n /**\n * Set the active and last-active classes\n *\n */\n setActiveItemClass(item) {\n const self = this;\n const last_active = self.control.querySelector('.last-active');\n if (last_active)\n removeClasses(last_active, 'last-active');\n addClasses(item, 'active last-active');\n self.trigger('item_select', item);\n if (self.activeItems.indexOf(item) == -1) {\n self.activeItems.push(item);\n }\n }\n /**\n * Remove active item\n *\n */\n removeActiveItem(item) {\n var idx = this.activeItems.indexOf(item);\n this.activeItems.splice(idx, 1);\n removeClasses(item, 'active');\n }\n /**\n * Clears all the active items\n *\n */\n clearActiveItems() {\n removeClasses(this.activeItems, 'active');\n this.activeItems = [];\n }\n /**\n * Sets the selected item in the dropdown menu\n * of available options.\n *\n */\n setActiveOption(option, scroll = true) {\n if (option === this.activeOption) {\n return;\n }\n this.clearActiveOption();\n if (!option)\n return;\n this.activeOption = option;\n setAttr(this.focus_node, { 'aria-activedescendant': option.getAttribute('id') });\n setAttr(option, { 'aria-selected': 'true' });\n addClasses(option, 'active');\n if (scroll)\n this.scrollToOption(option);\n }\n /**\n * Sets the dropdown_content scrollTop to display the option\n *\n */\n scrollToOption(option, behavior) {\n if (!option)\n return;\n const content = this.dropdown_content;\n const height_menu = content.clientHeight;\n const scrollTop = content.scrollTop || 0;\n const height_item = option.offsetHeight;\n const y = option.getBoundingClientRect().top - content.getBoundingClientRect().top + scrollTop;\n if (y + height_item > height_menu + scrollTop) {\n this.scroll(y - height_menu + height_item, behavior);\n }\n else if (y < scrollTop) {\n this.scroll(y, behavior);\n }\n }\n /**\n * Scroll the dropdown to the given position\n *\n */\n scroll(scrollTop, behavior) {\n const content = this.dropdown_content;\n if (behavior) {\n content.style.scrollBehavior = behavior;\n }\n content.scrollTop = scrollTop;\n content.style.scrollBehavior = '';\n }\n /**\n * Clears the active option\n *\n */\n clearActiveOption() {\n if (this.activeOption) {\n removeClasses(this.activeOption, 'active');\n setAttr(this.activeOption, { 'aria-selected': null });\n }\n this.activeOption = null;\n setAttr(this.focus_node, { 'aria-activedescendant': null });\n }\n /**\n * Selects all items (CTRL + A).\n */\n selectAll() {\n const self = this;\n if (self.settings.mode === 'single')\n return;\n const activeItems = self.controlChildren();\n if (!activeItems.length)\n return;\n self.inputState();\n self.close();\n self.activeItems = activeItems;\n iterate(activeItems, (item) => {\n self.setActiveItemClass(item);\n });\n }\n /**\n * Determines if the control_input should be in a hidden or visible state\n *\n */\n inputState() {\n var self = this;\n if (!self.control.contains(self.control_input))\n return;\n setAttr(self.control_input, { placeholder: self.settings.placeholder });\n if (self.activeItems.length > 0 || (!self.isFocused && self.settings.hidePlaceholder && self.items.length > 0)) {\n self.setTextboxValue();\n self.isInputHidden = true;\n }\n else {\n if (self.settings.hidePlaceholder && self.items.length > 0) {\n setAttr(self.control_input, { placeholder: '' });\n }\n self.isInputHidden = false;\n }\n self.wrapper.classList.toggle('input-hidden', self.isInputHidden);\n }\n /**\n * Get the input value\n */\n inputValue() {\n return this.control_input.value.trim();\n }\n /**\n * Gives the control focus.\n */\n focus() {\n var self = this;\n if (self.isDisabled || self.isReadOnly)\n return;\n self.ignoreFocus = true;\n const focusTarget = this.control_input.offsetWidth ? this.control_input : this.focus_node;\n focusTarget.focus();\n setTimeout(() => {\n self.ignoreFocus = false;\n // Fix https://github.com/orchidjs/tom-select/issues/806\n // Only proceed if this instance's element is still the active element. If Edge autofill\n // (or anything else) has moved focus to a different element in the interim, calling\n // onFocus() here would steal focus back and restart the cascade loop.\n const root = focusTarget.getRootNode();\n if (root.activeElement !== focusTarget) {\n return;\n }\n this.onFocus();\n }, 0);\n }\n /**\n * Forces the control out of focus.\n *\n */\n blur() {\n this.focus_node.blur();\n this.onBlur();\n }\n /**\n * Returns a function that scores an object\n * to show how good of a match it is to the\n * provided query.\n *\n * @return {function}\n */\n getScoreFunction(query) {\n return this.sifter.getScoreFunction(query, this.getSearchOptions());\n }\n /**\n * Returns search options for sifter (the system\n * for scoring and sorting results).\n *\n * @see https://github.com/orchidjs/sifter.js\n * @return {object}\n */\n getSearchOptions() {\n var settings = this.settings;\n var sort = settings.sortField;\n if (typeof settings.sortField === 'string') {\n sort = [{ field: settings.sortField }];\n }\n return {\n fields: settings.searchField,\n conjunction: settings.searchConjunction,\n sort: sort,\n nesting: settings.nesting\n };\n }\n /**\n * Searches through available options and returns\n * a sorted array of matches.\n *\n */\n search(query) {\n var result, calculateScore;\n var self = this;\n var options = this.getSearchOptions();\n // validate user-provided result scoring function\n if (self.settings.score) {\n calculateScore = self.settings.score.call(self, query);\n if (typeof calculateScore !== 'function') {\n throw new Error('Tom Select \"score\" setting must be a function that returns a function');\n }\n }\n // perform search\n if (self.isDropdownContentStale || query !== self.lastQuery) {\n self.lastQuery = query;\n // temp fix for https://github.com/orchidjs/tom-select/issues/987\n // UI crashed when more than 30 same chars in a row, prevent search and return empt result\n if (/(.)\\1{15,}/.test(query)) {\n query = '';\n }\n result = self.sifter.search(query, Object.assign(options, { score: calculateScore }));\n self.currentResults = result;\n }\n else {\n result = Object.assign({}, self.currentResults);\n }\n // filter out selected items\n if (self.settings.hideSelected) {\n result.items = result.items.filter((item) => {\n let hashed = hash_key(item.id);\n return !(hashed !== null && self.items.indexOf(hashed) !== -1);\n });\n }\n return result;\n }\n /**\n * Refreshes the list of available options shown\n * in the autocomplete dropdown menu.\n *\n */\n refreshOptions(triggerDropdown = true) {\n var i, j, k, n, optgroup, optgroups, html, has_create_option, active_group;\n var create;\n const groups = {};\n const groups_order = [];\n var self = this;\n var query = self.inputValue();\n const same_query = query === self.lastQuery || (query == '' && self.lastQuery == null);\n var results = self.search(query);\n var active_option = null;\n var show_dropdown = self.settings.shouldOpen || false;\n var dropdown_content = self.dropdown_content;\n if (same_query) {\n active_option = self.activeOption;\n if (active_option) {\n active_group = active_option.closest('[data-group]');\n }\n }\n // build markup\n n = results.items.length;\n if (typeof self.settings.maxOptions === 'number') {\n n = Math.min(n, self.settings.maxOptions);\n }\n if (n > 0) {\n show_dropdown = true;\n }\n // get fragment for group and the position of the group in group_order\n const getGroupFragment = (optgroup, order) => {\n let group_order_i = groups[optgroup];\n if (group_order_i !== undefined) {\n let order_group = groups_order[group_order_i];\n if (order_group !== undefined) {\n return [group_order_i, order_group.fragment];\n }\n }\n let group_fragment = document.createDocumentFragment();\n group_order_i = groups_order.length;\n groups_order.push({ fragment: group_fragment, order, optgroup });\n return [group_order_i, group_fragment];\n };\n // render and group available options individually\n for (i = 0; i < n; i++) {\n // get option dom element\n let item = results.items[i];\n if (!item)\n continue;\n let opt_value = item.id;\n let option = self.options[opt_value];\n if (option === undefined)\n continue;\n let opt_hash = get_hash(opt_value);\n let option_el = self.getOption(opt_hash, true);\n // toggle 'selected' class\n if (!self.settings.hideSelected) {\n option_el.classList.toggle('selected', self.items.includes(opt_hash));\n }\n optgroup = option[self.settings.optgroupField] || '';\n optgroups = Array.isArray(optgroup) ? optgroup : [optgroup];\n for (j = 0, k = optgroups && optgroups.length; j < k; j++) {\n optgroup = optgroups[j];\n let order = option.$order;\n let self_optgroup = self.optgroups[optgroup];\n if (self_optgroup === undefined && typeof self.settings.optionGroupRegister === 'function') {\n var regGroup;\n if (regGroup = self.settings.optionGroupRegister.apply(self, [optgroup])) {\n self.registerOptionGroup(regGroup);\n }\n }\n self_optgroup = self.optgroups[optgroup];\n if (self_optgroup === undefined) {\n optgroup = '';\n }\n else {\n order = self_optgroup.$order;\n }\n const [group_order_i, group_fragment] = getGroupFragment(optgroup, order);\n // nodes can only have one parent, so if the option is in mutple groups, we need a clone\n if (j > 0) {\n option_el = option_el.cloneNode(true);\n setAttr(option_el, { id: option.$id + '-clone-' + j, 'aria-selected': null });\n option_el.classList.add('ts-cloned');\n removeClasses(option_el, 'active');\n // make sure we keep the activeOption in the same group\n if (self.activeOption && self.activeOption.dataset.value == opt_value) {\n if (active_group && active_group.dataset.group === optgroup.toString()) {\n active_option = option_el;\n }\n }\n }\n group_fragment.appendChild(option_el);\n if (optgroup != '') {\n groups[optgroup] = group_order_i;\n }\n }\n }\n // sort optgroups\n if (self.settings.lockOptgroupOrder) {\n groups_order.sort((a, b) => {\n return a.order - b.order;\n });\n }\n // render optgroup headers & join groups\n html = document.createDocumentFragment();\n iterate(groups_order, (group_order) => {\n let group_fragment = group_order.fragment;\n let optgroup = group_order.optgroup;\n if (!group_fragment || !group_fragment.children.length)\n return;\n let group_heading = self.optgroups[optgroup];\n if (group_heading !== undefined) {\n let group_options = document.createDocumentFragment();\n let header = self.render('optgroup_header', group_heading);\n append(group_options, header);\n append(group_options, group_fragment);\n let group_html = self.render('optgroup', { group: group_heading, options: group_options });\n append(html, group_html);\n }\n else {\n append(html, group_fragment);\n }\n });\n dropdown_content.innerHTML = '';\n append(dropdown_content, html);\n self.isDropdownContentStale = false;\n // highlight matching terms inline\n if (self.settings.highlight) {\n removeHighlight(dropdown_content);\n if (results.query.length && results.tokens.length) {\n iterate(results.tokens, (tok) => {\n highlight(dropdown_content, tok.regex);\n });\n }\n }\n // helper method for adding templates to dropdown\n var add_template = (template) => {\n let content = self.render(template, { input: query });\n if (content) {\n show_dropdown = true;\n dropdown_content.insertBefore(content, dropdown_content.firstChild);\n }\n return content;\n };\n // add loading message\n if (self.loading) {\n add_template('loading');\n // invalid query\n }\n else if (!self.settings.shouldLoad.call(self, query)) {\n add_template('not_loading');\n // add no_results message\n }\n else if (results.items.length === 0) {\n add_template('no_results');\n }\n // add create option\n has_create_option = self.canCreate(query);\n if (has_create_option) {\n create = add_template('option_create');\n }\n // activate\n self.hasOptions = results.items.length > 0 || has_create_option;\n if (show_dropdown) {\n if (results.items.length > 0) {\n if (!active_option && self.settings.mode === 'single' && self.items[0] != undefined) {\n active_option = self.getOption(self.items[0]);\n }\n if (!dropdown_content.contains(active_option)) {\n let active_index = 0;\n if (create && !self.settings.addPrecedence) {\n active_index = 1;\n }\n active_option = self.selectable()[active_index];\n }\n }\n else if (create) {\n active_option = create;\n }\n if (triggerDropdown && !self.isOpen) {\n self.open();\n self.scrollToOption(active_option, 'auto');\n }\n self.setActiveOption(active_option);\n }\n else {\n self.clearActiveOption();\n if (triggerDropdown && self.isOpen) {\n self.close(false); // if create_option=null, we want the dropdown to close but not reset the textbox value\n }\n }\n }\n /**\n * Return list of selectable options\n *\n */\n selectable() {\n return this.dropdown_content.querySelectorAll('[data-selectable]');\n }\n /**\n * Adds an available option. If it already exists,\n * nothing will happen. Note: this does not refresh\n * the options list dropdown (use `refreshOptions`\n * for that).\n *\n * Usage:\n *\n * this.addOption(data)\n *\n */\n addOption(data, user_created = false) {\n const self = this;\n // @deprecated 1.7.7\n // use addOptions( array, user_created ) for adding multiple options\n if (Array.isArray(data)) {\n self.addOptions(data, user_created);\n return false;\n }\n const key = hash_key(data[self.settings.valueField]);\n if (key === null || self.options.hasOwnProperty(key)) {\n self.updateOption(data[self.settings.valueField], data);\n return false;\n }\n data.$order = data.$order || ++self.order;\n data.$id = self.inputId + '-opt-' + data.$order;\n self.options[key] = data;\n self.isDropdownContentStale = true;\n if (user_created) {\n self.userOptions[key] = user_created;\n self.trigger('option_add', key, data);\n }\n return key;\n }\n /**\n * Add multiple options\n *\n */\n addOptions(data, user_created = false) {\n iterate(data, (dat) => {\n this.addOption(dat, user_created);\n });\n }\n /**\n * @deprecated 1.7.7\n */\n registerOption(data) {\n return this.addOption(data);\n }\n /**\n * Registers an option group to the pool of option groups.\n *\n * @return {boolean|string}\n */\n registerOptionGroup(data) {\n var key = hash_key(data[this.settings.optgroupValueField]);\n if (key === null)\n return false;\n data.$order = data.$order || ++this.order;\n this.optgroups[key] = data;\n return key;\n }\n /**\n * Registers a new optgroup for options\n * to be bucketed into.\n *\n */\n addOptionGroup(id, data) {\n var hashed_id;\n data[this.settings.optgroupValueField] = id;\n if (hashed_id = this.registerOptionGroup(data)) {\n this.trigger('optgroup_add', hashed_id, data);\n }\n }\n /**\n * Removes an existing option group.\n *\n */\n removeOptionGroup(id) {\n if (this.optgroups.hasOwnProperty(id)) {\n delete this.optgroups[id];\n this.clearCache();\n this.trigger('optgroup_remove', id);\n }\n }\n /**\n * Clears all existing option groups.\n */\n clearOptionGroups() {\n this.optgroups = {};\n this.clearCache();\n this.trigger('optgroup_clear');\n }\n /**\n * Updates an option available for selection. If\n * it is visible in the selected items or options\n * dropdown, it will be re-rendered automatically.\n *\n */\n updateOption(value, data) {\n const self = this;\n var item_new;\n var index_item;\n const value_old = hash_key(value);\n const value_new = hash_key(data[self.settings.valueField]);\n // sanity checks\n if (value_old === null)\n return;\n const data_old = self.options[value_old];\n if (data_old == undefined)\n return;\n if (typeof value_new !== 'string')\n throw new Error('Value must be set in option data');\n const option = self.getOption(value_old);\n const item = self.getItem(value_old);\n data.$order = data.$order || data_old.$order;\n delete self.options[value_old];\n // invalidate render cache\n // don't remove existing node yet, we'll remove it after replacing it\n self.uncacheValue(value_new);\n self.options[value_new] = data;\n // update the option if it's in the dropdown\n if (option) {\n if (self.dropdown_content.contains(option)) {\n const option_new = self._render('option', data);\n replaceNode(option, option_new);\n if (self.activeOption === option) {\n self.setActiveOption(option_new);\n }\n }\n option.remove();\n }\n // update the item if we have one\n if (item) {\n index_item = self.items.indexOf(value_old);\n if (index_item !== -1) {\n self.items.splice(index_item, 1, value_new);\n }\n item_new = self._render('item', data);\n if (item.classList.contains('active'))\n addClasses(item_new, 'active');\n replaceNode(item, item_new);\n }\n // we might have updated the sortField\n self.isDropdownContentStale = true;\n }\n /**\n * Removes a single option.\n *\n */\n removeOption(value, silent) {\n const self = this;\n value = get_hash(value);\n self.uncacheValue(value);\n delete self.userOptions[value];\n delete self.options[value];\n self.isDropdownContentStale = true;\n self.trigger('option_remove', value);\n self.removeItem(value, silent);\n }\n /**\n * Clears all options.\n */\n clearOptions(filter) {\n const boundFilter = (filter || this.clearFilter).bind(this);\n this.loadedSearches = {};\n this.userOptions = {};\n this.clearCache();\n const selected = {};\n iterate(this.options, (option, key) => {\n if (boundFilter(option, key)) {\n selected[key] = option;\n }\n });\n this.options = this.sifter.items = selected;\n this.isDropdownContentStale = true;\n this.trigger('option_clear');\n }\n /**\n * Used by clearOptions() to decide whether or not an option should be removed\n * Return true to keep an option, false to remove\n *\n */\n clearFilter(option, value) {\n if (this.items.indexOf(value) >= 0) {\n return true;\n }\n return false;\n }\n /**\n * Returns the dom element of the option\n * matching the given value.\n *\n */\n getOption(value, create = false) {\n const hashed = hash_key(value);\n if (hashed === null)\n return null;\n const option = this.options[hashed];\n if (option != undefined) {\n if (option.$div) {\n return option.$div;\n }\n if (create) {\n return this._render('option', option);\n }\n }\n return null;\n }\n /**\n * Returns the dom element of the next or previous dom element of the same type\n * Note: adjacent options may not be adjacent DOM elements (optgroups)\n *\n */\n getAdjacent(option, direction, type = 'option') {\n var self = this, all;\n if (!option) {\n return null;\n }\n if (type == 'item') {\n all = self.controlChildren();\n }\n else {\n all = self.dropdown_content.querySelectorAll('[data-selectable]');\n }\n for (let i = 0; i < all.length; i++) {\n if (all[i] != option) {\n continue;\n }\n if (direction > 0) {\n return all[i + 1];\n }\n return all[i - 1];\n }\n return null;\n }\n /**\n * Returns the dom element of the item\n * matching the given value.\n *\n */\n getItem(item) {\n if (typeof item == 'object') {\n return item;\n }\n var value = hash_key(item);\n return value !== null\n ? this.control.querySelector(`[data-value=\"${addSlashes(value)}\"]`)\n : null;\n }\n /**\n * \"Selects\" multiple items at once. Adds them to the list\n * at the current caret position.\n *\n */\n addItems(values, silent) {\n var self = this;\n var items = Array.isArray(values) ? values : [values];\n items = items.filter(x => self.items.indexOf(x) === -1);\n const last_item = items[items.length - 1];\n items.forEach(item => {\n self.isPending = (item !== last_item);\n self.addItem(item, silent);\n });\n }\n /**\n * \"Selects\" an item. Adds it to the list\n * at the current caret position.\n *\n */\n addItem(value, silent) {\n var events = silent ? [] : ['change', 'dropdown_close'];\n debounce_events(this, events, () => {\n var item, wasFull;\n const self = this;\n const inputMode = self.settings.mode;\n const hashed = hash_key(value);\n if (hashed && self.items.indexOf(hashed) !== -1) {\n if (inputMode === 'single') {\n self.close();\n }\n if (inputMode === 'single' || !self.settings.duplicates) {\n return;\n }\n }\n if (hashed === null || !self.options.hasOwnProperty(hashed))\n return;\n if (inputMode === 'single')\n self.clear(silent);\n if (inputMode === 'multi' && self.isFull())\n return;\n item = self._render('item', self.options[hashed]);\n if (self.control.contains(item)) { // duplicates\n item = item.cloneNode(true);\n }\n wasFull = self.isFull();\n self.items.splice(self.caretPos, 0, hashed);\n self.insertAtCaret(item);\n if (self.isSetup) {\n // update menu / remove the option (if this is not one item being added as part of series)\n if (!self.isPending && self.settings.hideSelected) {\n let option = self.getOption(hashed);\n let next = self.getAdjacent(option, 1);\n if (next) {\n self.setActiveOption(next);\n }\n }\n //remove input value when enabled\n if (self.settings.clearAfterSelect) {\n self.setTextboxValue();\n }\n // refreshOptions after setActiveOption(),\n // otherwise setActiveOption() will be called by refreshOptions() with the wrong value\n if (!self.isPending && !self.settings.closeAfterSelect) {\n self.refreshOptions(self.isFocused && inputMode !== 'single');\n }\n // hide the menu if the maximum number of items have been selected or no options are left\n if (self.settings.closeAfterSelect != false && self.isFull()) {\n self.close();\n }\n else if (!self.isPending) {\n self.positionDropdown();\n }\n self.trigger('item_add', hashed, item);\n if (!self.isPending) {\n self.updateOriginalInput({ silent: silent });\n }\n }\n if (!self.isPending || (!wasFull && self.isFull())) {\n self.inputState();\n self.refreshState();\n }\n });\n }\n /**\n * Removes the selected item matching\n * the provided value.\n *\n */\n removeItem(item = null, silent) {\n const self = this;\n item = self.getItem(item);\n if (!item)\n return;\n var i, idx;\n const value = item.dataset.value;\n i = nodeIndex(item);\n item.remove();\n if (item.classList.contains('active')) {\n idx = self.activeItems.indexOf(item);\n self.activeItems.splice(idx, 1);\n removeClasses(item, 'active');\n }\n self.items.splice(i, 1);\n self.isDropdownContentStale = true;\n if (!self.settings.persist && self.userOptions.hasOwnProperty(value)) {\n self.removeOption(value, silent);\n }\n if (i < self.caretPos) {\n self.setCaret(self.caretPos - 1);\n }\n self.updateOriginalInput({ silent: silent });\n self.refreshState();\n self.positionDropdown();\n self.trigger('item_remove', value, item);\n }\n /**\n * Invokes the `create` method provided in the\n * TomSelect options that should provide the data\n * for the new item, given the user input.\n *\n * Once this completes, it will be added\n * to the item list.\n *\n */\n createItem(input = null, callback = () => { }) {\n // triggerDropdown parameter @deprecated 2.1.1\n if (arguments.length === 3) {\n callback = arguments[2];\n }\n if (typeof callback != 'function') {\n callback = () => { };\n }\n var self = this;\n var caret = self.caretPos;\n var output;\n input = input || self.inputValue();\n if (!self.canCreate(input)) {\n const hash = hash_key(input);\n if (hash) {\n if (this.options[input]) {\n self.addItem(input);\n }\n }\n callback();\n return false;\n }\n self.lock();\n var created = false;\n var create = (data) => {\n self.unlock();\n if (!data || typeof data !== 'object')\n return callback();\n var value = hash_key(data[self.settings.valueField]);\n if (typeof value !== 'string') {\n return callback();\n }\n self.setTextboxValue();\n self.addOption(data, true);\n self.setCaret(caret);\n self.addItem(value);\n callback(data);\n created = true;\n };\n if (typeof self.settings.create === 'function') {\n output = self.settings.create.call(this, input, create);\n }\n else {\n output = {\n [self.settings.labelField]: input,\n [self.settings.valueField]: input,\n };\n }\n if (!created) {\n create(output);\n }\n return true;\n }\n /**\n * Re-renders the selected item lists.\n */\n refreshItems() {\n var self = this;\n self.isDropdownContentStale = true;\n if (self.isSetup) {\n self.addItems(self.items);\n }\n self.updateOriginalInput();\n self.refreshState();\n }\n /**\n * Updates all state-dependent attributes\n * and CSS classes.\n */\n refreshState() {\n const self = this;\n self.refreshValidityState();\n const isFull = self.isFull();\n const isLocked = self.isLocked;\n self.wrapper.classList.toggle('rtl', self.rtl);\n const wrap_classList = self.wrapper.classList;\n wrap_classList.toggle('focus', self.isFocused);\n wrap_classList.toggle('disabled', self.isDisabled);\n wrap_classList.toggle('readonly', self.isReadOnly);\n wrap_classList.toggle('required', self.isRequired);\n wrap_classList.toggle('invalid', !self.isValid);\n wrap_classList.toggle('locked', isLocked);\n wrap_classList.toggle('full', isFull);\n wrap_classList.toggle('input-active', self.isFocused && !self.isInputHidden);\n wrap_classList.toggle('dropdown-active', self.isOpen);\n wrap_classList.toggle('has-options', isEmptyObject(self.options));\n wrap_classList.toggle('has-items', self.items.length > 0);\n }\n /**\n * Update the `required` attribute of both input and control input.\n *\n * The `required` property needs to be activated on the control input\n * for the error to be displayed at the right place. `required` also\n * needs to be temporarily deactivated on the input since the input is\n * hidden and can't show errors.\n */\n refreshValidityState() {\n var self = this;\n if (!self.input.validity) {\n return;\n }\n self.isValid = self.input.validity.valid;\n self.isInvalid = !self.isValid;\n }\n /**\n * Determines whether or not more items can be added\n * to the control without exceeding the user-defined maximum.\n *\n * @returns {boolean}\n */\n isFull() {\n return this.settings.maxItems !== null && this.items.length >= this.settings.maxItems;\n }\n /**\n * Refreshes the original <select> or <input>\n * element to reflect the current state.\n *\n */\n updateOriginalInput(opts = {}) {\n const self = this;\n var option, label;\n const empty_option = self.input.querySelector('option[value=\"\"]');\n if (self.is_select_tag) {\n const selected = [];\n const has_selected = self.input.querySelectorAll('option:checked').length;\n function AddSelected(option_el, value, label) {\n if (!option_el) {\n option_el = getDom('<option value=\"' + escape_html(value) + '\">' + escape_html(label) + '</option>');\n }\n // don't move empty option from top of list\n // fixes bug in firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1725293\n if (option_el != empty_option) {\n self.input.append(option_el);\n }\n selected.push(option_el);\n // marking empty option as selected can break validation\n // fixes https://github.com/orchidjs/tom-select/issues/303\n if (option_el != empty_option || has_selected > 0) {\n option_el.selected = true;\n }\n return option_el;\n }\n // unselect all selected options\n self.input.querySelectorAll('option:checked').forEach((option_el) => {\n option_el.selected = false;\n });\n // nothing selected?\n if (self.items.length == 0 && self.settings.mode == 'single') {\n AddSelected(empty_option, \"\", \"\");\n // order selected <option> tags for values in self.items\n }\n else {\n self.items.forEach((value) => {\n option = self.options[value];\n label = option[self.settings.labelField] || '';\n if (selected.includes(option.$option)) {\n const reuse_opt = self.input.querySelector(`option[value=\"${addSlashes(value)}\"]:not(:checked)`);\n AddSelected(reuse_opt, value, label);\n }\n else {\n option.$option = AddSelected(option.$option, value, label);\n }\n });\n }\n }\n else {\n self.input.value = self.getValue();\n }\n if (self.isSetup) {\n if (!opts.silent) {\n self.trigger('change', self.getValue());\n }\n }\n }\n /**\n * Shows the autocomplete dropdown containing\n * the available options.\n */\n open() {\n var self = this;\n if (self.isLocked || self.isOpen || (self.settings.mode === 'multi' && self.isFull()))\n return;\n self.isOpen = true;\n setAttr(self.focus_node, { 'aria-expanded': 'true' });\n self.refreshState();\n applyCSS(self.dropdown, { visibility: 'hidden', display: 'block' });\n self.positionDropdown();\n applyCSS(self.dropdown, { visibility: 'visible', display: 'block' });\n self.focus();\n self.trigger('dropdown_open', self.dropdown);\n }\n /**\n * Closes the autocomplete dropdown menu.\n */\n close(setTextboxValue = true) {\n var self = this;\n var trigger = self.isOpen;\n if (setTextboxValue) {\n // before blur() to prevent form onchange event\n self.setTextboxValue();\n if (self.settings.mode === 'single' && self.items.length) {\n self.inputState();\n }\n }\n self.isOpen = false;\n setAttr(self.focus_node, { 'aria-expanded': 'false' });\n applyCSS(self.dropdown, { display: 'none' });\n if (self.settings.hideSelected) {\n self.clearActiveOption();\n }\n self.refreshState();\n if (trigger)\n self.trigger('dropdown_close', self.dropdown);\n }\n /**\n * Calculates and applies the appropriate\n * position of the dropdown if dropdownParent = 'body'.\n * Otherwise, position is determined by css\n */\n positionDropdown() {\n if (this.settings.dropdownParent !== 'body') {\n return;\n }\n var context = this.control;\n var rect = context.getBoundingClientRect();\n var top = context.offsetHeight + rect.top + window.scrollY;\n var left = rect.left + window.scrollX;\n applyCSS(this.dropdown, {\n width: rect.width + 'px',\n top: top + 'px',\n left: left + 'px'\n });\n }\n /**\n * Resets / clears all selected items\n * from the control.\n *\n */\n clear(silent) {\n var self = this;\n if (!self.items.length)\n return;\n var items = self.controlChildren();\n iterate(items, (item) => {\n self.removeItem(item, true);\n });\n self.inputState();\n if (!silent)\n self.updateOriginalInput();\n self.trigger('clear');\n }\n /**\n * A helper method for inserting an element\n * at the current caret position.\n *\n */\n insertAtCaret(el) {\n const self = this;\n const caret = self.caretPos;\n const target = self.control;\n target.insertBefore(el, target.children[caret] || null);\n self.setCaret(caret + 1);\n }\n /**\n * Removes the current selected item(s).\n *\n */\n deleteSelection(e) {\n var direction, selection, caret, tail;\n var self = this;\n direction = (e && e.keyCode === constants.KEY_BACKSPACE) ? -1 : 1;\n selection = getSelection(self.control_input);\n // determine items that will be removed\n const rm_items = [];\n if (self.activeItems.length) {\n tail = getTail(self.activeItems, direction);\n caret = nodeIndex(tail);\n if (direction > 0) {\n caret++;\n }\n iterate(self.activeItems, (item) => rm_items.push(item));\n }\n else if ((self.isFocused || self.settings.mode === 'single') && self.items.length) {\n const items = self.controlChildren();\n let rm_item;\n if (direction < 0 && selection.start === 0 && selection.length === 0) {\n rm_item = items[self.caretPos - 1];\n }\n else if (direction > 0 && selection.start === self.inputValue().length) {\n rm_item = items[self.caretPos];\n }\n if (rm_item !== undefined) {\n rm_items.push(rm_item);\n }\n }\n if (!self.shouldDelete(rm_items, e)) {\n return false;\n }\n preventDefault(e, true);\n // perform removal\n if (typeof caret !== 'undefined') {\n self.setCaret(caret);\n }\n while (rm_items.length) {\n self.removeItem(rm_items.pop());\n }\n self.inputState();\n self.positionDropdown();\n self.refreshOptions(false);\n return true;\n }\n /**\n * Return true if the items should be deleted\n */\n shouldDelete(items, evt) {\n const values = items.map(item => item.dataset.value);\n // allow the callback to abort\n if (!values.length || (typeof this.settings.onDelete === 'function' && this.settings.onDelete.call(this, values, evt) === false)) {\n return false;\n }\n return true;\n }\n /**\n * Selects the previous / next item (depending on the `direction` argument).\n *\n * > 0 - right\n * < 0 - left\n *\n */\n advanceSelection(direction, e) {\n var last_active, adjacent, self = this;\n if (self.rtl)\n direction *= -1;\n if (self.inputValue().length)\n return;\n // add or remove to active items\n if (isKeyDown(constants.KEY_SHORTCUT, e) || isKeyDown('shiftKey', e)) {\n last_active = self.getLastActive(direction);\n if (last_active) {\n if (!last_active.classList.contains('active')) {\n adjacent = last_active;\n }\n else {\n adjacent = self.getAdjacent(last_active, direction, 'item');\n }\n // if no active item, get items adjacent to the control input\n }\n else if (direction > 0) {\n adjacent = self.control_input.nextElementSibling;\n }\n else {\n adjacent = self.control_input.previousElementSibling;\n }\n if (adjacent) {\n if (adjacent.classList.contains('active')) {\n self.removeActiveItem(last_active);\n }\n self.setActiveItemClass(adjacent); // mark as last_active !! after removeActiveItem() on last_active\n }\n // move caret to the left or right\n }\n else {\n self.moveCaret(direction);\n }\n }\n moveCaret(direction) { }\n /**\n * Get the last active item\n *\n */\n getLastActive(direction) {\n let last_active = this.control.querySelector('.last-active');\n if (last_active) {\n return last_active;\n }\n var result = this.control.querySelectorAll('.active');\n if (result) {\n return getTail(result, direction);\n }\n }\n /**\n * Moves the caret to the specified index.\n *\n * The input must be moved by leaving it in place and moving the\n * siblings, due to the fact that focus cannot be restored once lost\n * on mobile webkit devices\n *\n */\n setCaret(new_pos) {\n this.caretPos = this.items.length;\n }\n /**\n * Return list of item dom elements\n *\n */\n controlChildren() {\n return Array.from(this.control.querySelectorAll('[data-ts-item]'));\n }\n /**\n * Disables user input on the control. Used while\n * items are being asynchronously created.\n */\n lock() {\n this.setLocked(true);\n }\n /**\n * Re-enables user input on the control.\n */\n unlock() {\n this.setLocked(false);\n }\n /**\n * Disable or enable user input on the control\n */\n setLocked(lock = this.isReadOnly || this.isDisabled) {\n this.isLocked = lock;\n this.refreshState();\n }\n /**\n * Disables user input on the control completely.\n * While disabled, it cannot receive focus.\n */\n disable() {\n this.setDisabled(true);\n this.close();\n }\n /**\n * Enables the control so that it can respond\n * to focus and user input.\n */\n enable() {\n this.setDisabled(false);\n }\n setDisabled(disabled) {\n this.focus_node.tabIndex = disabled ? -1 : this.tabIndex;\n this.isDisabled = disabled;\n this.input.disabled = disabled;\n this.control_input.disabled = disabled;\n this.setLocked();\n }\n setReadOnly(isReadOnly) {\n this.isReadOnly = isReadOnly;\n this.input.readOnly = isReadOnly;\n this.control_input.readOnly = isReadOnly;\n this.setLocked();\n }\n /**\n * Completely destroys the control and\n * unbinds all event listeners so that it can\n * be garbage collected.\n */\n destroy() {\n var self = this;\n var revertSettings = self.revertSettings;\n self.trigger('destroy');\n self.off();\n self.wrapper.remove();\n self.dropdown.remove();\n self.input.innerHTML = revertSettings.innerHTML;\n self.input.tabIndex = revertSettings.tabIndex;\n removeClasses(self.input, 'tomselected', 'ts-hidden-accessible');\n self._destroy();\n delete self.input.tomselect;\n }\n /**\n * A helper method for rendering \"item\" and\n * \"option\" templates, given the data.\n *\n */\n render(templateName, data) {\n var id, html;\n const self = this;\n if (typeof this.settings.render[templateName] !== 'function') {\n return null;\n }\n // render markup\n html = self.settings.render[templateName].call(this, data, escape_html);\n if (!html) {\n return null;\n }\n html = getDom(html);\n // add mandatory attributes\n if (templateName === 'option' || templateName === 'option_create') {\n if (data[self.settings.disabledField]) {\n setAttr(html, { 'aria-disabled': 'true' });\n }\n else {\n setAttr(html, { 'data-selectable': '' });\n }\n }\n else if (templateName === 'optgroup') {\n id = data.group[self.settings.optgroupValueField];\n setAttr(html, { 'data-group': id });\n if (data.group[self.settings.disabledField]) {\n setAttr(html, { 'data-disabled': '' });\n }\n }\n if (templateName === 'option' || templateName === 'item') {\n const value = get_hash(data[self.settings.valueField]);\n setAttr(html, { 'data-value': value });\n // make sure we have some classes if a template is overwritten\n if (templateName === 'item') {\n addClasses(html, self.settings.itemClass);\n setAttr(html, { 'data-ts-item': '' });\n }\n else {\n addClasses(html, self.settings.optionClass);\n setAttr(html, {\n role: 'option',\n id: data.$id\n });\n // update cache\n data.$div = html;\n self.options[value] = data;\n }\n }\n return html;\n }\n /**\n * Type guarded rendering\n *\n */\n _render(templateName, data) {\n const html = this.render(templateName, data);\n if (html == null) {\n throw 'HTMLElement expected';\n }\n return html;\n }\n /**\n * Clears the render cache for a template. If\n * no template is given, clears all render\n * caches.\n *\n */\n clearCache() {\n iterate(this.options, (option) => {\n if (option.$div) {\n option.$div.remove();\n delete option.$div;\n }\n });\n }\n /**\n * Removes a value from item and option caches\n *\n */\n uncacheValue(value) {\n const option_el = this.getOption(value);\n if (option_el)\n option_el.remove();\n }\n /**\n * Determines whether or not to display the\n * create item prompt, given a user input.\n *\n */\n canCreate(input) {\n return this.settings.create && (input.length > 0) && this.settings.createFilter.call(this, input);\n }\n /**\n * Wraps this.`method` so that `new_fn` can be invoked 'before', 'after', or 'instead' of the original method\n *\n * this.hook('instead','onKeyDown',function( arg1, arg2 ...){\n *\n * });\n */\n hook(when, method, new_fn) {\n var self = this;\n var orig_method = self[method];\n self[method] = function () {\n var result, result_new;\n if (when === 'after') {\n result = orig_method.apply(self, arguments);\n }\n result_new = new_fn.apply(self, arguments);\n if (when === 'instead') {\n return result_new;\n }\n if (when === 'before') {\n result = orig_method.apply(self, arguments);\n }\n return result;\n };\n }\n}\n;\n//# sourceMappingURL=tom-select.js.map","/**\n * microplugin.js\n * Copyright (c) 2013 Brian Reavis & contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n * @author Brian Reavis <brian@thirdroute.com>\n */\nexport default function MicroPlugin(Interface) {\n Interface.plugins = {};\n return class extends Interface {\n constructor() {\n super(...arguments);\n this.plugins = {\n names: [],\n settings: {},\n requested: {},\n loaded: {}\n };\n }\n /**\n * Registers a plugin.\n *\n * @param {function} fn\n */\n static define(name, fn) {\n Interface.plugins[name] = {\n 'name': name,\n 'fn': fn\n };\n }\n /**\n * Initializes the listed plugins (with options).\n * Acceptable formats:\n *\n * List (without options):\n * ['a', 'b', 'c']\n *\n * List (with options):\n * [{'name': 'a', options: {}}, {'name': 'b', options: {}}]\n *\n * Hash (with options):\n * {'a': { ... }, 'b': { ... }, 'c': { ... }}\n *\n * @param {array|object} plugins\n */\n initializePlugins(plugins) {\n var key, name;\n const self = this;\n const queue = [];\n if (Array.isArray(plugins)) {\n plugins.forEach((plugin) => {\n if (typeof plugin === 'string') {\n queue.push(plugin);\n }\n else {\n self.plugins.settings[plugin.name] = plugin.options;\n queue.push(plugin.name);\n }\n });\n }\n else if (plugins) {\n for (key in plugins) {\n if (plugins.hasOwnProperty(key)) {\n self.plugins.settings[key] = plugins[key];\n queue.push(key);\n }\n }\n }\n while (name = queue.shift()) {\n self.require(name);\n }\n }\n loadPlugin(name) {\n var self = this;\n var plugins = self.plugins;\n var plugin = Interface.plugins[name];\n if (!Interface.plugins.hasOwnProperty(name)) {\n throw new Error('Unable to find \"' + name + '\" plugin');\n }\n plugins.requested[name] = true;\n plugins.loaded[name] = plugin.fn.apply(self, [self.plugins.settings[name] || {}]);\n plugins.names.push(name);\n }\n /**\n * Initializes a plugin.\n *\n */\n require(name) {\n var self = this;\n var plugins = self.plugins;\n if (!self.plugins.loaded.hasOwnProperty(name)) {\n if (plugins.requested[name]) {\n throw new Error('Plugin has circular dependency (\"' + name + '\")');\n }\n self.loadPlugin(name);\n }\n return plugins.loaded[name];\n }\n };\n}\n//# sourceMappingURL=microplugin.js.map","/**\n* Tom Select v2.6.1\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n*/\n\n/**\n * Converts a scalar to its best string representation\n * for hash keys and HTML attribute values.\n *\n * Transformations:\n * 'str' -> 'str'\n * null -> ''\n * undefined -> ''\n * true -> '1'\n * false -> '0'\n * 0 -> '0'\n * 1 -> '1'\n *\n */\nconst hash_key = value => {\n if (typeof value === 'undefined' || value === null) return null;\n return get_hash(value);\n};\nconst get_hash = value => {\n if (typeof value === 'boolean') return value ? '1' : '0';\n return value + '';\n};\n\n/**\n * Prevent default\n *\n */\nconst preventDefault = (evt, stop = false) => {\n if (evt) {\n evt.preventDefault();\n if (stop) {\n evt.stopPropagation();\n }\n }\n};\n\n/**\n * Return a dom element from either a dom query string, jQuery object, a dom element or html string\n * https://stackoverflow.com/questions/494143/creating-a-new-dom-element-from-an-html-string-using-built-in-dom-methods-or-pro/35385518#35385518\n *\n * param query should be {}\n */\nconst getDom = query => {\n if (query.jquery) {\n return query[0];\n }\n if (query instanceof HTMLElement) {\n return query;\n }\n if (isHtmlString(query)) {\n var tpl = document.createElement('template');\n tpl.innerHTML = query.trim(); // Never return a text node of whitespace as the result\n return tpl.content.firstChild;\n }\n return document.querySelector(query);\n};\nconst isHtmlString = arg => {\n if (typeof arg === 'string' && arg.indexOf('<') > -1) {\n return true;\n }\n return false;\n};\n\n/**\n * Plugin: \"checkbox_options\" (Tom Select)\n * Copyright (c) contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n */\n\nfunction plugin (userOptions) {\n var self = this;\n var orig_onOptionSelect = self.onOptionSelect;\n self.settings.hideSelected = false;\n const cbOptions = Object.assign({\n // so that the user may add different ones as well\n className: \"tomselect-checkbox\",\n // the following default to the historic plugin's values\n checkedClassNames: undefined,\n uncheckedClassNames: undefined\n }, userOptions);\n var UpdateChecked = function UpdateChecked(checkbox, toCheck) {\n if (toCheck) {\n checkbox.checked = true;\n if (cbOptions.uncheckedClassNames) {\n checkbox.classList.remove(...cbOptions.uncheckedClassNames);\n }\n if (cbOptions.checkedClassNames) {\n checkbox.classList.add(...cbOptions.checkedClassNames);\n }\n } else {\n checkbox.checked = false;\n if (cbOptions.checkedClassNames) {\n checkbox.classList.remove(...cbOptions.checkedClassNames);\n }\n if (cbOptions.uncheckedClassNames) {\n checkbox.classList.add(...cbOptions.uncheckedClassNames);\n }\n }\n };\n\n // update the checkbox for an option\n var UpdateCheckbox = function UpdateCheckbox(option) {\n setTimeout(() => {\n var checkbox = option.querySelector('input.' + cbOptions.className);\n if (checkbox instanceof HTMLInputElement) {\n UpdateChecked(checkbox, option.classList.contains('selected'));\n }\n }, 1);\n };\n\n // add checkbox to option template\n self.hook('after', 'setupTemplates', () => {\n var orig_render_option = self.settings.render.option;\n self.settings.render.option = (data, escape_html) => {\n var rendered = getDom(orig_render_option.call(self, data, escape_html));\n var checkbox = document.createElement('input');\n if (cbOptions.className) {\n checkbox.classList.add(cbOptions.className);\n }\n checkbox.addEventListener('click', function (evt) {\n preventDefault(evt);\n });\n checkbox.type = 'checkbox';\n const hashed = hash_key(data[self.settings.valueField]);\n UpdateChecked(checkbox, !!(hashed && self.items.indexOf(hashed) > -1));\n rendered.prepend(checkbox);\n return rendered;\n };\n });\n\n // uncheck when item removed\n self.on('item_remove', value => {\n var option = self.getOption(value);\n if (option) {\n // if dropdown hasn't been opened yet, the option won't exist\n option.classList.remove('selected'); // selected class won't be removed yet\n UpdateCheckbox(option);\n }\n });\n\n // check when item added\n self.on('item_add', value => {\n var option = self.getOption(value);\n if (option) {\n // if dropdown hasn't been opened yet, the option won't exist\n UpdateCheckbox(option);\n }\n });\n\n // remove items when selected option is clicked\n self.hook('instead', 'onOptionSelect', (evt, option) => {\n if (option.classList.contains('selected')) {\n option.classList.remove('selected');\n self.removeItem(option.dataset.value);\n self.refreshOptions();\n preventDefault(evt, true);\n return;\n }\n orig_onOptionSelect.call(self, evt, option);\n UpdateCheckbox(option);\n });\n}\n\nexport { plugin as default };\n//# sourceMappingURL=plugin.js.map\n","/**\n* Tom Select v2.6.1\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n*/\n\n/**\n * Return a dom element from either a dom query string, jQuery object, a dom element or html string\n * https://stackoverflow.com/questions/494143/creating-a-new-dom-element-from-an-html-string-using-built-in-dom-methods-or-pro/35385518#35385518\n *\n * param query should be {}\n */\nconst getDom = query => {\n if (query.jquery) {\n return query[0];\n }\n if (query instanceof HTMLElement) {\n return query;\n }\n if (isHtmlString(query)) {\n var tpl = document.createElement('template');\n tpl.innerHTML = query.trim(); // Never return a text node of whitespace as the result\n return tpl.content.firstChild;\n }\n return document.querySelector(query);\n};\nconst isHtmlString = arg => {\n if (typeof arg === 'string' && arg.indexOf('<') > -1) {\n return true;\n }\n return false;\n};\n\n/**\n * Plugin: \"dropdown_header\" (Tom Select)\n * Copyright (c) contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n */\n\nfunction plugin (userOptions) {\n const self = this;\n const options = Object.assign({\n className: 'clear-button',\n title: 'Clear All',\n role: 'button',\n tabindex: 0,\n html: data => {\n return `<div class=\"${data.className}\" title=\"${data.title}\" role=\"${data.role}\" tabindex=\"${data.tabindex}\">&times;</div>`;\n }\n }, userOptions);\n self.on('initialize', () => {\n var button = getDom(options.html(options));\n button.addEventListener('click', evt => {\n if (self.isLocked) return;\n self.clear();\n if (self.settings.mode === 'single' && self.settings.allowEmptyOption) {\n self.addItem('');\n }\n self.refreshOptions(false);\n evt.preventDefault();\n evt.stopPropagation();\n });\n self.control.appendChild(button);\n });\n}\n\nexport { plugin as default };\n//# sourceMappingURL=plugin.js.map\n","/**\n* Tom Select v2.6.1\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n*/\n\n/**\n * Converts a scalar to its best string representation\n * for hash keys and HTML attribute values.\n *\n * Transformations:\n * 'str' -> 'str'\n * null -> ''\n * undefined -> ''\n * true -> '1'\n * false -> '0'\n * 0 -> '0'\n * 1 -> '1'\n *\n */\n\n/**\n * Prevent default\n *\n */\nconst preventDefault = (evt, stop = false) => {\n if (evt) {\n evt.preventDefault();\n if (stop) {\n evt.stopPropagation();\n }\n }\n};\n\n/**\n * Add event helper\n *\n */\nconst addEvent = (target, type, callback, options) => {\n target.addEventListener(type, callback, options);\n};\n\n/**\n * Iterates over arrays and hashes.\n *\n * ```\n * iterate(this.items, function(item, id) {\n * // invoked for each item\n * });\n * ```\n *\n */\nconst iterate = (object, callback) => {\n if (Array.isArray(object)) {\n object.forEach(callback);\n } else {\n for (var key in object) {\n if (object.hasOwnProperty(key)) {\n callback(object[key], key);\n }\n }\n }\n};\n\n/**\n * Return a dom element from either a dom query string, jQuery object, a dom element or html string\n * https://stackoverflow.com/questions/494143/creating-a-new-dom-element-from-an-html-string-using-built-in-dom-methods-or-pro/35385518#35385518\n *\n * param query should be {}\n */\nconst getDom = query => {\n if (query.jquery) {\n return query[0];\n }\n if (query instanceof HTMLElement) {\n return query;\n }\n if (isHtmlString(query)) {\n var tpl = document.createElement('template');\n tpl.innerHTML = query.trim(); // Never return a text node of whitespace as the result\n return tpl.content.firstChild;\n }\n return document.querySelector(query);\n};\nconst isHtmlString = arg => {\n if (typeof arg === 'string' && arg.indexOf('<') > -1) {\n return true;\n }\n return false;\n};\n\n/**\n * Set attributes of an element\n *\n */\nconst setAttr = (el, attrs) => {\n iterate(attrs, (val, attr) => {\n if (val == null) {\n el.removeAttribute(attr);\n } else {\n el.setAttribute(attr, '' + val);\n }\n });\n};\n\n/**\n * Plugin: \"drag_drop\" (Tom Select)\n * Copyright (c) contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n */\n\nconst insertAfter = (referenceNode, newNode) => {\n var _referenceNode$parent;\n (_referenceNode$parent = referenceNode.parentNode) == null || _referenceNode$parent.insertBefore(newNode, referenceNode.nextSibling);\n};\nconst insertBefore = (referenceNode, newNode) => {\n var _referenceNode$parent2;\n (_referenceNode$parent2 = referenceNode.parentNode) == null || _referenceNode$parent2.insertBefore(newNode, referenceNode);\n};\nconst isBefore = (referenceNode, newNode) => {\n do {\n var _newNode;\n newNode = (_newNode = newNode) == null ? void 0 : _newNode.previousElementSibling;\n if (referenceNode == newNode) {\n return true;\n }\n } while (newNode && newNode.previousElementSibling);\n return false;\n};\nfunction plugin () {\n var self = this;\n if (self.settings.mode !== 'multi') return;\n var orig_lock = self.lock;\n var orig_unlock = self.unlock;\n let sortable = true;\n let drag_item;\n\n /**\n * Add draggable attribute to item\n */\n self.hook('after', 'setupTemplates', () => {\n var orig_render_item = self.settings.render.item;\n self.settings.render.item = (data, escape) => {\n const item = getDom(orig_render_item.call(self, data, escape));\n setAttr(item, {\n 'draggable': 'true'\n });\n\n // prevent doc_mousedown (see tom-select.ts)\n const mousedown = evt => {\n if (!sortable) preventDefault(evt);\n evt.stopPropagation();\n };\n const dragStart = evt => {\n drag_item = item;\n setTimeout(() => {\n item.classList.add('ts-dragging');\n }, 0);\n };\n const dragOver = evt => {\n evt.preventDefault();\n item.classList.add('ts-drag-over');\n moveitem(item, drag_item);\n };\n const dragLeave = () => {\n item.classList.remove('ts-drag-over');\n };\n const moveitem = (targetitem, dragitem) => {\n if (dragitem === undefined) return;\n if (isBefore(dragitem, item)) {\n insertAfter(targetitem, dragitem);\n } else {\n insertBefore(targetitem, dragitem);\n }\n };\n const dragend = () => {\n var _drag_item;\n document.querySelectorAll('.ts-drag-over').forEach(el => el.classList.remove('ts-drag-over'));\n (_drag_item = drag_item) == null || _drag_item.classList.remove('ts-dragging');\n drag_item = undefined;\n var values = [];\n self.control.querySelectorAll(`[data-value]`).forEach(el => {\n if (el.dataset.value) {\n let value = el.dataset.value;\n if (value) {\n values.push(value);\n }\n }\n });\n self.setValue(values);\n };\n addEvent(item, 'mousedown', mousedown);\n addEvent(item, 'dragstart', dragStart);\n addEvent(item, 'dragenter', dragOver);\n addEvent(item, 'dragover', dragOver);\n addEvent(item, 'dragleave', dragLeave);\n addEvent(item, 'dragend', dragend);\n return item;\n };\n });\n self.hook('instead', 'lock', () => {\n sortable = false;\n return orig_lock.call(self);\n });\n self.hook('instead', 'unlock', () => {\n sortable = true;\n return orig_unlock.call(self);\n });\n}\n\nexport { plugin as default };\n//# sourceMappingURL=plugin.js.map\n","/**\n* Tom Select v2.6.1\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n*/\n\n/**\n * Converts a scalar to its best string representation\n * for hash keys and HTML attribute values.\n *\n * Transformations:\n * 'str' -> 'str'\n * null -> ''\n * undefined -> ''\n * true -> '1'\n * false -> '0'\n * 0 -> '0'\n * 1 -> '1'\n *\n */\n\n/**\n * Prevent default\n *\n */\nconst preventDefault = (evt, stop = false) => {\n if (evt) {\n evt.preventDefault();\n if (stop) {\n evt.stopPropagation();\n }\n }\n};\n\n/**\n * Return a dom element from either a dom query string, jQuery object, a dom element or html string\n * https://stackoverflow.com/questions/494143/creating-a-new-dom-element-from-an-html-string-using-built-in-dom-methods-or-pro/35385518#35385518\n *\n * param query should be {}\n */\nconst getDom = query => {\n if (query.jquery) {\n return query[0];\n }\n if (query instanceof HTMLElement) {\n return query;\n }\n if (isHtmlString(query)) {\n var tpl = document.createElement('template');\n tpl.innerHTML = query.trim(); // Never return a text node of whitespace as the result\n return tpl.content.firstChild;\n }\n return document.querySelector(query);\n};\nconst isHtmlString = arg => {\n if (typeof arg === 'string' && arg.indexOf('<') > -1) {\n return true;\n }\n return false;\n};\n\n/**\n * Plugin: \"dropdown_header\" (Tom Select)\n * Copyright (c) contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n */\n\nfunction plugin (userOptions) {\n const self = this;\n const options = Object.assign({\n title: 'Untitled',\n headerClass: 'dropdown-header',\n titleRowClass: 'dropdown-header-title',\n labelClass: 'dropdown-header-label',\n closeClass: 'dropdown-header-close',\n html: data => {\n return '<div class=\"' + data.headerClass + '\">' + '<div class=\"' + data.titleRowClass + '\">' + '<span class=\"' + data.labelClass + '\">' + data.title + '</span>' + '<a class=\"' + data.closeClass + '\">&times;</a>' + '</div>' + '</div>';\n }\n }, userOptions);\n self.on('initialize', () => {\n var header = getDom(options.html(options));\n var close_link = header.querySelector('.' + options.closeClass);\n if (close_link) {\n close_link.addEventListener('click', evt => {\n preventDefault(evt, true);\n self.close();\n });\n }\n self.dropdown.insertBefore(header, self.dropdown.firstChild);\n });\n}\n\nexport { plugin as default };\n//# sourceMappingURL=plugin.js.map\n","/**\n* Tom Select v2.6.1\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n*/\n\n/**\n * Converts a scalar to its best string representation\n * for hash keys and HTML attribute values.\n *\n * Transformations:\n * 'str' -> 'str'\n * null -> ''\n * undefined -> ''\n * true -> '1'\n * false -> '0'\n * 0 -> '0'\n * 1 -> '1'\n *\n */\n\n/**\n * Iterates over arrays and hashes.\n *\n * ```\n * iterate(this.items, function(item, id) {\n * // invoked for each item\n * });\n * ```\n *\n */\nconst iterate = (object, callback) => {\n if (Array.isArray(object)) {\n object.forEach(callback);\n } else {\n for (var key in object) {\n if (object.hasOwnProperty(key)) {\n callback(object[key], key);\n }\n }\n }\n};\n\n/**\n * Remove css classes\n *\n */\nconst removeClasses = (elmts, ...classes) => {\n var norm_classes = classesArray(classes);\n elmts = castAsArray(elmts);\n elmts.map(el => {\n norm_classes.map(cls => {\n el.classList.remove(cls);\n });\n });\n};\n\n/**\n * Return arguments\n *\n */\nconst classesArray = args => {\n var classes = [];\n iterate(args, _classes => {\n if (typeof _classes === 'string') {\n _classes = _classes.trim().split(/[\\t\\n\\f\\r\\s]/);\n }\n if (Array.isArray(_classes)) {\n classes = classes.concat(_classes);\n }\n });\n return classes.filter(Boolean);\n};\n\n/**\n * Create an array from arg if it's not already an array\n *\n */\nconst castAsArray = arg => {\n if (!Array.isArray(arg)) {\n arg = [arg];\n }\n return arg;\n};\n\n/**\n * Get the index of an element amongst sibling nodes of the same type\n *\n */\nconst nodeIndex = (el, amongst) => {\n if (!el) return -1;\n amongst = amongst || el.nodeName;\n var i = 0;\n while (el = el.previousElementSibling) {\n if (el.matches(amongst)) {\n i++;\n }\n }\n return i;\n};\n\n/**\n * Plugin: \"dropdown_input\" (Tom Select)\n * Copyright (c) contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n */\n\nfunction plugin () {\n var self = this;\n\n /**\n * Moves the caret to the specified index.\n *\n * The input must be moved by leaving it in place and moving the\n * siblings, due to the fact that focus cannot be restored once lost\n * on mobile webkit devices\n *\n */\n self.hook('instead', 'setCaret', new_pos => {\n if (self.settings.mode === 'single' || !self.control.contains(self.control_input)) {\n new_pos = self.items.length;\n } else {\n new_pos = Math.max(0, Math.min(self.items.length, new_pos));\n if (new_pos != self.caretPos && !self.isPending) {\n self.controlChildren().forEach((child, j) => {\n if (j < new_pos) {\n self.control_input.insertAdjacentElement('beforebegin', child);\n } else {\n self.control.appendChild(child);\n }\n });\n }\n }\n self.caretPos = new_pos;\n });\n self.hook('instead', 'moveCaret', direction => {\n if (!self.isFocused) return;\n\n // move caret before or after selected items\n const last_active = self.getLastActive(direction);\n if (last_active) {\n const idx = nodeIndex(last_active);\n self.setCaret(direction > 0 ? idx + 1 : idx);\n self.setActiveItem();\n removeClasses(last_active, 'last-active');\n\n // move caret left or right of current position\n } else {\n self.setCaret(self.caretPos + direction);\n }\n });\n}\n\nexport { plugin as default };\n//# sourceMappingURL=plugin.js.map\n","/**\n* Tom Select v2.6.1\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n*/\n\nconst KEY_ESC = 27;\nconst KEY_TAB = 9;\n // ctrl key or apple key for ma\n\n/**\n * Converts a scalar to its best string representation\n * for hash keys and HTML attribute values.\n *\n * Transformations:\n * 'str' -> 'str'\n * null -> ''\n * undefined -> ''\n * true -> '1'\n * false -> '0'\n * 0 -> '0'\n * 1 -> '1'\n *\n */\n\n/**\n * Prevent default\n *\n */\nconst preventDefault = (evt, stop = false) => {\n if (evt) {\n evt.preventDefault();\n if (stop) {\n evt.stopPropagation();\n }\n }\n};\n\n/**\n * Add event helper\n *\n */\nconst addEvent = (target, type, callback, options) => {\n target.addEventListener(type, callback, options);\n};\n\n/**\n * Iterates over arrays and hashes.\n *\n * ```\n * iterate(this.items, function(item, id) {\n * // invoked for each item\n * });\n * ```\n *\n */\nconst iterate = (object, callback) => {\n if (Array.isArray(object)) {\n object.forEach(callback);\n } else {\n for (var key in object) {\n if (object.hasOwnProperty(key)) {\n callback(object[key], key);\n }\n }\n }\n};\n\n/**\n * Return a dom element from either a dom query string, jQuery object, a dom element or html string\n * https://stackoverflow.com/questions/494143/creating-a-new-dom-element-from-an-html-string-using-built-in-dom-methods-or-pro/35385518#35385518\n *\n * param query should be {}\n */\nconst getDom = query => {\n if (query.jquery) {\n return query[0];\n }\n if (query instanceof HTMLElement) {\n return query;\n }\n if (isHtmlString(query)) {\n var tpl = document.createElement('template');\n tpl.innerHTML = query.trim(); // Never return a text node of whitespace as the result\n return tpl.content.firstChild;\n }\n return document.querySelector(query);\n};\nconst isHtmlString = arg => {\n if (typeof arg === 'string' && arg.indexOf('<') > -1) {\n return true;\n }\n return false;\n};\n\n/**\n * Add css classes\n *\n */\nconst addClasses = (elmts, ...classes) => {\n var norm_classes = classesArray(classes);\n elmts = castAsArray(elmts);\n elmts.map(el => {\n norm_classes.map(cls => {\n el.classList.add(cls);\n });\n });\n};\n\n/**\n * Return arguments\n *\n */\nconst classesArray = args => {\n var classes = [];\n iterate(args, _classes => {\n if (typeof _classes === 'string') {\n _classes = _classes.trim().split(/[\\t\\n\\f\\r\\s]/);\n }\n if (Array.isArray(_classes)) {\n classes = classes.concat(_classes);\n }\n });\n return classes.filter(Boolean);\n};\n\n/**\n * Create an array from arg if it's not already an array\n *\n */\nconst castAsArray = arg => {\n if (!Array.isArray(arg)) {\n arg = [arg];\n }\n return arg;\n};\n\n/**\n * Plugin: \"dropdown_input\" (Tom Select)\n * Copyright (c) contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n */\n\nfunction plugin () {\n const self = this;\n self.settings.shouldOpen = true; // make sure the input is shown even if there are no options to display in the dropdown\n\n self.hook('before', 'setup', () => {\n var _self$input;\n self.focus_node = self.control;\n addClasses(self.control_input, 'dropdown-input');\n const div = getDom('<div class=\"dropdown-input-wrap\">');\n div.append(self.control_input);\n self.dropdown.insertBefore(div, self.dropdown.firstChild);\n\n // set a placeholder in the select control\n const placeholder = getDom('<input class=\"items-placeholder\" tabindex=\"-1\" />');\n placeholder.placeholder = self.settings.placeholder || '';\n self.control.append(placeholder);\n /**\n * TomSelect renders a custom control with a focusable <input class=\"items-placeholder\">.\n * The source <select>'s aria-label is not automatically propagated to that input,\n * which triggers \"Missing form label\" accessibility warnings.\n * This helper copies the label from the <select> onto the generated input.\n */\n const label = (_self$input = self.input) == null ? void 0 : _self$input.getAttribute('aria-label');\n if (!label) return;\n placeholder.setAttribute('aria-label', label);\n });\n self.on('initialize', () => {\n // set tabIndex on control to -1, otherwise [shift+tab] will put focus right back on control_input\n self.control_input.addEventListener('keydown', evt => {\n //addEvent(self.control_input,'keydown' as const,(evt:KeyboardEvent) =>{\n switch (evt.keyCode) {\n case KEY_ESC:\n if (self.isOpen) {\n preventDefault(evt, true);\n self.close();\n }\n self.clearActiveItems();\n return;\n case KEY_TAB:\n self.focus_node.tabIndex = -1;\n break;\n }\n return self.onKeyDown.call(self, evt);\n });\n self.on('blur', () => {\n self.focus_node.tabIndex = self.isDisabled ? -1 : self.tabIndex;\n });\n\n // give the control_input focus when the dropdown is open\n self.on('dropdown_open', () => {\n self.control_input.focus();\n });\n\n // prevent onBlur from closing when focus is on the control_input\n const orig_onBlur = self.onBlur;\n self.hook('instead', 'onBlur', evt => {\n if (evt && evt.relatedTarget == self.control_input) return;\n return orig_onBlur.call(self);\n });\n addEvent(self.control_input, 'blur', () => self.onBlur());\n\n // return focus to control to allow further keyboard input\n self.hook('before', 'close', () => {\n if (!self.isOpen) return;\n self.focus_node.focus({\n preventScroll: true\n });\n });\n });\n}\n\nexport { plugin as default };\n//# sourceMappingURL=plugin.js.map\n","/**\n* Tom Select v2.6.1\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n*/\n\n/**\n * Converts a scalar to its best string representation\n * for hash keys and HTML attribute values.\n *\n * Transformations:\n * 'str' -> 'str'\n * null -> ''\n * undefined -> ''\n * true -> '1'\n * false -> '0'\n * 0 -> '0'\n * 1 -> '1'\n *\n */\n\n/**\n * Add event helper\n *\n */\nconst addEvent = (target, type, callback, options) => {\n target.addEventListener(type, callback, options);\n};\n\n/**\n * Plugin: \"input_autogrow\" (Tom Select)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n */\n\nfunction plugin () {\n var self = this;\n self.on('initialize', () => {\n var test_input = document.createElement('span');\n var control = self.control_input;\n test_input.style.cssText = 'position:absolute; top:-99999px; left:-99999px; width:auto; padding:0; white-space:pre; ';\n self.wrapper.appendChild(test_input);\n var transfer_styles = ['letterSpacing', 'fontSize', 'fontFamily', 'fontWeight', 'textTransform'];\n for (const style_name of transfer_styles) {\n // @ts-ignore TS7015 https://stackoverflow.com/a/50506154/697576\n test_input.style[style_name] = control.style[style_name];\n }\n\n /**\n * Set the control width\n *\n */\n var resize = () => {\n test_input.textContent = control.value;\n control.style.width = test_input.clientWidth + 'px';\n };\n resize();\n self.on('update item_add item_remove', resize);\n addEvent(control, 'input', resize);\n addEvent(control, 'keyup', resize);\n addEvent(control, 'blur', resize);\n addEvent(control, 'update', resize);\n });\n}\n\nexport { plugin as default };\n//# sourceMappingURL=plugin.js.map\n","/**\n* Tom Select v2.6.1\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n*/\n\n/**\n * Converts a scalar to its best string representation\n * for hash keys and HTML attribute values.\n *\n * Transformations:\n * 'str' -> 'str'\n * null -> ''\n * undefined -> ''\n * true -> '1'\n * false -> '0'\n * 0 -> '0'\n * 1 -> '1'\n *\n */\n\n/**\n * Escapes a string for use within HTML.\n *\n */\nconst escape_html = str => {\n return (str + '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n};\n\n/**\n * Prevent default\n *\n */\nconst preventDefault = (evt, stop = false) => {\n if (evt) {\n evt.preventDefault();\n if (stop) {\n evt.stopPropagation();\n }\n }\n};\n\n/**\n * Add event helper\n *\n */\nconst addEvent = (target, type, callback, options) => {\n target.addEventListener(type, callback, options);\n};\n\n/**\n * Return a dom element from either a dom query string, jQuery object, a dom element or html string\n * https://stackoverflow.com/questions/494143/creating-a-new-dom-element-from-an-html-string-using-built-in-dom-methods-or-pro/35385518#35385518\n *\n * param query should be {}\n */\nconst getDom = query => {\n if (query.jquery) {\n return query[0];\n }\n if (query instanceof HTMLElement) {\n return query;\n }\n if (isHtmlString(query)) {\n var tpl = document.createElement('template');\n tpl.innerHTML = query.trim(); // Never return a text node of whitespace as the result\n return tpl.content.firstChild;\n }\n return document.querySelector(query);\n};\nconst isHtmlString = arg => {\n if (typeof arg === 'string' && arg.indexOf('<') > -1) {\n return true;\n }\n return false;\n};\n\n/**\n * Plugin: \"remove_button\" (Tom Select)\n * Copyright (c) contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n */\n\nfunction plugin (userOptions) {\n const options = Object.assign({\n label: '&times;',\n title: 'Remove',\n className: 'remove',\n append: true\n }, userOptions);\n\n //options.className = 'remove-single';\n var self = this;\n\n // override the render method to add remove button to each item\n if (!options.append) {\n return;\n }\n var html = '<a href=\"javascript:void(0)\" class=\"' + options.className + '\" tabindex=\"-1\" title=\"' + escape_html(options.title) + '\">' + options.label + '</a>';\n self.hook('after', 'setupTemplates', () => {\n var orig_render_item = self.settings.render.item;\n self.settings.render.item = (data, escape) => {\n var item = getDom(orig_render_item.call(self, data, escape));\n var close_button = getDom(html);\n item.appendChild(close_button);\n addEvent(close_button, 'mousedown', evt => {\n preventDefault(evt, true);\n });\n addEvent(close_button, 'click', evt => {\n if (self.isLocked) return;\n\n // propagating will trigger the dropdown to show for single mode\n preventDefault(evt, true);\n if (self.isLocked) return;\n if (!self.shouldDelete([item], evt)) return;\n self.removeItem(item);\n self.refreshOptions(false);\n self.inputState();\n });\n return item;\n };\n });\n}\n\nexport { plugin as default };\n//# sourceMappingURL=plugin.js.map\n","/**\n* Tom Select v2.6.1\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n*/\n\n/**\n * Converts a scalar to its best string representation\n * for hash keys and HTML attribute values.\n *\n * Transformations:\n * 'str' -> 'str'\n * null -> ''\n * undefined -> ''\n * true -> '1'\n * false -> '0'\n * 0 -> '0'\n * 1 -> '1'\n *\n */\n\n/**\n * Iterates over arrays and hashes.\n *\n * ```\n * iterate(this.items, function(item, id) {\n * // invoked for each item\n * });\n * ```\n *\n */\nconst iterate = (object, callback) => {\n if (Array.isArray(object)) {\n object.forEach(callback);\n } else {\n for (var key in object) {\n if (object.hasOwnProperty(key)) {\n callback(object[key], key);\n }\n }\n }\n};\n\n/**\n * Add css classes\n *\n */\nconst addClasses = (elmts, ...classes) => {\n var norm_classes = classesArray(classes);\n elmts = castAsArray(elmts);\n elmts.map(el => {\n norm_classes.map(cls => {\n el.classList.add(cls);\n });\n });\n};\n\n/**\n * Return arguments\n *\n */\nconst classesArray = args => {\n var classes = [];\n iterate(args, _classes => {\n if (typeof _classes === 'string') {\n _classes = _classes.trim().split(/[\\t\\n\\f\\r\\s]/);\n }\n if (Array.isArray(_classes)) {\n classes = classes.concat(_classes);\n }\n });\n return classes.filter(Boolean);\n};\n\n/**\n * Create an array from arg if it's not already an array\n *\n */\nconst castAsArray = arg => {\n if (!Array.isArray(arg)) {\n arg = [arg];\n }\n return arg;\n};\n\n/**\n * Plugin: \"virtual_scroll\" (Tom Select)\n * Copyright (c) contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n */\n\nfunction plugin () {\n const self = this;\n const orig_canLoad = self.canLoad;\n const orig_clearActiveOption = self.clearActiveOption;\n const orig_loadCallback = self.loadCallback;\n var pagination = {};\n var dropdown_content;\n var loading_more = false;\n var load_more_opt;\n var default_values = [];\n var default_values_loaded = false;\n var default_pagination;\n if (!self.settings.shouldLoadMore) {\n // return true if additional results should be loaded\n self.settings.shouldLoadMore = () => {\n const scroll_percent = dropdown_content.clientHeight / (dropdown_content.scrollHeight - dropdown_content.scrollTop);\n if (scroll_percent > 0.9) {\n return true;\n }\n if (self.activeOption) {\n var selectable = self.selectable();\n var index = Array.from(selectable).indexOf(self.activeOption);\n if (index >= selectable.length - 2) {\n return true;\n }\n }\n return false;\n };\n }\n if (!self.settings.firstUrl) {\n throw 'virtual_scroll plugin requires a firstUrl() method';\n }\n\n // in order for virtual scrolling to work,\n // options need to be ordered the same way they're returned from the remote data source\n self.settings.sortField = [{\n field: '$order'\n }, {\n field: '$score'\n }];\n\n // can we load more results for given query?\n const canLoadMore = query => {\n if (typeof self.settings.maxOptions === 'number' && dropdown_content.children.length >= self.settings.maxOptions) {\n return false;\n }\n if (query in pagination && pagination[query]) {\n return true;\n }\n return false;\n };\n const clearFilter = (option, value) => {\n if (self.items.indexOf(value) >= 0 || default_values.indexOf(value) >= 0) {\n return true;\n }\n return false;\n };\n\n // set the next url that will be\n self.setNextUrl = (value, next_url) => {\n pagination[value] = next_url;\n };\n\n // getUrl() to be used in settings.load()\n self.getUrl = query => {\n if (query in pagination) {\n const next_url = pagination[query];\n pagination[query] = false;\n return next_url;\n }\n\n // if the user goes back to a previous query\n // we need to load the first page again\n self.clearPagination();\n return self.settings.firstUrl.call(self, query);\n };\n\n // clear pagination\n self.clearPagination = () => {\n pagination = {};\n };\n\n // don't clear the active option (and cause unwanted dropdown scroll)\n // while loading more results\n self.hook('instead', 'clearActiveOption', () => {\n if (loading_more) {\n return;\n }\n return orig_clearActiveOption.call(self);\n });\n\n // override the canLoad method\n self.hook('instead', 'canLoad', query => {\n // first time the query has been seen\n if (!(query in pagination)) {\n return orig_canLoad.call(self, query);\n }\n return canLoadMore(query);\n });\n\n // wrap the load\n self.hook('instead', 'loadCallback', (options, optgroups) => {\n if (!loading_more) {\n self.clearOptions(clearFilter);\n } else if (load_more_opt) {\n const first_option = options[0];\n if (first_option !== undefined) {\n load_more_opt.dataset.value = first_option[self.settings.valueField];\n }\n }\n orig_loadCallback.call(self, options, optgroups);\n\n // After the initial preload (empty query), update default_values to include\n // preloaded options, not just the HTML <option> elements captured on initialize\n if (!loading_more && !default_values_loaded) {\n default_values_loaded = true;\n if (self.lastValue === '') {\n default_values = Object.keys(self.options);\n default_pagination = pagination[''];\n }\n }\n loading_more = false;\n });\n\n // as the “loading_more” element will be removed from the dropdown,\n // we activate the previous option if needed\n // to avoid the dropdown being scrolled back to the first one\n self.hook('before', 'refreshOptions', () => {\n if (self.activeOption && \"option\" !== self.activeOption.getAttribute(\"role\")) {\n self.setActiveOption(self.activeOption.previousElementSibling);\n }\n });\n\n // add templates to dropdown\n //\tloading_more if we have another url in the queue\n //\tno_more_results if we don't have another url in the queue\n self.hook('after', 'refreshOptions', () => {\n const query = self.lastValue;\n var option;\n if (canLoadMore(query)) {\n option = self.render('loading_more', {\n query: query\n });\n if (option) {\n option.setAttribute('data-selectable', ''); // so that navigating dropdown with [down] keypresses can navigate to this node\n load_more_opt = option;\n }\n } else if (query in pagination && !dropdown_content.querySelector('.no-results')) {\n option = self.render('no_more_results', {\n query: query\n });\n }\n if (option) {\n addClasses(option, self.settings.optionClass);\n dropdown_content.append(option);\n }\n });\n\n // Restore preloaded options and pagination when clearing search\n const restoreDefaults = () => {\n if (!default_values_loaded) {\n return;\n }\n self.clearOptions(clearFilter);\n if (default_pagination) {\n pagination[''] = default_pagination;\n }\n };\n self.on('type', query => {\n if (query === '') {\n restoreDefaults();\n self.refreshOptions(false);\n }\n });\n self.on('dropdown_close', restoreDefaults);\n\n // add scroll listener and default templates\n self.on('initialize', () => {\n default_values = Object.keys(self.options);\n dropdown_content = self.dropdown_content;\n\n // default templates\n self.settings.render = Object.assign({}, {\n loading_more: () => {\n return `<div class=\"loading-more-results\">Loading more results ... </div>`;\n },\n no_more_results: () => {\n return `<div class=\"no-more-results\">No more results</div>`;\n }\n }, self.settings.render);\n\n // watch dropdown content scroll position\n dropdown_content.addEventListener('scroll', () => {\n if (!self.settings.shouldLoadMore.call(self)) {\n return;\n }\n\n // !important: this will get checked again in load() but we still need to check here otherwise loading_more will be set to true\n if (!canLoadMore(self.lastValue)) {\n return;\n }\n\n // don't call load() too much\n if (loading_more) return;\n loading_more = true;\n self.load.call(self, self.lastValue);\n });\n });\n}\n\nexport { plugin as default };\n//# sourceMappingURL=plugin.js.map\n","import TomSelect from \"./tom-select.js\";\nimport change_listener from \"./plugins/change_listener/plugin.js\";\nimport checkbox_options from \"./plugins/checkbox_options/plugin.js\";\nimport clear_button from \"./plugins/clear_button/plugin.js\";\nimport drag_drop from \"./plugins/drag_drop/plugin.js\";\nimport dropdown_header from \"./plugins/dropdown_header/plugin.js\";\nimport caret_position from \"./plugins/caret_position/plugin.js\";\nimport dropdown_input from \"./plugins/dropdown_input/plugin.js\";\nimport input_autogrow from \"./plugins/input_autogrow/plugin.js\";\nimport no_backspace_delete from \"./plugins/no_backspace_delete/plugin.js\";\nimport no_active_items from \"./plugins/no_active_items/plugin.js\";\nimport optgroup_columns from \"./plugins/optgroup_columns/plugin.js\";\nimport remove_button from \"./plugins/remove_button/plugin.js\";\nimport restore_on_backspace from \"./plugins/restore_on_backspace/plugin.js\";\nimport virtual_scroll from \"./plugins/virtual_scroll/plugin.js\";\nTomSelect.define('change_listener', change_listener);\nTomSelect.define('checkbox_options', checkbox_options);\nTomSelect.define('clear_button', clear_button);\nTomSelect.define('drag_drop', drag_drop);\nTomSelect.define('dropdown_header', dropdown_header);\nTomSelect.define('caret_position', caret_position);\nTomSelect.define('dropdown_input', dropdown_input);\nTomSelect.define('input_autogrow', input_autogrow);\nTomSelect.define('no_backspace_delete', no_backspace_delete);\nTomSelect.define('no_active_items', no_active_items);\nTomSelect.define('optgroup_columns', optgroup_columns);\nTomSelect.define('remove_button', remove_button);\nTomSelect.define('restore_on_backspace', restore_on_backspace);\nTomSelect.define('virtual_scroll', virtual_scroll);\nexport default TomSelect;\n//# sourceMappingURL=tom-select.complete.js.map","/**\n* Tom Select v2.6.1\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n*/\n\n/**\n * Converts a scalar to its best string representation\n * for hash keys and HTML attribute values.\n *\n * Transformations:\n * 'str' -> 'str'\n * null -> ''\n * undefined -> ''\n * true -> '1'\n * false -> '0'\n * 0 -> '0'\n * 1 -> '1'\n *\n */\n\n/**\n * Add event helper\n *\n */\nconst addEvent = (target, type, callback, options) => {\n target.addEventListener(type, callback, options);\n};\n\n/**\n * Plugin: \"change_listener\" (Tom Select)\n * Copyright (c) contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n */\n\nfunction plugin () {\n addEvent(this.input, 'change', () => {\n this.sync();\n });\n}\n\nexport { plugin as default };\n//# sourceMappingURL=plugin.js.map\n","/**\n* Tom Select v2.6.1\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n*/\n\n/**\n * Plugin: \"input_autogrow\" (Tom Select)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n */\n\nfunction plugin () {\n var self = this;\n var orig_deleteSelection = self.deleteSelection;\n this.hook('instead', 'deleteSelection', evt => {\n if (self.activeItems.length) {\n return orig_deleteSelection.call(self, evt);\n }\n return false;\n });\n}\n\nexport { plugin as default };\n//# sourceMappingURL=plugin.js.map\n","/**\n* Tom Select v2.6.1\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n*/\n\n/**\n * Plugin: \"no_active_items\" (Tom Select)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n */\n\nfunction plugin () {\n this.hook('instead', 'setActiveItem', () => {});\n this.hook('instead', 'selectAll', () => {});\n}\n\nexport { plugin as default };\n//# sourceMappingURL=plugin.js.map\n","/**\n* Tom Select v2.6.1\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n*/\n\nconst KEY_LEFT = 37;\nconst KEY_RIGHT = 39;\n // ctrl key or apple key for ma\n\n/**\n * Get the closest node to the evt.target matching the selector\n * Stops at wrapper\n *\n */\nconst parentMatch = (target, selector, wrapper) => {\n while (target && target.matches) {\n if (target.matches(selector)) {\n return target;\n }\n target = target.parentNode;\n }\n};\n\n/**\n * Get the index of an element amongst sibling nodes of the same type\n *\n */\nconst nodeIndex = (el, amongst) => {\n if (!el) return -1;\n amongst = amongst || el.nodeName;\n var i = 0;\n while (el = el.previousElementSibling) {\n if (el.matches(amongst)) {\n i++;\n }\n }\n return i;\n};\n\n/**\n * Plugin: \"optgroup_columns\" (Tom Select.js)\n * Copyright (c) contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n */\n\nfunction plugin () {\n var self = this;\n var orig_keydown = self.onKeyDown;\n self.hook('instead', 'onKeyDown', evt => {\n var index, option, options, optgroup;\n if (!self.isOpen || !(evt.keyCode === KEY_LEFT || evt.keyCode === KEY_RIGHT)) {\n return orig_keydown.call(self, evt);\n }\n self.ignoreHover = true;\n optgroup = parentMatch(self.activeOption, '[data-group]');\n index = nodeIndex(self.activeOption, '[data-selectable]');\n if (!optgroup) {\n return;\n }\n if (evt.keyCode === KEY_LEFT) {\n optgroup = optgroup.previousSibling;\n } else {\n optgroup = optgroup.nextSibling;\n }\n if (!optgroup) {\n return;\n }\n options = optgroup.querySelectorAll('[data-selectable]');\n option = options[Math.min(options.length - 1, index)];\n if (option) {\n self.setActiveOption(option);\n }\n });\n}\n\nexport { plugin as default };\n//# sourceMappingURL=plugin.js.map\n","/**\n* Tom Select v2.6.1\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n*/\n\n/**\n * Plugin: \"restore_on_backspace\" (Tom Select)\n * Copyright (c) contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this\n * file except in compliance with the License. You may obtain a copy of the License at:\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n * ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n */\n\nfunction plugin (userOptions) {\n const self = this;\n const options = Object.assign({\n text: option => {\n return option[self.settings.labelField];\n }\n }, userOptions);\n self.on('item_remove', function (value) {\n if (!self.isFocused) {\n return;\n }\n if (self.control_input.value.trim() === '') {\n var option = self.options[value];\n if (option) {\n self.setTextboxValue(options.text.call(self, option));\n }\n }\n });\n}\n\nexport { plugin as default };\n//# sourceMappingURL=plugin.js.map\n","/**\n * Custom positioning reference element.\n * @see https://floating-ui.com/docs/virtual-elements\n */\n\nconst sides = ['top', 'right', 'bottom', 'left'];\nconst alignments = ['start', 'end'];\nconst placements = /*#__PURE__*/sides.reduce((acc, side) => acc.concat(side, side + \"-\" + alignments[0], side + \"-\" + alignments[1]), []);\nconst min = Math.min;\nconst max = Math.max;\nconst round = Math.round;\nconst floor = Math.floor;\nconst createCoords = v => ({\n x: v,\n y: v\n});\nconst oppositeSideMap = {\n left: 'right',\n right: 'left',\n bottom: 'top',\n top: 'bottom'\n};\nfunction clamp(start, value, end) {\n return max(start, min(value, end));\n}\nfunction evaluate(value, param) {\n return typeof value === 'function' ? value(param) : value;\n}\nfunction getSide(placement) {\n return placement.split('-')[0];\n}\nfunction getAlignment(placement) {\n return placement.split('-')[1];\n}\nfunction getOppositeAxis(axis) {\n return axis === 'x' ? 'y' : 'x';\n}\nfunction getAxisLength(axis) {\n return axis === 'y' ? 'height' : 'width';\n}\nfunction getSideAxis(placement) {\n const firstChar = placement[0];\n return firstChar === 't' || firstChar === 'b' ? 'y' : 'x';\n}\nfunction getAlignmentAxis(placement) {\n return getOppositeAxis(getSideAxis(placement));\n}\nfunction getAlignmentSides(placement, rects, rtl) {\n if (rtl === void 0) {\n rtl = false;\n }\n const alignment = getAlignment(placement);\n const alignmentAxis = getAlignmentAxis(placement);\n const length = getAxisLength(alignmentAxis);\n let mainAlignmentSide = alignmentAxis === 'x' ? alignment === (rtl ? 'end' : 'start') ? 'right' : 'left' : alignment === 'start' ? 'bottom' : 'top';\n if (rects.reference[length] > rects.floating[length]) {\n mainAlignmentSide = getOppositePlacement(mainAlignmentSide);\n }\n return [mainAlignmentSide, getOppositePlacement(mainAlignmentSide)];\n}\nfunction getExpandedPlacements(placement) {\n const oppositePlacement = getOppositePlacement(placement);\n return [getOppositeAlignmentPlacement(placement), oppositePlacement, getOppositeAlignmentPlacement(oppositePlacement)];\n}\nfunction getOppositeAlignmentPlacement(placement) {\n return placement.includes('start') ? placement.replace('start', 'end') : placement.replace('end', 'start');\n}\nconst lrPlacement = ['left', 'right'];\nconst rlPlacement = ['right', 'left'];\nconst tbPlacement = ['top', 'bottom'];\nconst btPlacement = ['bottom', 'top'];\nfunction getSideList(side, isStart, rtl) {\n switch (side) {\n case 'top':\n case 'bottom':\n if (rtl) return isStart ? rlPlacement : lrPlacement;\n return isStart ? lrPlacement : rlPlacement;\n case 'left':\n case 'right':\n return isStart ? tbPlacement : btPlacement;\n default:\n return [];\n }\n}\nfunction getOppositeAxisPlacements(placement, flipAlignment, direction, rtl) {\n const alignment = getAlignment(placement);\n let list = getSideList(getSide(placement), direction === 'start', rtl);\n if (alignment) {\n list = list.map(side => side + \"-\" + alignment);\n if (flipAlignment) {\n list = list.concat(list.map(getOppositeAlignmentPlacement));\n }\n }\n return list;\n}\nfunction getOppositePlacement(placement) {\n const side = getSide(placement);\n return oppositeSideMap[side] + placement.slice(side.length);\n}\nfunction expandPaddingObject(padding) {\n return {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0,\n ...padding\n };\n}\nfunction getPaddingObject(padding) {\n return typeof padding !== 'number' ? expandPaddingObject(padding) : {\n top: padding,\n right: padding,\n bottom: padding,\n left: padding\n };\n}\nfunction rectToClientRect(rect) {\n const {\n x,\n y,\n width,\n height\n } = rect;\n return {\n width,\n height,\n top: y,\n left: x,\n right: x + width,\n bottom: y + height,\n x,\n y\n };\n}\n\nexport { alignments, clamp, createCoords, evaluate, expandPaddingObject, floor, getAlignment, getAlignmentAxis, getAlignmentSides, getAxisLength, getExpandedPlacements, getOppositeAlignmentPlacement, getOppositeAxis, getOppositeAxisPlacements, getOppositePlacement, getPaddingObject, getSide, getSideAxis, max, min, placements, rectToClientRect, round, sides };\n","import { getSideAxis, getAlignmentAxis, getAxisLength, getSide, getAlignment, evaluate, getPaddingObject, rectToClientRect, min, clamp, placements, getAlignmentSides, getOppositeAlignmentPlacement, getOppositePlacement, getExpandedPlacements, getOppositeAxisPlacements, sides, max, getOppositeAxis } from '@floating-ui/utils';\nexport { rectToClientRect } from '@floating-ui/utils';\n\nfunction computeCoordsFromPlacement(_ref, placement, rtl) {\n let {\n reference,\n floating\n } = _ref;\n const sideAxis = getSideAxis(placement);\n const alignmentAxis = getAlignmentAxis(placement);\n const alignLength = getAxisLength(alignmentAxis);\n const side = getSide(placement);\n const isVertical = sideAxis === 'y';\n const commonX = reference.x + reference.width / 2 - floating.width / 2;\n const commonY = reference.y + reference.height / 2 - floating.height / 2;\n const commonAlign = reference[alignLength] / 2 - floating[alignLength] / 2;\n let coords;\n switch (side) {\n case 'top':\n coords = {\n x: commonX,\n y: reference.y - floating.height\n };\n break;\n case 'bottom':\n coords = {\n x: commonX,\n y: reference.y + reference.height\n };\n break;\n case 'right':\n coords = {\n x: reference.x + reference.width,\n y: commonY\n };\n break;\n case 'left':\n coords = {\n x: reference.x - floating.width,\n y: commonY\n };\n break;\n default:\n coords = {\n x: reference.x,\n y: reference.y\n };\n }\n switch (getAlignment(placement)) {\n case 'start':\n coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1);\n break;\n case 'end':\n coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1);\n break;\n }\n return coords;\n}\n\n/**\n * Resolves with an object of overflow side offsets that determine how much the\n * element is overflowing a given clipping boundary on each side.\n * - positive = overflowing the boundary by that number of pixels\n * - negative = how many pixels left before it will overflow\n * - 0 = lies flush with the boundary\n * @see https://floating-ui.com/docs/detectOverflow\n */\nasync function detectOverflow(state, options) {\n var _await$platform$isEle;\n if (options === void 0) {\n options = {};\n }\n const {\n x,\n y,\n platform,\n rects,\n elements,\n strategy\n } = state;\n const {\n boundary = 'clippingAncestors',\n rootBoundary = 'viewport',\n elementContext = 'floating',\n altBoundary = false,\n padding = 0\n } = evaluate(options, state);\n const paddingObject = getPaddingObject(padding);\n const altContext = elementContext === 'floating' ? 'reference' : 'floating';\n const element = elements[altBoundary ? altContext : elementContext];\n const clippingClientRect = rectToClientRect(await platform.getClippingRect({\n element: ((_await$platform$isEle = await (platform.isElement == null ? void 0 : platform.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || (await (platform.getDocumentElement == null ? void 0 : platform.getDocumentElement(elements.floating))),\n boundary,\n rootBoundary,\n strategy\n }));\n const rect = elementContext === 'floating' ? {\n x,\n y,\n width: rects.floating.width,\n height: rects.floating.height\n } : rects.reference;\n const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating));\n const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) ? (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {\n x: 1,\n y: 1\n } : {\n x: 1,\n y: 1\n };\n const elementClientRect = rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({\n elements,\n rect,\n offsetParent,\n strategy\n }) : rect);\n return {\n top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y,\n bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y,\n left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x,\n right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x\n };\n}\n\n// Maximum number of resets that can occur before bailing to avoid infinite reset loops.\nconst MAX_RESET_COUNT = 50;\n\n/**\n * Computes the `x` and `y` coordinates that will place the floating element\n * next to a given reference element.\n *\n * This export does not have any `platform` interface logic. You will need to\n * write one for the platform you are using Floating UI with.\n */\nconst computePosition = async (reference, floating, config) => {\n const {\n placement = 'bottom',\n strategy = 'absolute',\n middleware = [],\n platform\n } = config;\n const platformWithDetectOverflow = platform.detectOverflow ? platform : {\n ...platform,\n detectOverflow\n };\n const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(floating));\n let rects = await platform.getElementRects({\n reference,\n floating,\n strategy\n });\n let {\n x,\n y\n } = computeCoordsFromPlacement(rects, placement, rtl);\n let statefulPlacement = placement;\n let resetCount = 0;\n const middlewareData = {};\n for (let i = 0; i < middleware.length; i++) {\n const currentMiddleware = middleware[i];\n if (!currentMiddleware) {\n continue;\n }\n const {\n name,\n fn\n } = currentMiddleware;\n const {\n x: nextX,\n y: nextY,\n data,\n reset\n } = await fn({\n x,\n y,\n initialPlacement: placement,\n placement: statefulPlacement,\n strategy,\n middlewareData,\n rects,\n platform: platformWithDetectOverflow,\n elements: {\n reference,\n floating\n }\n });\n x = nextX != null ? nextX : x;\n y = nextY != null ? nextY : y;\n middlewareData[name] = {\n ...middlewareData[name],\n ...data\n };\n if (reset && resetCount < MAX_RESET_COUNT) {\n resetCount++;\n if (typeof reset === 'object') {\n if (reset.placement) {\n statefulPlacement = reset.placement;\n }\n if (reset.rects) {\n rects = reset.rects === true ? await platform.getElementRects({\n reference,\n floating,\n strategy\n }) : reset.rects;\n }\n ({\n x,\n y\n } = computeCoordsFromPlacement(rects, statefulPlacement, rtl));\n }\n i = -1;\n }\n }\n return {\n x,\n y,\n placement: statefulPlacement,\n strategy,\n middlewareData\n };\n};\n\n/**\n * Provides data to position an inner element of the floating element so that it\n * appears centered to the reference element.\n * @see https://floating-ui.com/docs/arrow\n */\nconst arrow = options => ({\n name: 'arrow',\n options,\n async fn(state) {\n const {\n x,\n y,\n placement,\n rects,\n platform,\n elements,\n middlewareData\n } = state;\n // Since `element` is required, we don't Partial<> the type.\n const {\n element,\n padding = 0\n } = evaluate(options, state) || {};\n if (element == null) {\n return {};\n }\n const paddingObject = getPaddingObject(padding);\n const coords = {\n x,\n y\n };\n const axis = getAlignmentAxis(placement);\n const length = getAxisLength(axis);\n const arrowDimensions = await platform.getDimensions(element);\n const isYAxis = axis === 'y';\n const minProp = isYAxis ? 'top' : 'left';\n const maxProp = isYAxis ? 'bottom' : 'right';\n const clientProp = isYAxis ? 'clientHeight' : 'clientWidth';\n const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length];\n const startDiff = coords[axis] - rects.reference[axis];\n const arrowOffsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(element));\n let clientSize = arrowOffsetParent ? arrowOffsetParent[clientProp] : 0;\n\n // DOM platform can return `window` as the `offsetParent`.\n if (!clientSize || !(await (platform.isElement == null ? void 0 : platform.isElement(arrowOffsetParent)))) {\n clientSize = elements.floating[clientProp] || rects.floating[length];\n }\n const centerToReference = endDiff / 2 - startDiff / 2;\n\n // If the padding is large enough that it causes the arrow to no longer be\n // centered, modify the padding so that it is centered.\n const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1;\n const minPadding = min(paddingObject[minProp], largestPossiblePadding);\n const maxPadding = min(paddingObject[maxProp], largestPossiblePadding);\n\n // Make sure the arrow doesn't overflow the floating element if the center\n // point is outside the floating element's bounds.\n const min$1 = minPadding;\n const max = clientSize - arrowDimensions[length] - maxPadding;\n const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;\n const offset = clamp(min$1, center, max);\n\n // If the reference is small enough that the arrow's padding causes it to\n // to point to nothing for an aligned placement, adjust the offset of the\n // floating element itself. To ensure `shift()` continues to take action,\n // a single reset is performed when this is true.\n const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min$1 ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;\n const alignmentOffset = shouldAddOffset ? center < min$1 ? center - min$1 : center - max : 0;\n return {\n [axis]: coords[axis] + alignmentOffset,\n data: {\n [axis]: offset,\n centerOffset: center - offset - alignmentOffset,\n ...(shouldAddOffset && {\n alignmentOffset\n })\n },\n reset: shouldAddOffset\n };\n }\n});\n\nfunction getPlacementList(alignment, autoAlignment, allowedPlacements) {\n const allowedPlacementsSortedByAlignment = alignment ? [...allowedPlacements.filter(placement => getAlignment(placement) === alignment), ...allowedPlacements.filter(placement => getAlignment(placement) !== alignment)] : allowedPlacements.filter(placement => getSide(placement) === placement);\n return allowedPlacementsSortedByAlignment.filter(placement => {\n if (alignment) {\n return getAlignment(placement) === alignment || (autoAlignment ? getOppositeAlignmentPlacement(placement) !== placement : false);\n }\n return true;\n });\n}\n/**\n * Optimizes the visibility of the floating element by choosing the placement\n * that has the most space available automatically, without needing to specify a\n * preferred placement. Alternative to `flip`.\n * @see https://floating-ui.com/docs/autoPlacement\n */\nconst autoPlacement = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'autoPlacement',\n options,\n async fn(state) {\n var _middlewareData$autoP, _middlewareData$autoP2, _placementsThatFitOnE;\n const {\n rects,\n middlewareData,\n placement,\n platform,\n elements\n } = state;\n const {\n crossAxis = false,\n alignment,\n allowedPlacements = placements,\n autoAlignment = true,\n ...detectOverflowOptions\n } = evaluate(options, state);\n const placements$1 = alignment !== undefined || allowedPlacements === placements ? getPlacementList(alignment || null, autoAlignment, allowedPlacements) : allowedPlacements;\n const overflow = await platform.detectOverflow(state, detectOverflowOptions);\n const currentIndex = ((_middlewareData$autoP = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP.index) || 0;\n const currentPlacement = placements$1[currentIndex];\n if (currentPlacement == null) {\n return {};\n }\n const alignmentSides = getAlignmentSides(currentPlacement, rects, await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)));\n\n // Make `computeCoords` start from the right place.\n if (placement !== currentPlacement) {\n return {\n reset: {\n placement: placements$1[0]\n }\n };\n }\n const currentOverflows = [overflow[getSide(currentPlacement)], overflow[alignmentSides[0]], overflow[alignmentSides[1]]];\n const allOverflows = [...(((_middlewareData$autoP2 = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP2.overflows) || []), {\n placement: currentPlacement,\n overflows: currentOverflows\n }];\n const nextPlacement = placements$1[currentIndex + 1];\n\n // There are more placements to check.\n if (nextPlacement) {\n return {\n data: {\n index: currentIndex + 1,\n overflows: allOverflows\n },\n reset: {\n placement: nextPlacement\n }\n };\n }\n const placementsSortedByMostSpace = allOverflows.map(d => {\n const alignment = getAlignment(d.placement);\n return [d.placement, alignment && crossAxis ?\n // Check along the mainAxis and main crossAxis side.\n d.overflows.slice(0, 2).reduce((acc, v) => acc + v, 0) :\n // Check only the mainAxis.\n d.overflows[0], d.overflows];\n }).sort((a, b) => a[1] - b[1]);\n const placementsThatFitOnEachSide = placementsSortedByMostSpace.filter(d => d[2].slice(0,\n // Aligned placements should not check their opposite crossAxis\n // side.\n getAlignment(d[0]) ? 2 : 3).every(v => v <= 0));\n const resetPlacement = ((_placementsThatFitOnE = placementsThatFitOnEachSide[0]) == null ? void 0 : _placementsThatFitOnE[0]) || placementsSortedByMostSpace[0][0];\n if (resetPlacement !== placement) {\n return {\n data: {\n index: currentIndex + 1,\n overflows: allOverflows\n },\n reset: {\n placement: resetPlacement\n }\n };\n }\n return {};\n }\n };\n};\n\n/**\n * Optimizes the visibility of the floating element by flipping the `placement`\n * in order to keep it in view when the preferred placement(s) will overflow the\n * clipping boundary. Alternative to `autoPlacement`.\n * @see https://floating-ui.com/docs/flip\n */\nconst flip = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'flip',\n options,\n async fn(state) {\n var _middlewareData$arrow, _middlewareData$flip;\n const {\n placement,\n middlewareData,\n rects,\n initialPlacement,\n platform,\n elements\n } = state;\n const {\n mainAxis: checkMainAxis = true,\n crossAxis: checkCrossAxis = true,\n fallbackPlacements: specifiedFallbackPlacements,\n fallbackStrategy = 'bestFit',\n fallbackAxisSideDirection = 'none',\n flipAlignment = true,\n ...detectOverflowOptions\n } = evaluate(options, state);\n\n // If a reset by the arrow was caused due to an alignment offset being\n // added, we should skip any logic now since `flip()` has already done its\n // work.\n // https://github.com/floating-ui/floating-ui/issues/2549#issuecomment-1719601643\n if ((_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {\n return {};\n }\n const side = getSide(placement);\n const initialSideAxis = getSideAxis(initialPlacement);\n const isBasePlacement = getSide(initialPlacement) === initialPlacement;\n const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));\n const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [getOppositePlacement(initialPlacement)] : getExpandedPlacements(initialPlacement));\n const hasFallbackAxisSideDirection = fallbackAxisSideDirection !== 'none';\n if (!specifiedFallbackPlacements && hasFallbackAxisSideDirection) {\n fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl));\n }\n const placements = [initialPlacement, ...fallbackPlacements];\n const overflow = await platform.detectOverflow(state, detectOverflowOptions);\n const overflows = [];\n let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || [];\n if (checkMainAxis) {\n overflows.push(overflow[side]);\n }\n if (checkCrossAxis) {\n const sides = getAlignmentSides(placement, rects, rtl);\n overflows.push(overflow[sides[0]], overflow[sides[1]]);\n }\n overflowsData = [...overflowsData, {\n placement,\n overflows\n }];\n\n // One or more sides is overflowing.\n if (!overflows.every(side => side <= 0)) {\n var _middlewareData$flip2, _overflowsData$filter;\n const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1;\n const nextPlacement = placements[nextIndex];\n if (nextPlacement) {\n const ignoreCrossAxisOverflow = checkCrossAxis === 'alignment' ? initialSideAxis !== getSideAxis(nextPlacement) : false;\n if (!ignoreCrossAxisOverflow ||\n // We leave the current main axis only if every placement on that axis\n // overflows the main axis.\n overflowsData.every(d => getSideAxis(d.placement) === initialSideAxis ? d.overflows[0] > 0 : true)) {\n // Try next placement and re-run the lifecycle.\n return {\n data: {\n index: nextIndex,\n overflows: overflowsData\n },\n reset: {\n placement: nextPlacement\n }\n };\n }\n }\n\n // First, find the candidates that fit on the mainAxis side of overflow,\n // then find the placement that fits the best on the main crossAxis side.\n let resetPlacement = (_overflowsData$filter = overflowsData.filter(d => d.overflows[0] <= 0).sort((a, b) => a.overflows[1] - b.overflows[1])[0]) == null ? void 0 : _overflowsData$filter.placement;\n\n // Otherwise fallback.\n if (!resetPlacement) {\n switch (fallbackStrategy) {\n case 'bestFit':\n {\n var _overflowsData$filter2;\n const placement = (_overflowsData$filter2 = overflowsData.filter(d => {\n if (hasFallbackAxisSideDirection) {\n const currentSideAxis = getSideAxis(d.placement);\n return currentSideAxis === initialSideAxis ||\n // Create a bias to the `y` side axis due to horizontal\n // reading directions favoring greater width.\n currentSideAxis === 'y';\n }\n return true;\n }).map(d => [d.placement, d.overflows.filter(overflow => overflow > 0).reduce((acc, overflow) => acc + overflow, 0)]).sort((a, b) => a[1] - b[1])[0]) == null ? void 0 : _overflowsData$filter2[0];\n if (placement) {\n resetPlacement = placement;\n }\n break;\n }\n case 'initialPlacement':\n resetPlacement = initialPlacement;\n break;\n }\n }\n if (placement !== resetPlacement) {\n return {\n reset: {\n placement: resetPlacement\n }\n };\n }\n }\n return {};\n }\n };\n};\n\nfunction getSideOffsets(overflow, rect) {\n return {\n top: overflow.top - rect.height,\n right: overflow.right - rect.width,\n bottom: overflow.bottom - rect.height,\n left: overflow.left - rect.width\n };\n}\nfunction isAnySideFullyClipped(overflow) {\n return sides.some(side => overflow[side] >= 0);\n}\n/**\n * Provides data to hide the floating element in applicable situations, such as\n * when it is not in the same clipping context as the reference element.\n * @see https://floating-ui.com/docs/hide\n */\nconst hide = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'hide',\n options,\n async fn(state) {\n const {\n rects,\n platform\n } = state;\n const {\n strategy = 'referenceHidden',\n ...detectOverflowOptions\n } = evaluate(options, state);\n switch (strategy) {\n case 'referenceHidden':\n {\n const overflow = await platform.detectOverflow(state, {\n ...detectOverflowOptions,\n elementContext: 'reference'\n });\n const offsets = getSideOffsets(overflow, rects.reference);\n return {\n data: {\n referenceHiddenOffsets: offsets,\n referenceHidden: isAnySideFullyClipped(offsets)\n }\n };\n }\n case 'escaped':\n {\n const overflow = await platform.detectOverflow(state, {\n ...detectOverflowOptions,\n altBoundary: true\n });\n const offsets = getSideOffsets(overflow, rects.floating);\n return {\n data: {\n escapedOffsets: offsets,\n escaped: isAnySideFullyClipped(offsets)\n }\n };\n }\n default:\n {\n return {};\n }\n }\n }\n };\n};\n\nfunction getBoundingRect(rects) {\n const minX = min(...rects.map(rect => rect.left));\n const minY = min(...rects.map(rect => rect.top));\n const maxX = max(...rects.map(rect => rect.right));\n const maxY = max(...rects.map(rect => rect.bottom));\n return {\n x: minX,\n y: minY,\n width: maxX - minX,\n height: maxY - minY\n };\n}\nfunction getRectsByLine(rects) {\n const sortedRects = rects.slice().sort((a, b) => a.y - b.y);\n const groups = [];\n let prevRect = null;\n for (let i = 0; i < sortedRects.length; i++) {\n const rect = sortedRects[i];\n if (!prevRect || rect.y - prevRect.y > prevRect.height / 2) {\n groups.push([rect]);\n } else {\n groups[groups.length - 1].push(rect);\n }\n prevRect = rect;\n }\n return groups.map(rect => rectToClientRect(getBoundingRect(rect)));\n}\n/**\n * Provides improved positioning for inline reference elements that can span\n * over multiple lines, such as hyperlinks or range selections.\n * @see https://floating-ui.com/docs/inline\n */\nconst inline = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'inline',\n options,\n async fn(state) {\n const {\n placement,\n elements,\n rects,\n platform,\n strategy\n } = state;\n // A MouseEvent's client{X,Y} coords can be up to 2 pixels off a\n // ClientRect's bounds, despite the event listener being triggered. A\n // padding of 2 seems to handle this issue.\n const {\n padding = 2,\n x,\n y\n } = evaluate(options, state);\n const nativeClientRects = Array.from((await (platform.getClientRects == null ? void 0 : platform.getClientRects(elements.reference))) || []);\n const clientRects = getRectsByLine(nativeClientRects);\n const fallback = rectToClientRect(getBoundingRect(nativeClientRects));\n const paddingObject = getPaddingObject(padding);\n function getBoundingClientRect() {\n // There are two rects and they are disjoined.\n if (clientRects.length === 2 && clientRects[0].left > clientRects[1].right && x != null && y != null) {\n // Find the first rect in which the point is fully inside.\n return clientRects.find(rect => x > rect.left - paddingObject.left && x < rect.right + paddingObject.right && y > rect.top - paddingObject.top && y < rect.bottom + paddingObject.bottom) || fallback;\n }\n\n // There are 2 or more connected rects.\n if (clientRects.length >= 2) {\n if (getSideAxis(placement) === 'y') {\n const firstRect = clientRects[0];\n const lastRect = clientRects[clientRects.length - 1];\n const isTop = getSide(placement) === 'top';\n const top = firstRect.top;\n const bottom = lastRect.bottom;\n const left = isTop ? firstRect.left : lastRect.left;\n const right = isTop ? firstRect.right : lastRect.right;\n const width = right - left;\n const height = bottom - top;\n return {\n top,\n bottom,\n left,\n right,\n width,\n height,\n x: left,\n y: top\n };\n }\n const isLeftSide = getSide(placement) === 'left';\n const maxRight = max(...clientRects.map(rect => rect.right));\n const minLeft = min(...clientRects.map(rect => rect.left));\n const measureRects = clientRects.filter(rect => isLeftSide ? rect.left === minLeft : rect.right === maxRight);\n const top = measureRects[0].top;\n const bottom = measureRects[measureRects.length - 1].bottom;\n const left = minLeft;\n const right = maxRight;\n const width = right - left;\n const height = bottom - top;\n return {\n top,\n bottom,\n left,\n right,\n width,\n height,\n x: left,\n y: top\n };\n }\n return fallback;\n }\n const resetRects = await platform.getElementRects({\n reference: {\n getBoundingClientRect\n },\n floating: elements.floating,\n strategy\n });\n if (rects.reference.x !== resetRects.reference.x || rects.reference.y !== resetRects.reference.y || rects.reference.width !== resetRects.reference.width || rects.reference.height !== resetRects.reference.height) {\n return {\n reset: {\n rects: resetRects\n }\n };\n }\n return {};\n }\n };\n};\n\nconst originSides = /*#__PURE__*/new Set(['left', 'top']);\n\n// For type backwards-compatibility, the `OffsetOptions` type was also\n// Derivable.\n\nasync function convertValueToCoords(state, options) {\n const {\n placement,\n platform,\n elements\n } = state;\n const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));\n const side = getSide(placement);\n const alignment = getAlignment(placement);\n const isVertical = getSideAxis(placement) === 'y';\n const mainAxisMulti = originSides.has(side) ? -1 : 1;\n const crossAxisMulti = rtl && isVertical ? -1 : 1;\n const rawValue = evaluate(options, state);\n\n // eslint-disable-next-line prefer-const\n let {\n mainAxis,\n crossAxis,\n alignmentAxis\n } = typeof rawValue === 'number' ? {\n mainAxis: rawValue,\n crossAxis: 0,\n alignmentAxis: null\n } : {\n mainAxis: rawValue.mainAxis || 0,\n crossAxis: rawValue.crossAxis || 0,\n alignmentAxis: rawValue.alignmentAxis\n };\n if (alignment && typeof alignmentAxis === 'number') {\n crossAxis = alignment === 'end' ? alignmentAxis * -1 : alignmentAxis;\n }\n return isVertical ? {\n x: crossAxis * crossAxisMulti,\n y: mainAxis * mainAxisMulti\n } : {\n x: mainAxis * mainAxisMulti,\n y: crossAxis * crossAxisMulti\n };\n}\n\n/**\n * Modifies the placement by translating the floating element along the\n * specified axes.\n * A number (shorthand for `mainAxis` or distance), or an axes configuration\n * object may be passed.\n * @see https://floating-ui.com/docs/offset\n */\nconst offset = function (options) {\n if (options === void 0) {\n options = 0;\n }\n return {\n name: 'offset',\n options,\n async fn(state) {\n var _middlewareData$offse, _middlewareData$arrow;\n const {\n x,\n y,\n placement,\n middlewareData\n } = state;\n const diffCoords = await convertValueToCoords(state, options);\n\n // If the placement is the same and the arrow caused an alignment offset\n // then we don't need to change the positioning coordinates.\n if (placement === ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse.placement) && (_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {\n return {};\n }\n return {\n x: x + diffCoords.x,\n y: y + diffCoords.y,\n data: {\n ...diffCoords,\n placement\n }\n };\n }\n };\n};\n\n/**\n * Optimizes the visibility of the floating element by shifting it in order to\n * keep it in view when it will overflow the clipping boundary.\n * @see https://floating-ui.com/docs/shift\n */\nconst shift = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'shift',\n options,\n async fn(state) {\n const {\n x,\n y,\n placement,\n platform\n } = state;\n const {\n mainAxis: checkMainAxis = true,\n crossAxis: checkCrossAxis = false,\n limiter = {\n fn: _ref => {\n let {\n x,\n y\n } = _ref;\n return {\n x,\n y\n };\n }\n },\n ...detectOverflowOptions\n } = evaluate(options, state);\n const coords = {\n x,\n y\n };\n const overflow = await platform.detectOverflow(state, detectOverflowOptions);\n const crossAxis = getSideAxis(getSide(placement));\n const mainAxis = getOppositeAxis(crossAxis);\n let mainAxisCoord = coords[mainAxis];\n let crossAxisCoord = coords[crossAxis];\n if (checkMainAxis) {\n const minSide = mainAxis === 'y' ? 'top' : 'left';\n const maxSide = mainAxis === 'y' ? 'bottom' : 'right';\n const min = mainAxisCoord + overflow[minSide];\n const max = mainAxisCoord - overflow[maxSide];\n mainAxisCoord = clamp(min, mainAxisCoord, max);\n }\n if (checkCrossAxis) {\n const minSide = crossAxis === 'y' ? 'top' : 'left';\n const maxSide = crossAxis === 'y' ? 'bottom' : 'right';\n const min = crossAxisCoord + overflow[minSide];\n const max = crossAxisCoord - overflow[maxSide];\n crossAxisCoord = clamp(min, crossAxisCoord, max);\n }\n const limitedCoords = limiter.fn({\n ...state,\n [mainAxis]: mainAxisCoord,\n [crossAxis]: crossAxisCoord\n });\n return {\n ...limitedCoords,\n data: {\n x: limitedCoords.x - x,\n y: limitedCoords.y - y,\n enabled: {\n [mainAxis]: checkMainAxis,\n [crossAxis]: checkCrossAxis\n }\n }\n };\n }\n };\n};\n/**\n * Built-in `limiter` that will stop `shift()` at a certain point.\n */\nconst limitShift = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n options,\n fn(state) {\n const {\n x,\n y,\n placement,\n rects,\n middlewareData\n } = state;\n const {\n offset = 0,\n mainAxis: checkMainAxis = true,\n crossAxis: checkCrossAxis = true\n } = evaluate(options, state);\n const coords = {\n x,\n y\n };\n const crossAxis = getSideAxis(placement);\n const mainAxis = getOppositeAxis(crossAxis);\n let mainAxisCoord = coords[mainAxis];\n let crossAxisCoord = coords[crossAxis];\n const rawOffset = evaluate(offset, state);\n const computedOffset = typeof rawOffset === 'number' ? {\n mainAxis: rawOffset,\n crossAxis: 0\n } : {\n mainAxis: 0,\n crossAxis: 0,\n ...rawOffset\n };\n if (checkMainAxis) {\n const len = mainAxis === 'y' ? 'height' : 'width';\n const limitMin = rects.reference[mainAxis] - rects.floating[len] + computedOffset.mainAxis;\n const limitMax = rects.reference[mainAxis] + rects.reference[len] - computedOffset.mainAxis;\n if (mainAxisCoord < limitMin) {\n mainAxisCoord = limitMin;\n } else if (mainAxisCoord > limitMax) {\n mainAxisCoord = limitMax;\n }\n }\n if (checkCrossAxis) {\n var _middlewareData$offse, _middlewareData$offse2;\n const len = mainAxis === 'y' ? 'width' : 'height';\n const isOriginSide = originSides.has(getSide(placement));\n const limitMin = rects.reference[crossAxis] - rects.floating[len] + (isOriginSide ? ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse[crossAxis]) || 0 : 0) + (isOriginSide ? 0 : computedOffset.crossAxis);\n const limitMax = rects.reference[crossAxis] + rects.reference[len] + (isOriginSide ? 0 : ((_middlewareData$offse2 = middlewareData.offset) == null ? void 0 : _middlewareData$offse2[crossAxis]) || 0) - (isOriginSide ? computedOffset.crossAxis : 0);\n if (crossAxisCoord < limitMin) {\n crossAxisCoord = limitMin;\n } else if (crossAxisCoord > limitMax) {\n crossAxisCoord = limitMax;\n }\n }\n return {\n [mainAxis]: mainAxisCoord,\n [crossAxis]: crossAxisCoord\n };\n }\n };\n};\n\n/**\n * Provides data that allows you to change the size of the floating element —\n * for instance, prevent it from overflowing the clipping boundary or match the\n * width of the reference element.\n * @see https://floating-ui.com/docs/size\n */\nconst size = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'size',\n options,\n async fn(state) {\n var _state$middlewareData, _state$middlewareData2;\n const {\n placement,\n rects,\n platform,\n elements\n } = state;\n const {\n apply = () => {},\n ...detectOverflowOptions\n } = evaluate(options, state);\n const overflow = await platform.detectOverflow(state, detectOverflowOptions);\n const side = getSide(placement);\n const alignment = getAlignment(placement);\n const isYAxis = getSideAxis(placement) === 'y';\n const {\n width,\n height\n } = rects.floating;\n let heightSide;\n let widthSide;\n if (side === 'top' || side === 'bottom') {\n heightSide = side;\n widthSide = alignment === ((await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating))) ? 'start' : 'end') ? 'left' : 'right';\n } else {\n widthSide = side;\n heightSide = alignment === 'end' ? 'top' : 'bottom';\n }\n const maximumClippingHeight = height - overflow.top - overflow.bottom;\n const maximumClippingWidth = width - overflow.left - overflow.right;\n const overflowAvailableHeight = min(height - overflow[heightSide], maximumClippingHeight);\n const overflowAvailableWidth = min(width - overflow[widthSide], maximumClippingWidth);\n const noShift = !state.middlewareData.shift;\n let availableHeight = overflowAvailableHeight;\n let availableWidth = overflowAvailableWidth;\n if ((_state$middlewareData = state.middlewareData.shift) != null && _state$middlewareData.enabled.x) {\n availableWidth = maximumClippingWidth;\n }\n if ((_state$middlewareData2 = state.middlewareData.shift) != null && _state$middlewareData2.enabled.y) {\n availableHeight = maximumClippingHeight;\n }\n if (noShift && !alignment) {\n const xMin = max(overflow.left, 0);\n const xMax = max(overflow.right, 0);\n const yMin = max(overflow.top, 0);\n const yMax = max(overflow.bottom, 0);\n if (isYAxis) {\n availableWidth = width - 2 * (xMin !== 0 || xMax !== 0 ? xMin + xMax : max(overflow.left, overflow.right));\n } else {\n availableHeight = height - 2 * (yMin !== 0 || yMax !== 0 ? yMin + yMax : max(overflow.top, overflow.bottom));\n }\n }\n await apply({\n ...state,\n availableWidth,\n availableHeight\n });\n const nextDimensions = await platform.getDimensions(elements.floating);\n if (width !== nextDimensions.width || height !== nextDimensions.height) {\n return {\n reset: {\n rects: true\n }\n };\n }\n return {};\n }\n };\n};\n\nexport { arrow, autoPlacement, computePosition, detectOverflow, flip, hide, inline, limitShift, offset, shift, size };\n","function hasWindow() {\n return typeof window !== 'undefined';\n}\nfunction getNodeName(node) {\n if (isNode(node)) {\n return (node.nodeName || '').toLowerCase();\n }\n // Mocked nodes in testing environments may not be instances of Node. By\n // returning `#document` an infinite loop won't occur.\n // https://github.com/floating-ui/floating-ui/issues/2317\n return '#document';\n}\nfunction getWindow(node) {\n var _node$ownerDocument;\n return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;\n}\nfunction getDocumentElement(node) {\n var _ref;\n return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement;\n}\nfunction isNode(value) {\n if (!hasWindow()) {\n return false;\n }\n return value instanceof Node || value instanceof getWindow(value).Node;\n}\nfunction isElement(value) {\n if (!hasWindow()) {\n return false;\n }\n return value instanceof Element || value instanceof getWindow(value).Element;\n}\nfunction isHTMLElement(value) {\n if (!hasWindow()) {\n return false;\n }\n return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement;\n}\nfunction isShadowRoot(value) {\n if (!hasWindow() || typeof ShadowRoot === 'undefined') {\n return false;\n }\n return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot;\n}\nfunction isOverflowElement(element) {\n const {\n overflow,\n overflowX,\n overflowY,\n display\n } = getComputedStyle(element);\n return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && display !== 'inline' && display !== 'contents';\n}\nfunction isTableElement(element) {\n return /^(table|td|th)$/.test(getNodeName(element));\n}\nfunction isTopLayer(element) {\n try {\n if (element.matches(':popover-open')) {\n return true;\n }\n } catch (_e) {\n // no-op\n }\n try {\n return element.matches(':modal');\n } catch (_e) {\n return false;\n }\n}\nconst willChangeRe = /transform|translate|scale|rotate|perspective|filter/;\nconst containRe = /paint|layout|strict|content/;\nconst isNotNone = value => !!value && value !== 'none';\nlet isWebKitValue;\nfunction isContainingBlock(elementOrCss) {\n const css = isElement(elementOrCss) ? getComputedStyle(elementOrCss) : elementOrCss;\n\n // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block\n // https://drafts.csswg.org/css-transforms-2/#individual-transforms\n return isNotNone(css.transform) || isNotNone(css.translate) || isNotNone(css.scale) || isNotNone(css.rotate) || isNotNone(css.perspective) || !isWebKit() && (isNotNone(css.backdropFilter) || isNotNone(css.filter)) || willChangeRe.test(css.willChange || '') || containRe.test(css.contain || '');\n}\nfunction getContainingBlock(element) {\n let currentNode = getParentNode(element);\n while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) {\n if (isContainingBlock(currentNode)) {\n return currentNode;\n } else if (isTopLayer(currentNode)) {\n return null;\n }\n currentNode = getParentNode(currentNode);\n }\n return null;\n}\nfunction isWebKit() {\n if (isWebKitValue == null) {\n isWebKitValue = typeof CSS !== 'undefined' && CSS.supports && CSS.supports('-webkit-backdrop-filter', 'none');\n }\n return isWebKitValue;\n}\nfunction isLastTraversableNode(node) {\n return /^(html|body|#document)$/.test(getNodeName(node));\n}\nfunction getComputedStyle(element) {\n return getWindow(element).getComputedStyle(element);\n}\nfunction getNodeScroll(element) {\n if (isElement(element)) {\n return {\n scrollLeft: element.scrollLeft,\n scrollTop: element.scrollTop\n };\n }\n return {\n scrollLeft: element.scrollX,\n scrollTop: element.scrollY\n };\n}\nfunction getParentNode(node) {\n if (getNodeName(node) === 'html') {\n return node;\n }\n const result =\n // Step into the shadow DOM of the parent of a slotted node.\n node.assignedSlot ||\n // DOM Element detected.\n node.parentNode ||\n // ShadowRoot detected.\n isShadowRoot(node) && node.host ||\n // Fallback.\n getDocumentElement(node);\n return isShadowRoot(result) ? result.host : result;\n}\nfunction getNearestOverflowAncestor(node) {\n const parentNode = getParentNode(node);\n if (isLastTraversableNode(parentNode)) {\n return node.ownerDocument ? node.ownerDocument.body : node.body;\n }\n if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {\n return parentNode;\n }\n return getNearestOverflowAncestor(parentNode);\n}\nfunction getOverflowAncestors(node, list, traverseIframes) {\n var _node$ownerDocument2;\n if (list === void 0) {\n list = [];\n }\n if (traverseIframes === void 0) {\n traverseIframes = true;\n }\n const scrollableAncestor = getNearestOverflowAncestor(node);\n const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body);\n const win = getWindow(scrollableAncestor);\n if (isBody) {\n const frameElement = getFrameElement(win);\n return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], frameElement && traverseIframes ? getOverflowAncestors(frameElement) : []);\n } else {\n return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes));\n }\n}\nfunction getFrameElement(win) {\n return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null;\n}\n\nexport { getComputedStyle, getContainingBlock, getDocumentElement, getFrameElement, getNearestOverflowAncestor, getNodeName, getNodeScroll, getOverflowAncestors, getParentNode, getWindow, isContainingBlock, isElement, isHTMLElement, isLastTraversableNode, isNode, isOverflowElement, isShadowRoot, isTableElement, isTopLayer, isWebKit };\n","import { rectToClientRect, arrow as arrow$1, autoPlacement as autoPlacement$1, detectOverflow as detectOverflow$1, flip as flip$1, hide as hide$1, inline as inline$1, limitShift as limitShift$1, offset as offset$1, shift as shift$1, size as size$1, computePosition as computePosition$1 } from '@floating-ui/core';\nimport { round, createCoords, max, min, floor } from '@floating-ui/utils';\nimport { getComputedStyle as getComputedStyle$1, isHTMLElement, isElement, getWindow, isWebKit, getFrameElement, getNodeScroll, getDocumentElement, isTopLayer, getNodeName, isOverflowElement, getOverflowAncestors, getParentNode, isLastTraversableNode, isContainingBlock, isTableElement, getContainingBlock } from '@floating-ui/utils/dom';\nexport { getOverflowAncestors } from '@floating-ui/utils/dom';\n\nfunction getCssDimensions(element) {\n const css = getComputedStyle$1(element);\n // In testing environments, the `width` and `height` properties are empty\n // strings for SVG elements, returning NaN. Fallback to `0` in this case.\n let width = parseFloat(css.width) || 0;\n let height = parseFloat(css.height) || 0;\n const hasOffset = isHTMLElement(element);\n const offsetWidth = hasOffset ? element.offsetWidth : width;\n const offsetHeight = hasOffset ? element.offsetHeight : height;\n const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight;\n if (shouldFallback) {\n width = offsetWidth;\n height = offsetHeight;\n }\n return {\n width,\n height,\n $: shouldFallback\n };\n}\n\nfunction unwrapElement(element) {\n return !isElement(element) ? element.contextElement : element;\n}\n\nfunction getScale(element) {\n const domElement = unwrapElement(element);\n if (!isHTMLElement(domElement)) {\n return createCoords(1);\n }\n const rect = domElement.getBoundingClientRect();\n const {\n width,\n height,\n $\n } = getCssDimensions(domElement);\n let x = ($ ? round(rect.width) : rect.width) / width;\n let y = ($ ? round(rect.height) : rect.height) / height;\n\n // 0, NaN, or Infinity should always fallback to 1.\n\n if (!x || !Number.isFinite(x)) {\n x = 1;\n }\n if (!y || !Number.isFinite(y)) {\n y = 1;\n }\n return {\n x,\n y\n };\n}\n\nconst noOffsets = /*#__PURE__*/createCoords(0);\nfunction getVisualOffsets(element) {\n const win = getWindow(element);\n if (!isWebKit() || !win.visualViewport) {\n return noOffsets;\n }\n return {\n x: win.visualViewport.offsetLeft,\n y: win.visualViewport.offsetTop\n };\n}\nfunction shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) {\n if (isFixed === void 0) {\n isFixed = false;\n }\n if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow(element)) {\n return false;\n }\n return isFixed;\n}\n\nfunction getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {\n if (includeScale === void 0) {\n includeScale = false;\n }\n if (isFixedStrategy === void 0) {\n isFixedStrategy = false;\n }\n const clientRect = element.getBoundingClientRect();\n const domElement = unwrapElement(element);\n let scale = createCoords(1);\n if (includeScale) {\n if (offsetParent) {\n if (isElement(offsetParent)) {\n scale = getScale(offsetParent);\n }\n } else {\n scale = getScale(element);\n }\n }\n const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0);\n let x = (clientRect.left + visualOffsets.x) / scale.x;\n let y = (clientRect.top + visualOffsets.y) / scale.y;\n let width = clientRect.width / scale.x;\n let height = clientRect.height / scale.y;\n if (domElement) {\n const win = getWindow(domElement);\n const offsetWin = offsetParent && isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;\n let currentWin = win;\n let currentIFrame = getFrameElement(currentWin);\n while (currentIFrame && offsetParent && offsetWin !== currentWin) {\n const iframeScale = getScale(currentIFrame);\n const iframeRect = currentIFrame.getBoundingClientRect();\n const css = getComputedStyle$1(currentIFrame);\n const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x;\n const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y;\n x *= iframeScale.x;\n y *= iframeScale.y;\n width *= iframeScale.x;\n height *= iframeScale.y;\n x += left;\n y += top;\n currentWin = getWindow(currentIFrame);\n currentIFrame = getFrameElement(currentWin);\n }\n }\n return rectToClientRect({\n width,\n height,\n x,\n y\n });\n}\n\n// If <html> has a CSS width greater than the viewport, then this will be\n// incorrect for RTL.\nfunction getWindowScrollBarX(element, rect) {\n const leftScroll = getNodeScroll(element).scrollLeft;\n if (!rect) {\n return getBoundingClientRect(getDocumentElement(element)).left + leftScroll;\n }\n return rect.left + leftScroll;\n}\n\nfunction getHTMLOffset(documentElement, scroll) {\n const htmlRect = documentElement.getBoundingClientRect();\n const x = htmlRect.left + scroll.scrollLeft - getWindowScrollBarX(documentElement, htmlRect);\n const y = htmlRect.top + scroll.scrollTop;\n return {\n x,\n y\n };\n}\n\nfunction convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {\n let {\n elements,\n rect,\n offsetParent,\n strategy\n } = _ref;\n const isFixed = strategy === 'fixed';\n const documentElement = getDocumentElement(offsetParent);\n const topLayer = elements ? isTopLayer(elements.floating) : false;\n if (offsetParent === documentElement || topLayer && isFixed) {\n return rect;\n }\n let scroll = {\n scrollLeft: 0,\n scrollTop: 0\n };\n let scale = createCoords(1);\n const offsets = createCoords(0);\n const isOffsetParentAnElement = isHTMLElement(offsetParent);\n if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {\n if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {\n scroll = getNodeScroll(offsetParent);\n }\n if (isOffsetParentAnElement) {\n const offsetRect = getBoundingClientRect(offsetParent);\n scale = getScale(offsetParent);\n offsets.x = offsetRect.x + offsetParent.clientLeft;\n offsets.y = offsetRect.y + offsetParent.clientTop;\n }\n }\n const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);\n return {\n width: rect.width * scale.x,\n height: rect.height * scale.y,\n x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x + htmlOffset.x,\n y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y + htmlOffset.y\n };\n}\n\nfunction getClientRects(element) {\n return Array.from(element.getClientRects());\n}\n\n// Gets the entire size of the scrollable document area, even extending outside\n// of the `<html>` and `<body>` rect bounds if horizontally scrollable.\nfunction getDocumentRect(element) {\n const html = getDocumentElement(element);\n const scroll = getNodeScroll(element);\n const body = element.ownerDocument.body;\n const width = max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth);\n const height = max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight);\n let x = -scroll.scrollLeft + getWindowScrollBarX(element);\n const y = -scroll.scrollTop;\n if (getComputedStyle$1(body).direction === 'rtl') {\n x += max(html.clientWidth, body.clientWidth) - width;\n }\n return {\n width,\n height,\n x,\n y\n };\n}\n\n// Safety check: ensure the scrollbar space is reasonable in case this\n// calculation is affected by unusual styles.\n// Most scrollbars leave 15-18px of space.\nconst SCROLLBAR_MAX = 25;\nfunction getViewportRect(element, strategy) {\n const win = getWindow(element);\n const html = getDocumentElement(element);\n const visualViewport = win.visualViewport;\n let width = html.clientWidth;\n let height = html.clientHeight;\n let x = 0;\n let y = 0;\n if (visualViewport) {\n width = visualViewport.width;\n height = visualViewport.height;\n const visualViewportBased = isWebKit();\n if (!visualViewportBased || visualViewportBased && strategy === 'fixed') {\n x = visualViewport.offsetLeft;\n y = visualViewport.offsetTop;\n }\n }\n const windowScrollbarX = getWindowScrollBarX(html);\n // <html> `overflow: hidden` + `scrollbar-gutter: stable` reduces the\n // visual width of the <html> but this is not considered in the size\n // of `html.clientWidth`.\n if (windowScrollbarX <= 0) {\n const doc = html.ownerDocument;\n const body = doc.body;\n const bodyStyles = getComputedStyle(body);\n const bodyMarginInline = doc.compatMode === 'CSS1Compat' ? parseFloat(bodyStyles.marginLeft) + parseFloat(bodyStyles.marginRight) || 0 : 0;\n const clippingStableScrollbarWidth = Math.abs(html.clientWidth - body.clientWidth - bodyMarginInline);\n if (clippingStableScrollbarWidth <= SCROLLBAR_MAX) {\n width -= clippingStableScrollbarWidth;\n }\n } else if (windowScrollbarX <= SCROLLBAR_MAX) {\n // If the <body> scrollbar is on the left, the width needs to be extended\n // by the scrollbar amount so there isn't extra space on the right.\n width += windowScrollbarX;\n }\n return {\n width,\n height,\n x,\n y\n };\n}\n\n// Returns the inner client rect, subtracting scrollbars if present.\nfunction getInnerBoundingClientRect(element, strategy) {\n const clientRect = getBoundingClientRect(element, true, strategy === 'fixed');\n const top = clientRect.top + element.clientTop;\n const left = clientRect.left + element.clientLeft;\n const scale = isHTMLElement(element) ? getScale(element) : createCoords(1);\n const width = element.clientWidth * scale.x;\n const height = element.clientHeight * scale.y;\n const x = left * scale.x;\n const y = top * scale.y;\n return {\n width,\n height,\n x,\n y\n };\n}\nfunction getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {\n let rect;\n if (clippingAncestor === 'viewport') {\n rect = getViewportRect(element, strategy);\n } else if (clippingAncestor === 'document') {\n rect = getDocumentRect(getDocumentElement(element));\n } else if (isElement(clippingAncestor)) {\n rect = getInnerBoundingClientRect(clippingAncestor, strategy);\n } else {\n const visualOffsets = getVisualOffsets(element);\n rect = {\n x: clippingAncestor.x - visualOffsets.x,\n y: clippingAncestor.y - visualOffsets.y,\n width: clippingAncestor.width,\n height: clippingAncestor.height\n };\n }\n return rectToClientRect(rect);\n}\nfunction hasFixedPositionAncestor(element, stopNode) {\n const parentNode = getParentNode(element);\n if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) {\n return false;\n }\n return getComputedStyle$1(parentNode).position === 'fixed' || hasFixedPositionAncestor(parentNode, stopNode);\n}\n\n// A \"clipping ancestor\" is an `overflow` element with the characteristic of\n// clipping (or hiding) child elements. This returns all clipping ancestors\n// of the given element up the tree.\nfunction getClippingElementAncestors(element, cache) {\n const cachedResult = cache.get(element);\n if (cachedResult) {\n return cachedResult;\n }\n let result = getOverflowAncestors(element, [], false).filter(el => isElement(el) && getNodeName(el) !== 'body');\n let currentContainingBlockComputedStyle = null;\n const elementIsFixed = getComputedStyle$1(element).position === 'fixed';\n let currentNode = elementIsFixed ? getParentNode(element) : element;\n\n // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block\n while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {\n const computedStyle = getComputedStyle$1(currentNode);\n const currentNodeIsContaining = isContainingBlock(currentNode);\n if (!currentNodeIsContaining && computedStyle.position === 'fixed') {\n currentContainingBlockComputedStyle = null;\n }\n const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === 'static' && !!currentContainingBlockComputedStyle && (currentContainingBlockComputedStyle.position === 'absolute' || currentContainingBlockComputedStyle.position === 'fixed') || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode);\n if (shouldDropCurrentNode) {\n // Drop non-containing blocks.\n result = result.filter(ancestor => ancestor !== currentNode);\n } else {\n // Record last containing block for next iteration.\n currentContainingBlockComputedStyle = computedStyle;\n }\n currentNode = getParentNode(currentNode);\n }\n cache.set(element, result);\n return result;\n}\n\n// Gets the maximum area that the element is visible in due to any number of\n// clipping ancestors.\nfunction getClippingRect(_ref) {\n let {\n element,\n boundary,\n rootBoundary,\n strategy\n } = _ref;\n const elementClippingAncestors = boundary === 'clippingAncestors' ? isTopLayer(element) ? [] : getClippingElementAncestors(element, this._c) : [].concat(boundary);\n const clippingAncestors = [...elementClippingAncestors, rootBoundary];\n const firstRect = getClientRectFromClippingAncestor(element, clippingAncestors[0], strategy);\n let top = firstRect.top;\n let right = firstRect.right;\n let bottom = firstRect.bottom;\n let left = firstRect.left;\n for (let i = 1; i < clippingAncestors.length; i++) {\n const rect = getClientRectFromClippingAncestor(element, clippingAncestors[i], strategy);\n top = max(rect.top, top);\n right = min(rect.right, right);\n bottom = min(rect.bottom, bottom);\n left = max(rect.left, left);\n }\n return {\n width: right - left,\n height: bottom - top,\n x: left,\n y: top\n };\n}\n\nfunction getDimensions(element) {\n const {\n width,\n height\n } = getCssDimensions(element);\n return {\n width,\n height\n };\n}\n\nfunction getRectRelativeToOffsetParent(element, offsetParent, strategy) {\n const isOffsetParentAnElement = isHTMLElement(offsetParent);\n const documentElement = getDocumentElement(offsetParent);\n const isFixed = strategy === 'fixed';\n const rect = getBoundingClientRect(element, true, isFixed, offsetParent);\n let scroll = {\n scrollLeft: 0,\n scrollTop: 0\n };\n const offsets = createCoords(0);\n\n // If the <body> scrollbar appears on the left (e.g. RTL systems). Use\n // Firefox with layout.scrollbar.side = 3 in about:config to test this.\n function setLeftRTLScrollbarOffset() {\n offsets.x = getWindowScrollBarX(documentElement);\n }\n if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {\n if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {\n scroll = getNodeScroll(offsetParent);\n }\n if (isOffsetParentAnElement) {\n const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);\n offsets.x = offsetRect.x + offsetParent.clientLeft;\n offsets.y = offsetRect.y + offsetParent.clientTop;\n } else if (documentElement) {\n setLeftRTLScrollbarOffset();\n }\n }\n if (isFixed && !isOffsetParentAnElement && documentElement) {\n setLeftRTLScrollbarOffset();\n }\n const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);\n const x = rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x;\n const y = rect.top + scroll.scrollTop - offsets.y - htmlOffset.y;\n return {\n x,\n y,\n width: rect.width,\n height: rect.height\n };\n}\n\nfunction isStaticPositioned(element) {\n return getComputedStyle$1(element).position === 'static';\n}\n\nfunction getTrueOffsetParent(element, polyfill) {\n if (!isHTMLElement(element) || getComputedStyle$1(element).position === 'fixed') {\n return null;\n }\n if (polyfill) {\n return polyfill(element);\n }\n let rawOffsetParent = element.offsetParent;\n\n // Firefox returns the <html> element as the offsetParent if it's non-static,\n // while Chrome and Safari return the <body> element. The <body> element must\n // be used to perform the correct calculations even if the <html> element is\n // non-static.\n if (getDocumentElement(element) === rawOffsetParent) {\n rawOffsetParent = rawOffsetParent.ownerDocument.body;\n }\n return rawOffsetParent;\n}\n\n// Gets the closest ancestor positioned element. Handles some edge cases,\n// such as table ancestors and cross browser bugs.\nfunction getOffsetParent(element, polyfill) {\n const win = getWindow(element);\n if (isTopLayer(element)) {\n return win;\n }\n if (!isHTMLElement(element)) {\n let svgOffsetParent = getParentNode(element);\n while (svgOffsetParent && !isLastTraversableNode(svgOffsetParent)) {\n if (isElement(svgOffsetParent) && !isStaticPositioned(svgOffsetParent)) {\n return svgOffsetParent;\n }\n svgOffsetParent = getParentNode(svgOffsetParent);\n }\n return win;\n }\n let offsetParent = getTrueOffsetParent(element, polyfill);\n while (offsetParent && isTableElement(offsetParent) && isStaticPositioned(offsetParent)) {\n offsetParent = getTrueOffsetParent(offsetParent, polyfill);\n }\n if (offsetParent && isLastTraversableNode(offsetParent) && isStaticPositioned(offsetParent) && !isContainingBlock(offsetParent)) {\n return win;\n }\n return offsetParent || getContainingBlock(element) || win;\n}\n\nconst getElementRects = async function (data) {\n const getOffsetParentFn = this.getOffsetParent || getOffsetParent;\n const getDimensionsFn = this.getDimensions;\n const floatingDimensions = await getDimensionsFn(data.floating);\n return {\n reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy),\n floating: {\n x: 0,\n y: 0,\n width: floatingDimensions.width,\n height: floatingDimensions.height\n }\n };\n};\n\nfunction isRTL(element) {\n return getComputedStyle$1(element).direction === 'rtl';\n}\n\nconst platform = {\n convertOffsetParentRelativeRectToViewportRelativeRect,\n getDocumentElement,\n getClippingRect,\n getOffsetParent,\n getElementRects,\n getClientRects,\n getDimensions,\n getScale,\n isElement,\n isRTL\n};\n\nfunction rectsAreEqual(a, b) {\n return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;\n}\n\n// https://samthor.au/2021/observing-dom/\nfunction observeMove(element, onMove) {\n let io = null;\n let timeoutId;\n const root = getDocumentElement(element);\n function cleanup() {\n var _io;\n clearTimeout(timeoutId);\n (_io = io) == null || _io.disconnect();\n io = null;\n }\n function refresh(skip, threshold) {\n if (skip === void 0) {\n skip = false;\n }\n if (threshold === void 0) {\n threshold = 1;\n }\n cleanup();\n const elementRectForRootMargin = element.getBoundingClientRect();\n const {\n left,\n top,\n width,\n height\n } = elementRectForRootMargin;\n if (!skip) {\n onMove();\n }\n if (!width || !height) {\n return;\n }\n const insetTop = floor(top);\n const insetRight = floor(root.clientWidth - (left + width));\n const insetBottom = floor(root.clientHeight - (top + height));\n const insetLeft = floor(left);\n const rootMargin = -insetTop + \"px \" + -insetRight + \"px \" + -insetBottom + \"px \" + -insetLeft + \"px\";\n const options = {\n rootMargin,\n threshold: max(0, min(1, threshold)) || 1\n };\n let isFirstUpdate = true;\n function handleObserve(entries) {\n const ratio = entries[0].intersectionRatio;\n if (ratio !== threshold) {\n if (!isFirstUpdate) {\n return refresh();\n }\n if (!ratio) {\n // If the reference is clipped, the ratio is 0. Throttle the refresh\n // to prevent an infinite loop of updates.\n timeoutId = setTimeout(() => {\n refresh(false, 1e-7);\n }, 1000);\n } else {\n refresh(false, ratio);\n }\n }\n if (ratio === 1 && !rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) {\n // It's possible that even though the ratio is reported as 1, the\n // element is not actually fully within the IntersectionObserver's root\n // area anymore. This can happen under performance constraints. This may\n // be a bug in the browser's IntersectionObserver implementation. To\n // work around this, we compare the element's bounding rect now with\n // what it was at the time we created the IntersectionObserver. If they\n // are not equal then the element moved, so we refresh.\n refresh();\n }\n isFirstUpdate = false;\n }\n\n // Older browsers don't support a `document` as the root and will throw an\n // error.\n try {\n io = new IntersectionObserver(handleObserve, {\n ...options,\n // Handle <iframe>s\n root: root.ownerDocument\n });\n } catch (_e) {\n io = new IntersectionObserver(handleObserve, options);\n }\n io.observe(element);\n }\n refresh(true);\n return cleanup;\n}\n\n/**\n * Automatically updates the position of the floating element when necessary.\n * Should only be called when the floating element is mounted on the DOM or\n * visible on the screen.\n * @returns cleanup function that should be invoked when the floating element is\n * removed from the DOM or hidden from the screen.\n * @see https://floating-ui.com/docs/autoUpdate\n */\nfunction autoUpdate(reference, floating, update, options) {\n if (options === void 0) {\n options = {};\n }\n const {\n ancestorScroll = true,\n ancestorResize = true,\n elementResize = typeof ResizeObserver === 'function',\n layoutShift = typeof IntersectionObserver === 'function',\n animationFrame = false\n } = options;\n const referenceEl = unwrapElement(reference);\n const ancestors = ancestorScroll || ancestorResize ? [...(referenceEl ? getOverflowAncestors(referenceEl) : []), ...(floating ? getOverflowAncestors(floating) : [])] : [];\n ancestors.forEach(ancestor => {\n ancestorScroll && ancestor.addEventListener('scroll', update, {\n passive: true\n });\n ancestorResize && ancestor.addEventListener('resize', update);\n });\n const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update) : null;\n let reobserveFrame = -1;\n let resizeObserver = null;\n if (elementResize) {\n resizeObserver = new ResizeObserver(_ref => {\n let [firstEntry] = _ref;\n if (firstEntry && firstEntry.target === referenceEl && resizeObserver && floating) {\n // Prevent update loops when using the `size` middleware.\n // https://github.com/floating-ui/floating-ui/issues/1740\n resizeObserver.unobserve(floating);\n cancelAnimationFrame(reobserveFrame);\n reobserveFrame = requestAnimationFrame(() => {\n var _resizeObserver;\n (_resizeObserver = resizeObserver) == null || _resizeObserver.observe(floating);\n });\n }\n update();\n });\n if (referenceEl && !animationFrame) {\n resizeObserver.observe(referenceEl);\n }\n if (floating) {\n resizeObserver.observe(floating);\n }\n }\n let frameId;\n let prevRefRect = animationFrame ? getBoundingClientRect(reference) : null;\n if (animationFrame) {\n frameLoop();\n }\n function frameLoop() {\n const nextRefRect = getBoundingClientRect(reference);\n if (prevRefRect && !rectsAreEqual(prevRefRect, nextRefRect)) {\n update();\n }\n prevRefRect = nextRefRect;\n frameId = requestAnimationFrame(frameLoop);\n }\n update();\n return () => {\n var _resizeObserver2;\n ancestors.forEach(ancestor => {\n ancestorScroll && ancestor.removeEventListener('scroll', update);\n ancestorResize && ancestor.removeEventListener('resize', update);\n });\n cleanupIo == null || cleanupIo();\n (_resizeObserver2 = resizeObserver) == null || _resizeObserver2.disconnect();\n resizeObserver = null;\n if (animationFrame) {\n cancelAnimationFrame(frameId);\n }\n };\n}\n\n/**\n * Resolves with an object of overflow side offsets that determine how much the\n * element is overflowing a given clipping boundary on each side.\n * - positive = overflowing the boundary by that number of pixels\n * - negative = how many pixels left before it will overflow\n * - 0 = lies flush with the boundary\n * @see https://floating-ui.com/docs/detectOverflow\n */\nconst detectOverflow = detectOverflow$1;\n\n/**\n * Modifies the placement by translating the floating element along the\n * specified axes.\n * A number (shorthand for `mainAxis` or distance), or an axes configuration\n * object may be passed.\n * @see https://floating-ui.com/docs/offset\n */\nconst offset = offset$1;\n\n/**\n * Optimizes the visibility of the floating element by choosing the placement\n * that has the most space available automatically, without needing to specify a\n * preferred placement. Alternative to `flip`.\n * @see https://floating-ui.com/docs/autoPlacement\n */\nconst autoPlacement = autoPlacement$1;\n\n/**\n * Optimizes the visibility of the floating element by shifting it in order to\n * keep it in view when it will overflow the clipping boundary.\n * @see https://floating-ui.com/docs/shift\n */\nconst shift = shift$1;\n\n/**\n * Optimizes the visibility of the floating element by flipping the `placement`\n * in order to keep it in view when the preferred placement(s) will overflow the\n * clipping boundary. Alternative to `autoPlacement`.\n * @see https://floating-ui.com/docs/flip\n */\nconst flip = flip$1;\n\n/**\n * Provides data that allows you to change the size of the floating element —\n * for instance, prevent it from overflowing the clipping boundary or match the\n * width of the reference element.\n * @see https://floating-ui.com/docs/size\n */\nconst size = size$1;\n\n/**\n * Provides data to hide the floating element in applicable situations, such as\n * when it is not in the same clipping context as the reference element.\n * @see https://floating-ui.com/docs/hide\n */\nconst hide = hide$1;\n\n/**\n * Provides data to position an inner element of the floating element so that it\n * appears centered to the reference element.\n * @see https://floating-ui.com/docs/arrow\n */\nconst arrow = arrow$1;\n\n/**\n * Provides improved positioning for inline reference elements that can span\n * over multiple lines, such as hyperlinks or range selections.\n * @see https://floating-ui.com/docs/inline\n */\nconst inline = inline$1;\n\n/**\n * Built-in `limiter` that will stop `shift()` at a certain point.\n */\nconst limitShift = limitShift$1;\n\n/**\n * Computes the `x` and `y` coordinates that will place the floating element\n * next to a given reference element.\n */\nconst computePosition = (reference, floating, options) => {\n // This caches the expensive `getClippingElementAncestors` function so that\n // multiple lifecycle resets re-use the same result. It only lives for a\n // single call. If other functions become expensive, we can add them as well.\n const cache = new Map();\n const mergedOptions = {\n platform,\n ...options\n };\n const platformWithCache = {\n ...mergedOptions.platform,\n _c: cache\n };\n return computePosition$1(reference, floating, {\n ...mergedOptions,\n platform: platformWithCache\n });\n};\n\nexport { arrow, autoPlacement, autoUpdate, computePosition, detectOverflow, flip, hide, inline, limitShift, offset, platform, shift, size };\n","import TomSelect from \"tom-select\"\nimport { translate } from \"alchemy_admin/i18n\"\nimport {\n autoUpdate,\n computePosition,\n flip,\n offset,\n size\n} from \"@floating-ui/dom\"\n\nconst DROPDOWN_WINDOW_MARGIN = 16\nconst DROPDOWN_MIN_HEIGHT = 120\n\nclass Select extends HTMLSelectElement {\n #tomSelect = null\n\n connectedCallback() {\n this.classList.add(\"alchemy_selectbox\")\n this.#initTomSelect()\n }\n\n disconnectedCallback() {\n this.#destroyTomSelect()\n }\n\n enable() {\n this.removeAttribute(\"disabled\")\n this.#tomSelect?.enable()\n }\n\n disable() {\n this.setAttribute(\"disabled\", \"disabled\")\n this.#tomSelect?.disable()\n }\n\n setOptions(data, prompt = undefined) {\n const selectedValue = this.value\n\n // Tom Select needs to be rebuilt from the new native options, so tear it\n // down, replace the options and initialize it again.\n this.#destroyTomSelect()\n\n // reset the old options and insert the placeholder(s) first\n this.innerHTML = \"\"\n if (prompt) {\n this.add(new Option(prompt, \"\"))\n }\n\n // add the new options to the select\n data.forEach((item) => {\n this.add(new Option(item.text, item.id, false, item.id === selectedValue))\n })\n\n this.#initTomSelect()\n }\n\n get allowClear() {\n return this.dataset.hasOwnProperty(\"allowClear\") || this.multiple\n }\n\n get placeholder() {\n return this.getAttribute(\"placeholder\")\n }\n\n #initTomSelect() {\n const plugins = {}\n const hasPlaceholder = !!this.placeholder\n // Capture this before Tom Select initializes, since it rewrites the\n // select's selected option during setup.\n const hasSelectedOption = !!this.querySelector(\"option[selected]\")\n const dropdownMask = document.createElement(\"div\")\n dropdownMask.className = \"ts-dropdown-mask\"\n\n let removeAutoUpdater = () => {}\n\n if (this.multiple) {\n plugins.remove_button = {\n title: translate(\"Remove\")\n }\n }\n\n if (this.allowClear) {\n plugins.clear_button = {\n html() {\n return `<button type=\"button\" class=\"clear-button\" aria-label=\"${translate(\n \"Clear selection\"\n )}\">\n <alchemy-icon name=\"close\" size=\"1x\"></alchemy-icon>\n </button>`\n }\n }\n }\n\n const settings = {\n plugins,\n closeAfterSelect: !this.multiple,\n onInitialize: function () {\n if (this.input.autofocus) {\n this.focus()\n }\n // Tom Select auto-selects the first option when none is selected. With\n // a placeholder we want it to start empty instead, but only clear when\n // no option was explicitly marked selected, so a preselected value is\n // preserved.\n if (hasPlaceholder && !hasSelectedOption) {\n this.clear()\n }\n },\n onType(term) {\n this.control_input.classList.toggle(\"has-value\", term.length > 0)\n },\n // remove the transition after selection of option.\n refreshThrottle: 0,\n onDropdownOpen: async function () {\n // Make the dropdown at least as wide as the control.\n const styles = {\n minWidth: `${this.control.offsetWidth}px`\n }\n // If the select is inside a dialog, we need to ensure the dropdown appears above it.\n if (this.control.closest(\".alchemy-dialog-body, .alchemy-popover\")) {\n styles.zIndex = \"101\"\n }\n Object.assign(this.dropdown.style, styles)\n // Append the dropdown to the body to avoid overflow issues, especially in dialogs.\n document.body.append(dropdownMask)\n document.body.append(this.dropdown)\n // Use Floating UI to position the dropdown relative to the control.\n const updatePosition = async () => {\n // Use Floating UI to calculate the dropdown position\n const { x, y } = await computePosition(this.control, this.dropdown, {\n middleware: [\n // Flip to the opposite side if there’s not enough space\n flip(),\n // Make some space between the control and the dropdown to prevent overlap\n offset(2),\n // Ensure the dropdown fits within the viewport\n size({\n apply({ availableHeight, elements }) {\n Object.assign(\n elements.floating.querySelector(\".ts-dropdown-content\")\n .style,\n {\n maxHeight: `${Math.max(DROPDOWN_MIN_HEIGHT, availableHeight - DROPDOWN_WINDOW_MARGIN)}px`\n }\n )\n }\n })\n ]\n })\n // Position the dropdown\n Object.assign(this.dropdown.style, {\n left: `${x}px`,\n top: `${y}px`\n })\n }\n // Update the dropdown position whenever the window resizes or scrolls.\n removeAutoUpdater = autoUpdate(\n this.control,\n this.dropdown,\n updatePosition\n )\n },\n onDropdownClose: function () {\n this.control_input.classList.remove(\"has-value\")\n // Remove the dropdown from DOM when closed.\n this.dropdown.remove()\n dropdownMask.remove()\n // Cleanup the position auto-update when the dropdown is closed.\n removeAutoUpdater()\n },\n allowEmptyOption: true,\n openOnFocus: false,\n // Keep options in their original order instead of sorting by value.\n sortField: \"$order\",\n // Show every option, not just the first 50 (e.g. the timezone select).\n maxOptions: null,\n // Customize the \"create\" and \"no results\" dropdown messages with i18n.\n render: {\n option_create(data, escape) {\n return `<div class=\"create\">\n ${translate(\"Add\")}<strong>${escape(data.input)}</strong>&hellip;\n </div>`\n },\n no_results() {\n return `<div class=\"no-results\">${translate(\"No results found\")}</div>`\n }\n }\n }\n\n this.#tomSelect = new TomSelect(this, settings)\n\n // Mimick the native select's click-to-open behavior.\n this.#tomSelect.control.addEventListener(\n \"click\",\n this.#tomSelect.open.bind(this.#tomSelect)\n )\n }\n\n #destroyTomSelect() {\n this.#tomSelect?.destroy()\n this.#tomSelect = null\n }\n}\n\ncustomElements.define(\"alchemy-select\", Select, { extends: \"select\" })\n","import Sortable from \"sortablejs\"\nimport { growl } from \"alchemy_admin/growler\"\nimport { patch } from \"alchemy_admin/utils/ajax\"\nimport { translate } from \"alchemy_admin/i18n\"\nimport pleaseWaitOverlay from \"alchemy_admin/please_wait_overlay\"\n\n/**\n * Custom element for the sitemap container\n * Handles search/filter functionality and drag-and-drop sorting\n */\nexport class AlchemySitemap extends HTMLElement {\n connectedCallback() {\n this.searchInput = document.querySelector(\".search_input_field\")\n this.clearButton = document.querySelector(\"#search_field_clear\")\n this.resultCounter = document.querySelector(\"#page_filter_result\")\n\n this.setupSearch()\n\n // Wait for child custom elements to be defined before setting up sortables\n requestAnimationFrame(() => {\n this.setupSortables()\n })\n\n // Set up MutationObserver to re-initialize sortables when children containers are added\n this.observer = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n mutation.addedNodes.forEach((node) => {\n if (node.nodeType !== Node.ELEMENT_NODE) return\n\n // If the added node itself is a children container, initialize it\n if (node.classList?.contains(\"children\")) {\n this.setupSortable(node)\n }\n\n // Also check for children containers nested within the added node\n // This handles cases where a parent element with nested children is added at once\n node\n .querySelectorAll(\".children\")\n .forEach((el) => this.setupSortable(el))\n })\n })\n })\n\n // Observe the sitemap for added nodes\n this.observer.observe(this, {\n childList: true,\n subtree: true\n })\n }\n\n disconnectedCallback() {\n this.teardownSearch()\n this.observer?.disconnect()\n }\n\n setupSearch() {\n this.searchInput?.addEventListener(\"input\", this)\n this.clearButton?.addEventListener(\"click\", this)\n }\n\n teardownSearch() {\n this.searchInput?.removeEventListener(\"input\", this)\n this.clearButton?.removeEventListener(\"click\", this)\n }\n\n handleEvent(event) {\n if (event.type === \"input\" && event.target === this.searchInput) {\n this.handleSearch(event)\n } else if (event.type === \"click\" && event.target === this.clearButton) {\n this.handleClearSearch(event)\n }\n }\n\n handleSearch(event) {\n const term = event.target.value.toLowerCase().trim()\n\n if (term === \"\") {\n this.clearFilter()\n return\n }\n\n this.filterPages(term)\n }\n\n filterPages(term) {\n const allPages = this.querySelectorAll(\".sitemap_page\")\n let matchCount = 0\n let firstMatch = null\n\n allPages.forEach((pageElement) => {\n const pageName = pageElement.getAttribute(\"name\") || \"\"\n\n if (pageName.toLowerCase().includes(term)) {\n pageElement.classList.add(\"highlight\")\n pageElement.classList.remove(\"no-match\")\n matchCount++\n if (!firstMatch) firstMatch = pageElement\n } else {\n pageElement.classList.remove(\"highlight\")\n pageElement.classList.add(\"no-match\")\n }\n })\n\n // Update result counter\n\n if (matchCount === 1) {\n this.resultCounter.textContent = `1 ${translate(\"page_found\")}`\n this.resultCounter.style.display = \"block\"\n } else if (matchCount > 1) {\n this.resultCounter.textContent = `${matchCount} ${translate(\"pages_found\")}`\n this.resultCounter.style.display = \"block\"\n } else {\n this.resultCounter.style.display = \"none\"\n }\n\n // Scroll first match into view\n if (firstMatch) {\n firstMatch.scrollIntoView({ behavior: \"smooth\", block: \"center\" })\n }\n }\n\n clearFilter() {\n const allPages = this.querySelectorAll(\".sitemap_page\")\n allPages.forEach((pageElement) => {\n pageElement.classList.remove(\"highlight\", \"no-match\")\n })\n\n this.resultCounter.style.display = \"none\"\n }\n\n handleClearSearch(event) {\n event.preventDefault()\n this.searchInput.value = \"\"\n this.clearFilter()\n }\n\n setupSortable(container) {\n new Sortable(container, {\n group: \"pages\",\n animation: 150,\n fallbackOnBody: true,\n swapThreshold: 0.65,\n handle: \".page-icon.handle\",\n draggable: \"alchemy-page-node\",\n onEnd: (evt) => this.handleSort(evt)\n })\n }\n\n setupSortables() {\n const sortables = this.querySelectorAll(\".children\")\n sortables.forEach((el) => this.setupSortable(el))\n }\n\n async handleSort(evt) {\n // Only proceed if actually moved to different position/container\n if (evt.from === evt.to && evt.oldIndex === evt.newIndex) {\n return\n }\n\n // evt.item is the <alchemy-page-node> element being dragged\n const pageNode = evt.item\n const pageId = pageNode.pageId\n const url = Alchemy.routes.move_admin_page_path(pageId)\n const data = {\n target_parent_id: evt.to.dataset.parentId,\n new_position: evt.newIndex\n }\n\n pleaseWaitOverlay(true)\n\n try {\n const response = await patch(url, data)\n const pageData = await response.data\n\n // Update the URL path of the moved page\n const pageEl = pageNode.querySelector(`#page_${pageId}`)\n if (pageEl) {\n const urlPathEl = pageEl.querySelector(\".sitemap_url\")\n if (urlPathEl && pageData.url_path) {\n urlPathEl.textContent = pageData.url_path\n }\n }\n\n // Update folder icons for affected parent pages\n this.updateFolderIcons(evt.from, evt.to)\n\n growl(translate(\"Successfully moved page\"))\n } catch (error) {\n growl(error.message || error, \"error\")\n // Revert the DOM change by reloading on error\n window.location.reload()\n } finally {\n pleaseWaitOverlay(false)\n }\n }\n\n updateFolderIcons(fromContainer, toContainer) {\n // Update folder icon for source parent (might now have no children)\n const fromParent = fromContainer.closest(\"alchemy-page-node\")\n fromParent?.updateFolderButton()\n\n // Update folder icon for destination parent (now definitely has children)\n if (fromContainer !== toContainer) {\n const toParent = toContainer.closest(\"alchemy-page-node\")\n toParent?.updateFolderButton()\n }\n }\n}\n\ncustomElements.define(\"alchemy-sitemap\", AlchemySitemap)\n","import Sortable from \"sortablejs\"\nimport { growl } from \"alchemy_admin/growler\"\nimport { post } from \"alchemy_admin/utils/ajax\"\nimport { reloadPreview } from \"alchemy_admin/components/preview_window\"\nimport { dispatchPageDirtyEvent } from \"alchemy_admin/components/element_editor\"\n\nconst SORTABLE_OPTIONS = {\n draggable: \".element-editor\",\n handle: \".element-handle.draggable\",\n ghostClass: \"dragged\",\n animation: 150,\n swapThreshold: 0.65,\n easing: \"cubic-bezier(1, 0, 0, 1)\"\n}\n\nfunction onStart(event) {\n const name = event.item.dataset.elementName\n document\n .querySelectorAll(`[data-droppable-elements~=\"${name}\"]`)\n .forEach((dropzone) => dropzone.classList.add(\"droppable-elements\"))\n}\n\nfunction onSort(event) {\n const item = event.item\n const parentElement = event.to.parentElement.closest(\".element-editor\")\n const params = {\n element_id: item.dataset.elementId,\n position: event.newIndex + 1\n }\n\n if (parentElement) {\n params.parent_element_id = parentElement.dataset.elementId\n }\n\n // Only send the request if the item was moved to a different container\n // or sorted in the same list. Not on the old list in order to avoid incrementing\n // the position of the other elements.\n if (event.target === event.to) {\n post(Alchemy.routes.order_admin_elements_path, params).then((response) => {\n const data = response.data\n growl(data.message)\n if (data.pageHasUnpublishedChanges) {\n dispatchPageDirtyEvent(data)\n }\n reloadPreview()\n item.updateTitle(data.preview_text)\n })\n }\n}\n\nfunction onEnd() {\n const dropzones = document.querySelectorAll(\"[data-droppable-elements]\")\n dropzones.forEach((dropzone) =>\n dropzone.classList.remove(\"droppable-elements\")\n )\n}\n\nclass SortableElements extends HTMLElement {\n connectedCallback() {\n const group = {\n name: this.dataset.elementName,\n put(to, _from, item) {\n return to.el.dataset.droppableElements\n .split(\" \")\n .includes(item.dataset.elementName)\n }\n }\n new Sortable(this, {\n ...SORTABLE_OPTIONS,\n onStart,\n onSort,\n onEnd,\n group\n })\n }\n}\n\ncustomElements.define(\"alchemy-sortable-elements\", SortableElements)\n","class Spinner extends HTMLElement {\n connectedCallback() {\n this.className = `spinner spinner--${this.size}`\n this.innerHTML = `\n <svg width=\"100%\" viewBox=\"0 0 28 28\" style=\"--spinner-color: ${this.color}\">\n <path\n class=\"hex1\"\n d=\"M5.938,18.07l-5.878-5.9l2.154-8.058l8.024-2.161l5.87,5.9l-2.144,8.058L5.938,18.07z\"\n />\n <path\n class=\"hex2\"\n d=\"M19.686,20.785l-4.731-4.754l1.725-6.487l6.468-1.742l4.733,4.754l-1.734,6.487L19.686,20.785z\"\n />\n <path\n class=\"hex3\"\n d=\"M11.708,26.294l-3.47-3.485l1.276-4.758l4.74-1.276l3.468,3.485l-1.265,4.758L11.708,26.294z\"\n />\n </svg>\n `\n }\n\n get size() {\n return this.getAttribute(\"size\") || \"medium\"\n }\n\n get color() {\n return this.getAttribute(\"color\") || \"currentColor\"\n }\n}\n\ncustomElements.define(\"alchemy-spinner\", Spinner)\n","import { setupSelectLocale } from \"alchemy_admin/i18n\"\n\nclass TagsAutocomplete extends HTMLElement {\n #select2 = null\n\n async connectedCallback() {\n await setupSelectLocale()\n if (!this.isConnected) return\n\n this.classList.add(\"autocomplete_tag_list\")\n this.#select2 = $(this.input).select2(this.select2Config)\n }\n\n disconnectedCallback() {\n this.#select2?.select2(\"destroy\")\n this.#select2 = null\n }\n\n get input() {\n return this.getElementsByTagName(\"input\")[0]\n }\n\n get select2Config() {\n return {\n tags: true,\n tokenSeparators: [\",\"],\n openOnEnter: false,\n minimumInputLength: 1,\n createSearchChoice: this.#createSearchChoice,\n ajax: {\n url: this.getAttribute(\"url\"),\n dataType: \"json\",\n data: (term) => {\n return { term }\n },\n results: (data) => {\n return { results: data }\n }\n },\n initSelection: this.#initSelection\n }\n }\n\n #createSearchChoice(term, data) {\n if (\n $(data).filter(function () {\n return this.text.localeCompare(term) === 0\n }).length === 0\n ) {\n return {\n id: term,\n text: term\n }\n }\n }\n\n #initSelection(element, callback) {\n const data = []\n $(element.val().split(\",\")).each(function () {\n data.push({\n id: this.trim(),\n text: this\n })\n })\n callback(data)\n }\n}\n\ncustomElements.define(\"alchemy-tags-autocomplete\", TagsAutocomplete)\n","import \"tinymce\"\nimport { currentLocale } from \"alchemy_admin/i18n\"\n\nconst DARK_THEME = \"alchemy-dark\"\nconst LIGHT_THEME = \"alchemy\"\n\nclass Tinymce extends HTMLElement {\n #min_height = null\n\n /**\n * the observer will initialize Tinymce if the textarea becomes visible\n */\n connectedCallback() {\n this.className = \"tinymce_container\"\n\n // Append the spinner if not already present (idempotent on reconnect/clone)\n if (!this.querySelector(\":scope > alchemy-spinner\")) {\n this.insertAdjacentHTML(\n \"beforeend\",\n `<alchemy-spinner size=\"small\"></alchemy-spinner>`\n )\n }\n\n // hide the textarea until TinyMCE is ready to show the editor\n this.style.minHeight = `${this.minHeight}px`\n this.editor.style.display = \"none\"\n\n const observerCallback = (entries, observer) => {\n entries.forEach((entry) => {\n if (entry.intersectionRatio > 0) {\n this._initTinymceEditor()\n // disable observer after the Tinymce was initialized\n observer.unobserve(entry.target)\n }\n })\n }\n\n const options = {\n root: document.getElementById(\"element_area\"),\n rootMargin: \"0px\",\n threshold: [0.05]\n }\n\n this.tinymceIntersectionObserver = new IntersectionObserver(\n observerCallback,\n options\n )\n this.tinymceIntersectionObserver.observe(this)\n\n // Set up theme change listener\n this._setupThemeChangeListener()\n }\n\n /**\n * disconnect intersection observer and remove Tinymce editor if the web components get destroyed\n */\n disconnectedCallback() {\n this.tinymceIntersectionObserver?.disconnect()\n\n // Remove theme change listener\n this._removeThemeChangeListener()\n\n tinymce.get(this.editorId)?.remove(this.editorId)\n }\n\n /**\n * initialize Richtext area after the Intersection observer triggered\n * @private\n */\n _initTinymceEditor() {\n tinymce.init(this.configuration).then((editors) => {\n editors.forEach((editor) => this._setupEditor(editor))\n })\n }\n\n /**\n * Setup editor after initialization\n * @param {Object} editor - The TinyMCE editor instance\n * @private\n */\n _setupEditor(editor) {\n // mark the editor container as visible\n // without these correction the editor remains hidden\n // after a drag and drop action\n editor.show()\n\n // remove the spinner after the Tinymce initialized (only on first init)\n const spinner = this.getElementsByTagName(\"alchemy-spinner\")[0]\n if (spinner) {\n spinner.remove()\n }\n\n // event listener to mark the editor as dirty\n if (this.elementEditor) {\n editor.on(\"dirty\", (evt) => {\n this.elementEditor.setDirty(evt.target.editorContainer)\n })\n editor.on(\"click\", () => this.elementEditor.onClickElement(false))\n }\n }\n\n /**\n * Set up listener for OS theme changes\n * @private\n */\n _setupThemeChangeListener() {\n this.darkModeMediaQuery = window.matchMedia(\"(prefers-color-scheme: dark)\")\n this.themeChangeHandler = (event) => this._handleThemeChange(event)\n this.darkModeMediaQuery.addEventListener(\"change\", this.themeChangeHandler)\n }\n\n /**\n * Remove theme change listener\n * @private\n */\n _removeThemeChangeListener() {\n if (this.darkModeMediaQuery && this.themeChangeHandler) {\n this.darkModeMediaQuery.removeEventListener(\n \"change\",\n this.themeChangeHandler\n )\n }\n }\n\n /**\n * Handle OS theme change and update TinyMCE skin\n * @param {MediaQueryListEvent} event - The media query change event\n * @private\n */\n _handleThemeChange(event) {\n const editor = tinymce.get(this.editorId)\n if (editor) {\n const skin = event.matches ? DARK_THEME : LIGHT_THEME\n const content_css = event.matches ? DARK_THEME : LIGHT_THEME\n\n // Update the skin by reinitializing the editor with new configuration\n editor.remove()\n tinymce\n .init({\n content_css,\n ...this.configuration,\n skin\n })\n .then((editors) => {\n editors.forEach((editor) => this._setupEditor(editor))\n })\n }\n }\n\n get configuration() {\n const customConfig = {}\n\n // read the attributes on the component and add them as custom configuration\n this.getAttributeNames().forEach((attributeName) => {\n if (![\"class\", \"id\", \"is\", \"name\", \"style\"].includes(attributeName)) {\n const config = this.getAttribute(attributeName)\n const key = attributeName.replaceAll(\"-\", \"_\")\n\n // Handle boolean HTML attributes (e.g., readonly=\"readonly\" or readonly=\"\")\n if (config === attributeName || config === \"\") {\n customConfig[key] = true\n } else {\n try {\n customConfig[key] = JSON.parse(config)\n } catch (e) {\n // also string values as parameter\n customConfig[key] = config\n }\n }\n }\n })\n\n const config = {\n content_css: this.preferredTheme,\n ...Alchemy.TinymceDefaults,\n ...customConfig,\n language: currentLocale(),\n selector: `#${this.editorId}`,\n skin: this.preferredTheme\n }\n\n // Tinymce has a height of 400px by default\n // if the element has a min_height set, we use this value for the height as well\n // so we do not need to set both values in the element configuration\n config.height = config.min_height\n\n return config\n }\n\n get preferredTheme() {\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n ? DARK_THEME\n : LIGHT_THEME\n }\n\n get editorId() {\n return this.editor.id\n }\n\n get editor() {\n return this.getElementsByTagName(\"textarea\")[0]\n }\n\n get elementEditor() {\n return document\n .getElementById(this.editorId)\n .closest(\"alchemy-element-editor\")\n }\n\n get minHeight() {\n return this.#min_height || this.configuration.min_height\n }\n\n set minHeight(value) {\n this.#min_height = value\n }\n}\n\ncustomElements.define(\"alchemy-tinymce\", Tinymce)\n","import Spinner from \"alchemy_admin/spinner\"\n\nclass UpdateCheck extends HTMLElement {\n async connectedCallback() {\n const spinner = new Spinner(\"small\")\n spinner.spin(this)\n\n try {\n const response = await fetch(this.url, { credentials: \"include\" })\n const responseJSON = await response.json()\n\n if (response.ok) {\n this.showStatus(responseJSON)\n } else {\n this.showError(response)\n }\n } catch (error) {\n this.showError(error)\n } finally {\n spinner.stop()\n }\n }\n\n get url() {\n return this.getAttribute(\"url\")\n }\n\n showStatus(responseJSON) {\n if (responseJSON[\"status\"] == \"true\") {\n this.querySelector(\".update_available\").classList.remove(\"hidden\")\n } else {\n this.querySelector(\".up_to_date\").classList.remove(\"hidden\")\n }\n }\n\n showError(error) {\n this.querySelector(\".error\").classList.remove(\"hidden\")\n console.error(\"[alchemy] Error fetching update status\", error)\n }\n}\n\ncustomElements.define(\"alchemy-update-check\", UpdateCheck)\n","(()=>{var n=Handlebars.template;(Handlebars.templates=Handlebars.templates||{})[\"node_folder.hbs\"]=n({0:function(n,e,l,a,r){return\"right\"},1:function(n,e,l,a,r){return\"down\"},compiler:[8,\">= 4.3.0\"],main:function(n,e,l,a,r){var o,t=n.lambda,d=n.escapeExpression,u=n.lookupProperty||function(n,e){if(Object.prototype.hasOwnProperty.call(n,e))return n[e]};return'<a class=\"node_folder\" data-record-id=\"'+d(t(null!=(o=null!=e?u(e,\"node\"):e)?u(o,\"id\"):o,e))+'\" data-record-type=\"'+d(t(null!=(o=null!=e?u(e,\"node\"):e)?u(o,\"type\"):o,e))+'\">\\n <alchemy-icon name=\"arrow-'+(null!=(o=u(l,\"if\").call(null!=e?e:n.nullContext||{},null!=(o=null!=e?u(e,\"node\"):e)?u(o,\"folded\"):o,{name:\"if\",hash:{},fn:n.program(0,r,0),inverse:n.program(1,r,0),data:r,loc:{start:{line:2,column:28},end:{line:2,column:72}}}))?o:\"\")+'-s\"></alchemy-icon>\\n</a>\\n'},useData:!0})})();","import { registerIconLibrary, setDefaultAnimation } from \"shoelace\"\n\n// Change the default animation for all tooltips\nsetDefaultAnimation(\"tooltip.show\", {\n keyframes: [\n { transform: \"translateY(10px)\", opacity: \"0\" },\n { transform: \"translateY(0)\", opacity: \"1\" }\n ],\n options: {\n duration: 100\n }\n})\n\nsetDefaultAnimation(\"tooltip.hide\", {\n keyframes: [\n { transform: \"translateY(0)\", opacity: \"1\" },\n { transform: \"translateY(10px)\", opacity: \"0\" }\n ],\n options: {\n duration: 100\n }\n})\n\n// Change the default animation for all dialogs\nsetDefaultAnimation(\"dialog.show\", {\n keyframes: [\n { transform: \"scale(0.98)\", opacity: \"0\" },\n { transform: \"scale(1)\", opacity: \"1\" }\n ],\n options: {\n duration: 150\n }\n})\n\nsetDefaultAnimation(\"dialog.hide\", {\n keyframes: [\n { transform: \"scale(1)\", opacity: \"1\" },\n { transform: \"scale(0.98)\", opacity: \"0\" }\n ],\n options: {\n duration: 150\n }\n})\n\nconst spriteUrl = document\n .querySelector('link[rel=\"preload\"][as=\"image\"]')\n .getAttribute(\"href\")\n\nconst iconMap = {\n \"x-lg\": \"close\",\n caret: \"arrow-down-s\"\n}\n\nconst options = {\n resolver: (name) => `${spriteUrl}#ri-${iconMap[name] || name}-line`,\n mutator: (svg) => {\n svg.setAttribute(\"fill\", \"currentColor\")\n svg.setAttribute(\"viewBox\", \"0 0 24 24\")\n },\n spriteSheet: true\n}\n\nregisterIconLibrary(\"default\", options)\nregisterIconLibrary(\"system\", options)\n","export function on(eventName, baseSelector, targetSelector, callback) {\n document.querySelectorAll(baseSelector).forEach((baseNode) => {\n baseNode.addEventListener(eventName, (evt) => {\n const targets = Array.from(baseNode.querySelectorAll(targetSelector))\n let currentNode = evt.target\n\n while (currentNode !== baseNode) {\n if (targets.includes(currentNode)) {\n callback.call(currentNode, evt)\n return\n }\n currentNode = currentNode.parentElement\n }\n })\n })\n}\n","import Cropper from \"cropperjs\"\n\nexport default class ImageCropper {\n #initialized = false\n #cropper = null\n #cropFromField = null\n #cropSizeField = null\n\n constructor(image, settings) {\n this.image = image\n this.defaultBox = settings.default_box\n this.aspectRatio = settings.ratio\n this.#cropFromField = document.getElementById(\n settings.crop_from_form_field_id\n )\n this.#cropSizeField = document.getElementById(\n settings.crop_size_form_field_id\n )\n this.elementId = settings.element_id\n this.elementEditor = document.querySelector(\n `[data-element-id='${this.elementId}']`\n )\n this.dialog = Alchemy.currentDialog()\n if (this.dialog) {\n this.dialog.options.closed = () => this.destroy()\n this.bind()\n }\n this.init()\n }\n\n get cropperOptions() {\n return {\n aspectRatio: this.aspectRatio,\n viewMode: 1,\n zoomable: false,\n checkCrossOrigin: false, // Prevent CORS issues\n checkOrientation: false, // Prevent loading the image via AJAX which can cause CORS issues\n data: this.box\n }\n }\n\n get cropFrom() {\n if (this.#cropFromField?.value) {\n return this.#cropFromField.value.split(\"x\").map((v) => parseInt(v))\n }\n }\n\n get cropSize() {\n if (this.#cropSizeField?.value) {\n return this.#cropSizeField.value.split(\"x\").map((v) => parseInt(v))\n }\n }\n\n get box() {\n if (this.cropFrom && this.cropSize) {\n return {\n x: this.cropFrom[0],\n y: this.cropFrom[1],\n width: this.cropSize[0],\n height: this.cropSize[1]\n }\n } else {\n return this.defaultBoxSize\n }\n }\n\n get defaultBoxSize() {\n return {\n x: this.defaultBox[0],\n y: this.defaultBox[1],\n width: this.defaultBox[2],\n height: this.defaultBox[3]\n }\n }\n\n init() {\n if (!this.#initialized) {\n this.#cropper = new Cropper(this.image, this.cropperOptions)\n this.#initialized = true\n }\n }\n\n update(coords) {\n this.#cropFromField.value = `${coords.x}x${coords.y}`\n this.#cropFromField.dispatchEvent(new Event(\"change\"))\n this.#cropSizeField.value = `${coords.width}x${coords.height}`\n this.#cropSizeField.dispatchEvent(new Event(\"change\"))\n }\n\n reset() {\n const cropper = this.#cropper\n // Apply the default size. cropperjs clamps the crop box to its maximum size.\n cropper.setData(this.defaultBoxSize)\n // When the default box sits at the maximum crop box size, sub-pixel rounding\n // makes cropperjs treat setData's box as oversized and revert its position\n // (renderCropBox resets top/left to their old values). Re-apply the position\n // in canvas coordinates afterwards – that does not touch the size, so it is\n // not reverted and the mask actually moves to the default box.\n const canvas = cropper.getCanvasData()\n const scale = canvas.width / canvas.naturalWidth\n cropper.setCropBoxData({\n left: canvas.left + this.defaultBoxSize.x * scale,\n top: canvas.top + this.defaultBoxSize.y * scale\n })\n this.update(this.defaultBoxSize)\n }\n\n destroy() {\n if (this.#cropper) {\n this.#cropper.destroy()\n }\n this.#initialized = false\n return true\n }\n\n bind() {\n this.dialog.dialog_body.find('button[type=\"submit\"]').on(\"click\", () => {\n const data = this.#cropper.getData(true)\n this.update(data)\n this.elementEditor.setDirty()\n this.dialog.close()\n return false\n })\n this.dialog.dialog_body.find('button[type=\"reset\"]').on(\"click\", () => {\n this.reset()\n return false\n })\n }\n}\n","import { Dialog } from \"alchemy_admin/dialog\"\n\nexport default class ImageOverlay extends Dialog {\n constructor(url, options = {}) {\n super(url, options)\n }\n\n init() {\n $(\".zoomed-picture-background\").on(\"click\", (e) => {\n e.stopPropagation()\n if (e.target.nodeName === \"IMG\") {\n return\n }\n this.close()\n return false\n })\n $(\".picture-overlay-handle\").on(\"click\", (e) => {\n this.dialog.toggleClass(\"hide-form\")\n return false\n })\n this.$previous = $(\".previous-picture\")\n this.$next = $(\".next-picture\")\n this.#initKeyboardNavigation()\n super.init()\n }\n\n previous() {\n if (this.$previous[0] != null) {\n this.$previous[0].click()\n }\n }\n\n next() {\n if (this.$next[0] != null) {\n this.$next[0].click()\n }\n }\n\n build() {\n this.dialog_container = $('<div class=\"alchemy-image-overlay-container\" />')\n this.dialog = $('<div class=\"alchemy-image-overlay-dialog\" />')\n this.dialog_body = $('<div class=\"alchemy-image-overlay-body\" />')\n this.close_button = $(`<a class=\"alchemy-image-overlay-close\">\n <alchemy-icon name=\"close\" size=\"xl\"></alchemy-icon>\n </a>`)\n this.dialog.append(this.close_button)\n this.dialog.append(this.dialog_body)\n this.dialog_container.append(this.dialog)\n this.overlay = $('<div class=\"alchemy-image-overlay\" />')\n this.$body.append(this.overlay)\n this.$body.append(this.dialog_container)\n }\n\n #initKeyboardNavigation() {\n this.$document.keydown((e) => {\n if (e.target.nodeName === \"INPUT\" || e.target.nodeName === \"TEXTAREA\") {\n return true\n }\n switch (e.which) {\n case 37:\n this.previous()\n return false\n case 39:\n this.next()\n return false\n default:\n return true\n }\n })\n }\n}\n","import { on } from \"alchemy_admin/utils/events\"\nimport { openDialog } from \"alchemy_admin/dialog\"\n\nfunction toggleCheckboxes(state) {\n document\n .querySelectorAll(\".picture_tool.select input[type='checkbox']\")\n .forEach((checkbox) => {\n checkbox.checked = state\n checkbox.closest(\".picture_thumbnail\").classList.toggle(\"active\", state)\n })\n}\n\nfunction checkedInputs() {\n return document.querySelectorAll(\"#picture_archive input:checked\")\n}\n\nfunction editMultiplePicturesUrl(href) {\n const url = new URL(href)\n\n checkedInputs().forEach((entry) =>\n url.searchParams.append(entry.name, entry.value)\n )\n\n return url.toString()\n}\n\n/**\n * Multiple picture select handler for the picture archive.\n */\nexport default function PictureSelector() {\n const selectAllButton = document.querySelector(\"#select_all_pictures\")\n const selectedItemTools = document.querySelector(\".selected_item_tools\")\n\n on(\"click\", \".toolbar_buttons\", \"a#select_all_pictures\", (event) => {\n event.preventDefault()\n\n selectAllButton.classList.toggle(\"active\")\n\n const state = selectAllButton.classList.contains(\"active\")\n\n toggleCheckboxes(state)\n\n selectedItemTools.classList.toggle(\"hidden\", !state)\n })\n\n // make the item toolbar visible and show the checkbox also if it is not hovered anymore\n on(\"change\", \".picture_tool.select\", \"input\", (event) => {\n selectedItemTools.classList.toggle(\"hidden\", checkedInputs().length === 0)\n\n const parentElementClassList = event.target.parentElement.classList\n const checked = event.target.checked\n\n parentElementClassList.toggle(\"visible\", checked)\n })\n\n // open the edit view in a dialog modal\n on(\"click\", \".selected_item_tools\", \"a#edit_multiple_pictures\", (event) => {\n event.preventDefault()\n\n const url = editMultiplePicturesUrl(event.target.href)\n\n openDialog(url, {\n title: event.target.title,\n size: \"400x295\"\n })\n })\n}\n","import Sortable from \"sortablejs\"\nimport { patch } from \"alchemy_admin/utils/ajax\"\nimport { on } from \"alchemy_admin/utils/events\"\nimport { growl } from \"alchemy_admin/growler\"\n\nfunction displayNodeFolders() {\n document.querySelectorAll(\"li.menu-item\").forEach((el) => {\n const leftIconArea = el.querySelector(\".nodes_tree-left_images\")\n const list = el.querySelector(\".children\")\n const node = {\n folded: el.dataset.folded === \"true\",\n id: el.dataset.id,\n type: el.dataset.type\n }\n\n if (list.children.length > 0 || node.folded) {\n leftIconArea.innerHTML = Handlebars.templates[\"node_folder.hbs\"]({\n node: node\n })\n } else {\n leftIconArea.innerHTML = \"&nbsp;\"\n }\n })\n}\n\nfunction onFinishDragging(evt) {\n const url = Alchemy.routes[evt.item.dataset.type].move_api_path(\n evt.item.dataset.id\n )\n const data = {\n target_parent_id: evt.to.dataset.recordId,\n new_position: evt.newIndex\n }\n\n patch(url, data)\n .then(() => {\n const message = Alchemy.t(\"Successfully moved menu item\")\n growl(message)\n displayNodeFolders()\n })\n .catch((error) => {\n growl(error.message || error, \"error\")\n })\n}\n\nfunction handleNodeFolders() {\n on(\"click\", \".nodes_tree\", \".node_folder\", function () {\n const nodeId = this.dataset.recordId\n const menu_item = this.closest(\"li.menu-item\")\n const url =\n Alchemy.routes[this.dataset.recordType].toggle_folded_api_path(nodeId)\n const list = menu_item.querySelector(\".children\")\n\n patch(url)\n .then(() => {\n list.classList.toggle(\"folded\")\n menu_item.dataset.folded =\n menu_item.dataset.folded == \"true\" ? \"false\" : \"true\"\n displayNodeFolders()\n })\n .catch((error) => {\n growl(error.message || error)\n })\n })\n}\n\nexport default function NodeTree() {\n handleNodeFolders()\n displayNodeFolders()\n\n document.querySelectorAll(\".nodes_tree ul.children\").forEach((el) => {\n new Sortable(el, {\n group: \"nodes\",\n animation: 150,\n fallbackOnBody: true,\n swapThreshold: 0.65,\n handle: \".node_name\",\n invertSwap: true,\n onEnd: onFinishDragging\n })\n })\n}\n","// We still use jQuery in some places (ie. select2)\nimport \"handlebars\"\nimport \"jquery\"\nimport \"@ungap/custom-elements\"\nimport { Turbo } from \"@hotwired/turbo-rails\"\nimport \"select2\"\n\nimport Rails from \"@rails/ujs\"\n\nimport { translate } from \"alchemy_admin/i18n\"\nimport { currentDialog, closeCurrentDialog } from \"alchemy_admin/dialog\"\nimport Dirty from \"alchemy_admin/dirty\"\nimport * as FixedElements from \"alchemy_admin/fixed_elements\"\nimport { growl } from \"alchemy_admin/growler\"\nimport Initializer from \"alchemy_admin/initializer\"\nimport { LinkDialog } from \"alchemy_admin/link_dialog\"\nimport pleaseWaitOverlay from \"alchemy_admin/please_wait_overlay\"\nimport Spinner from \"alchemy_admin/spinner\"\nimport { reloadPreview } from \"alchemy_admin/components/preview_window\"\nimport { openConfirmDialog } from \"alchemy_admin/confirm_dialog\"\n\n// Web Components\nimport \"alchemy_admin/components\"\n\n// Handlebars Templates\nimport \"alchemy_admin/templates/compiled\"\n\n// Shoelace Setup\nimport \"alchemy_admin/shoelace_theme\"\n\n// Global Alchemy object\nif (typeof window.Alchemy === \"undefined\") {\n window.Alchemy = {}\n}\n\n// Enhance the global Alchemy object with imported features\nObject.assign(Alchemy, {\n closeCurrentDialog,\n currentDialog,\n ...Dirty,\n t: translate, // Global utility method for translating a given string\n FixedElements,\n growl,\n LinkDialog,\n pleaseWaitOverlay,\n Spinner,\n reloadPreview\n})\n\nRails.start()\nTurbo.config.forms.confirm = openConfirmDialog\ndocument.addEventListener(\"turbo:load\", Initializer)\n\n// Public API for extensions\nexport { RemoteSelect } from \"alchemy_admin/components/remote_select\"\nexport { on } from \"alchemy_admin/utils/events\"\n\n// Page-specific modules - bundled to avoid dual-loading\nexport { default as ImageCropper } from \"alchemy_admin/image_cropper\"\nexport { default as ImageOverlay } from \"alchemy_admin/image_overlay\"\nexport { default as pictureSelector } from \"alchemy_admin/picture_selector\"\nexport { default as NodeTree } from \"alchemy_admin/node_tree\"\n","import Hotkeys from \"alchemy_admin/hotkeys\"\nimport pleaseWaitOverlay from \"alchemy_admin/please_wait_overlay\"\n\nexport default function Initializer() {\n // We obviously have javascript enabled.\n document.documentElement.classList.remove(\"no-js\")\n\n // Initialize hotkeys.\n Hotkeys()\n\n // Add observer for please wait overlay.\n document.querySelectorAll(\".please_wait\").forEach((element) => {\n element.addEventListener(\"click\", pleaseWaitOverlay)\n })\n\n // Hack for enabling tab focus for <a>'s styled as button.\n document.querySelectorAll(\"a.button\").forEach((button) => {\n button.setAttribute(\"tabindex\", 0)\n })\n\n // Override the filter of keymaster.js so we can blur the fields on esc key.\n key.filter = function (event) {\n let tagName = (event.target || event.srcElement).tagName\n return (\n key.isPressed(\"esc\") ||\n !(tagName === \"INPUT\" || tagName === \"SELECT\" || tagName === \"TEXTAREA\")\n )\n }\n}\n"],"names":["KEY_SEPARATOR","getTranslation","key","locale","currentLocale","translations","Alchemy","test","keys","split","group","nestedTranslation","console","warn","document","documentElement","lang","translate","replacement","undefined","translation","replace","async","setupSelectLocale","import","$","extend","fn","select2","defaults","locales","bindedHotkeys","showHelp","evt","target","is","String","fromCharCode","which","openDialog","title","t","size","Hotkeys","scope","jQuery","removeEventListener","addEventListener","forEach","hotkey","unbind","search_fields","querySelectorAll","search_fields_clear","setScope","el","focus","focusVisible","push","click","blur","dataset","alchemyHotkey","createHtmlElement","text","element","createElement","innerHTML","content","children","Spinner$1","constructor","color","this","spinner","spin","parent","body","append","stop","remove","currentDialogs","DEFAULTS","header_height","padding","modal","overflow","ready","closed","Dialog","url","options","$document","$window","window","$body","width","parseInt","height","build","resize","open","dialog","trigger","bind_close_events","requestAnimationFrame","dialog_container","addClass","overlay","load","close","off","removeClass","on","pop","show_spinner","get","data","fail","xhr","show_error","reload","dialog_body","empty","remove_spinner","hide","html","init","dispatchEvent","CustomEvent","bubbles","detail","show","Spinner","watch_remote_forms","find","$form","event","getResponseHeader","match","responseText","statusText","status","error_body","error_header","error_type","error_messages","$errorDiv","error","close_button","e","keydown","dialog_header","dialog_title","getSize","css","doc_width","doc_height","currentDialog","length","closeCurrentDialog","callback","ConfirmDialog","message","ok_label","cancel_label","on_ok","bindEvents","cancelButton","preventDefault","on_cancel","okButton","source","querySelector","openConfirmDialog","Promise","resolve","pleaseWaitOverlay","checkPageDirtyness","action","appendTo","Turbo","visit","pathname","then","proceed","onbeforeunload","Dirty","PageLeaveObserver","currentTarget","removeTab","element_id","fixed_elements","getElementById","panel_name","label","tab","panel","growl","style","flashType","flashNotices","flashMessage","ANCHOR_REGEX","PreviewWindow","HTMLIFrameElement","afterLoad","reloadIcon","loadTimeout","handleEvent","type","clearLoadTimeout","stopSpinner","call","onPreviewReady","connectedCallback","attachEvents","localStorage","getItem","previewUrlSelect","value","refresh","disconnectedCallback","postMessage","contentWindow","startSpinner","src","setTimeout","isDragged","dragged","transitionProperty","pointerEvents","reloadButton","sizeSelect","setItem","includes","clearTimeout","getAttribute","reloadPreview","customElements","define","extends","IngredientAnchorLink","updateIcon","ingredientId","active","ingredientEditor","setAttribute","Action","HTMLElement","super","actions","removeFixedElement","updateAnchorIcon","hidePleaseWaitOverlay","func","name","params","hasAttribute","JSON","parse","hightlightTerm","term","RegExp","RemoteSelect","isConnected","input","classList","add","select2Config","onOpen","onChange","added","stringify","dispatchCustomEvent","removed","allowClear","selection","placeholder","queryParams","getElementsByTagName","initSelection","_$el","ajax","ajaxConfig","formatSelection","item","_renderResult","formatResult","_el","query","_renderListEntry","datatype","quietMillis","page","_searchQuery","results","response","_parseResponse","q","name_cont","meta","more","per_page","total_count","Error","_hightlightTerm","attachment","icon_css_class","AutoSubmit","submitEvent","Event","cancelable","form","Button","HTMLButtonElement","remote","stopPropagation","disable","enable","rect","getBoundingClientRect","initialButtonText","removeAttribute","CharCounter","maxChars","formField","getFormField","createDisplayElement","countCharacters","formFields","display","className","after","charLength","textContent","toggle","ClipboardButton","clipboard","ClipboardJS","destroy","formatItem","object","optionEl","swatch","ColorSelect","select","initializeSelect2","onSelectChange","colorInput","textInput","toggleColorPicker","val","minimumResultsForSearch","enabled","disabled","Datepicker","flatpickr","inputField","flatpickrOptions","enableTime","inputType","slice","altInput","altFormat","altInputClass","noCalendar","time_24hr","onValueUpdate","_selectedDates","_dateStr","instance","closest","setDirty","dateFormat","DialogLink","HTMLAnchorElement","dialogOptions","contains","JSON_CONTENT_TYPE","isGetRequest","method","toLowerCase","prepareOptions","accept","headers","Accept","getToken","prepareHeaders","attributes","patch","post","path","fetch","URL","location","origin","search","URLSearchParams","toString","prepareURL","contentType","isJson","isTurboStream","responseData","json","renderStreamMessage","ok","DomIdSelect","dataItem","hash","id","selectElement","pageId","fetchDomIds","routes","api_ingredients_path","page_id","ingredients","filter","ingredient","dom_id","map","prompt","setOptions","reset","frame","elements","contentDocument","Array","from","PublishElementButton","scheduleButtonVariant","scheduleButton","publishButton","dropdown","loading","DeleteElementButton","button","removeElement","elementEditor","fixed","elementId","pageHasUnpublishedChanges","dispatchPageDirtyEvent","tooltip","publishButtonTooltip","ElementEditor","header","toggleButton","onHeaderDblclick","onToggleClick","focusElement","previewWindow","focusElementPreview","onClickElement","onSaveElement","hasEditors","firstChild","setTitle","selectTabForElement","expand","setClean","warning","ingredientsWithErrors","errorDisplay","errorMessage","appendChild","elementErrors","notice","updateTitle","previewText","ingredientAnchors","anchor","scrollToElement","scrollIntoView","behavior","scroll","reject","tabs","dirty","editor","quote","collapsed","collapse","compact","toggleIcon","collapse_admin_element_path","nestedElementIds","selector","join","nestedElement","catch","finally","expanded","parentElementEditor","expand_admin_element_path","parentElementIds","parentElement","published","isPublished","bodySelector","footer","elementName","hasChildren","option","icon","ElementSelect","dropdownAutoWidth","hint","description","ElementsWindow","visible","turboFrame","collapseButton","onCollapseClick","onWindowMessage","onBodyClick","focusElementEditor","collapseAllElements","removeProperty","widthFromCookie","setProperty","cookie","row","startsWith","ElementsWindowHandle","dragging","elementsWindow","minWidth","maxWidth","onMouseDown","onMouseUp","onDrag","pageX","styles","getComputedStyle","parseFloat","elementWindowWidth","innerWidth","Math","min","max","FileEditor","deleteLink","fileIcon","fileName","formFieldId","removeFile","ListFilter","debounceTimer","filterField","clearButton","onHotkey","onKeyup","onFocus","onClearClick","onEscape","visibility","matchedItems","itemsToShow","Set","lowerTerm","items","nameAttribute","indexOf","ancestor","itemsSelector","has","block","clear","debounceTime","Message","dismissTimeoutId","dismiss","closeIcon","dismissable","insertAdjacentHTML","iconName","dismissDelay","noticesWrapper","autoDismissDelay","Growl","Icon","observedAttributes","spriteUrl","render","attributeChangedCallback","sizeClass","IngredientGroup","HTMLDetailsElement","localStorageKey","isInLocalStorage","expanded_ingredient_groups","localStorageItem","LinkButton","LinkDialog","linkUrl","linkTitle","linkTarget","linkClass","link","setLink","linkButtons","linkUrlField","linkTitleField","linkTargetField","linkClassField","UnlinkButton","linked","isLinked","LinkButtons","removeLink","unlinkButton","setElementDirty","linkButton","formatFileSize","bytes","exponent","floor","log","pow","toFixed","name_or_page_name_cont","node","ancestors","a","seperator","FileUpload","file","request","progressEventLoaded","progressEventTotal","valid","loadedSize","cancel","reader","FileReader","readAsDataURL","image","Image","result","prepend","initialize","validateFile","addRequestEventListener","finished","abort","config","uploader_defaults","maxFileSize","file_size_limit","allowedFiletypes","allowed_filetypes","alchemy_pictures","alchemy_attachments","upload","onprogress","progressEvent","onload","responseMessage","onerror","errorMessageContainer","progressElement","loaded","total","round","toggleAttribute","isValid","Progress","fileCount","fileUploads","buttonLabel","actionButton","handleFileChange","updateView","onComplete","fileUpload","activeUploads","setupCloseButton","_status","ariaLabel","sumFileProgresses","field","reduce","accumulator","totalProgress","overallProgressValue","overallUploadSize","every","entry","fileProgress","uploadedFileCount","uploadsStatuses","totalSize","ceil","weight","Uploader","dropzoneElement","isDraggedOver","fileInput","onFileInputChange","dropzone","setupDropZone","onDropzoneDragleave","onDropzoneDrop","onDropzoneDragover","handleUploadComplete","uploadFiles","files","toggleDropzoneClass","dataTransfer","getAsFile","redirectUrl","uploadProgress","fileUploadCount","XMLHttpRequest","upload_limit","submitFile","createProgress","formData","FormData","set","setRequestHeader","send","removeChild","Overlay","BUTTON","AlchemyPageNode","folded","folderButton","handleFolderClick","fold_admin_page_path","toggleChildren","updateFolderIcon","childrenContainer","updateFolderButton","folderElement","shouldShowButton","tagName","outerHTML","PagePublicationFields","publicField","onClick","checkbox","date","Date","now","getTime","getTimezoneOffset","toISOString","checked","publicationDateFields","publicOnPicker","substring","publicUntilPicker","pages","site","url_path","language_code","PictureDescriptionSelect","searchParams","PictureEditor","cropFromField","cropSizeField","pictureIdField","targetSizeField","imageCropperField","pictureThumbnail","deleteButton","cropLink","targetSize","pictureId","update","delay","timeout","args","that","apply","debounce","updateImage","updateCropLink","removeImage","observer","MutationObserver","mutationCallback","observe","disconnect","mutationsList","mutation","url_admin_picture_path","crop","imageCropperEnabled","crop_from","cropFrom","crop_size","cropSize","flatten","alt","href","defaultCropFrom","defaultCropSize","mask","n","zoom","imageFileWidth","b","imageFileHeight","dimensions","imageCropper","PictureThumbnail","onLoaded","onError","start","setImage","createImage","complete","hoist","replaceChildren","PublishPageButton","markDirty","variant","forEvents","events","MicroEvent","_events","fct","event_array","arguments","splice","self","arrayToPattern","chars","Boolean","maxValueLength","sequencePattern","array","hasDuplicates","pattern","prev_char_count","prev_pattern","char","i","setToPattern","escape_regex","str","longest","unicodeLength","allSubstrings","subresult","tmp","charAt","unshift","code_points","unicode_map","multi_char_reg","latin_convert","latin_condensed","aa","ae","ao","au","av","ay","c","d","f","g","h","j","k","l","m","o","oe","oi","oo","ou","p","r","s","th","tz","u","v","vy","w","y","z","hv","latin","unicode","convert_pat","Object","normalize","asciifold","_asciifold","generateSets","unicode_sets","addMatching","to_add","folded_set","patt","code_point_min","code_point_max","composed","code_point","generator","generateMap","multi_char","sort","multi_char_patt","substringsToPattern","min_replacement","sub_pat","strings","chars_replaced","mapSequence","sequencesToPattern","sequences","all","sequence","seq","len","substrs","inSequences","needle_seq","end","needle_parts","parts","part","needle_part","substr","Sequence","last","clone","position","last_piece","last_part","last_substr","clone_last_len","getPattern","match_str","overlapping","added_types","new_seq","old_seq","getAttr","obj","getAttrNesting","names","shift","scoreValue","token","score","pos","regex","string","propToArray","isArray","iterate","hasOwnProperty","cmp","Sifter","settings","diacritics","tokenize","respect_word_boundaries","weights","tokens","words","field_regex","word","field_match","getScoreFunction","prepareSearch","_getScoreFunction","token_count","fields","field_count","getAttrFn","scoreObject","sum","conjunction","getSortFunction","_getSortFunction","implicit_score","sort_flds","sort_empty","bind","get_field","fld","direction","sort_fld","optsUser","assign","trim","fn_score","_","fn_sort","limit","hash_key","get_hash","escape_html","loadDebounce","loadedSearches","debounce_events","types","event_args","addEvent","isKeyDown","key_name","altKey","ctrlKey","shiftKey","metaKey","getId","existing_id","addSlashes","getDom","jquery","isHtmlString","tpl","arg","triggerEvent","dom_el","event_name","createEvent","initEvent","applyCSS","addClasses","elmts","classes","norm_classes","classesArray","castAsArray","cls","removeClasses","_classes","concat","parentMatch","wrapper","matches","parentNode","getTail","list","nodeIndex","amongst","nodeName","previousElementSibling","setAttr","attrs","attr","replaceNode","existing","replaceChild","highlight","highlightRecursive","nodeType","spannode","middlebit","splitText","index","middleclone","cloneNode","highlightText","childNodes","highlightChildren","KEY_SHORTCUT","navigator","userAgent","optgroups","plugins","delimiter","splitOn","persist","create","createOnBlur","createFilter","clearAfterSelect","openOnFocus","shouldOpen","maxOptions","maxItems","hideSelected","duplicates","addPrecedence","selectOnTab","preload","allowEmptyOption","refreshThrottle","loadThrottle","loadingClass","dataAttr","optgroupField","valueField","labelField","disabledField","optgroupLabelField","optgroupValueField","lockOptgroupOrder","sortField","searchField","searchConjunction","mode","wrapperClass","controlClass","dropdownClass","dropdownContentClass","itemClass","optionClass","dropdownParent","controlInput","copyClassesToDropdown","hidePlaceholder","shouldLoad","getSettings","settings_user","attr_data","field_label","field_value","field_disabled","field_optgroup","field_optgroup_label","field_optgroup_value","tag_name","settings_element","optionsMap","group_count","$order","readData","addOption","arr","option_data","$option","selected","child","optgroup","optgroup_data","init_select","_a","_b","data_raw","opt","values","init_textbox","instance_i","TomSelect","Interface","requested","initializePlugins","queue","plugin","require","loadPlugin","MicroPlugin","input_arg","user_settings","dir","order","isOpen","isDisabled","isReadOnly","isInvalid","isLocked","isFocused","isInputHidden","isSetup","isDropdownContentStale","ignoreFocus","ignoreHover","hasOptions","lastValue","caretPos","activeOption","activeItems","userOptions","refreshTimeout","tomselect","getPropertyValue","tabIndex","is_select_tag","rtl","inputId","isRequired","required","sifter","setupCallbacks","setupTemplates","control","_render","dropdown_content","inputMode","control_input","focus_node","setup","passive_event","passive","listboxId","role","control_id","escapeQuery","label_click","for","label_id","classes_plugins","multiple","target_match","onOptionHover","capture","onOptionSelect","onItemSelect","onKeyDown","onKeyPress","onInput","onBlur","onPaste","doc_mousedown","composedPath","inputState","win_scroll","positionDropdown","input_invalid","refreshState","_destroy","revertSettings","insertAdjacentElement","sync","refreshItems","setupOptions","addOptions","registerOptionGroup","templates","optgroup_header","escape","option_create","no_results","not_loading","callbacks","change","item_add","item_remove","item_select","option_add","option_remove","option_clear","optgroup_add","optgroup_remove","optgroup_clear","dropdown_open","dropdown_close","get_settings","setValue","readOnly","setReadOnly","lastQuery","clearActiveItems","pastedText","inputValue","splitInput","piece","addItem","createItem","character","keyCode","constants.KEY_SHORTCUT","selectAll","next","getAdjacent","setActiveOption","prev","canSelect","activeElement","advanceSelection","deleteSelection","_onInput","refreshOptions","wasFocused","hasFocus","deactivate","setActiveItem","setCaret","closeAfterSelect","setTextboxValue","canLoad","loadCallback","clearActiveOption","getValue","silent","addItems","setMaxItems","eventName","begin","swap","getLastActive","prototype","setActiveItemClass","removeActiveItem","last_active","idx","scrollToOption","height_menu","clientHeight","scrollTop","height_item","offsetHeight","top","scrollBehavior","controlChildren","focusTarget","offsetWidth","getRootNode","getSearchOptions","nesting","calculateScore","currentResults","hashed","triggerDropdown","has_create_option","active_group","groups","groups_order","same_query","active_option","show_dropdown","getGroupFragment","group_order_i","order_group","fragment","group_fragment","createDocumentFragment","opt_value","opt_hash","option_el","getOption","self_optgroup","regGroup","optionGroupRegister","$id","group_order","group_heading","group_options","group_html","tok","add_template","template","insertBefore","canCreate","active_index","selectable","user_created","updateOption","dat","registerOption","addOptionGroup","hashed_id","removeOptionGroup","clearCache","clearOptionGroups","item_new","index_item","value_old","value_new","data_old","uncacheValue","option_new","removeOption","removeItem","clearOptions","boundFilter","clearFilter","$div","last_item","x","isPending","wasFull","isFull","insertAtCaret","updateOriginalInput","output","caret","lock","created","unlock","refreshValidityState","wrap_classList","validity","opts","empty_option","has_selected","AddSelected","context","scrollY","left","scrollX","tail","selectionStart","selectionEnd","rm_items","rm_item","shouldDelete","onDelete","adjacent","nextElementSibling","moveCaret","new_pos","setLocked","setDisabled","templateName","hook","when","new_fn","orig_method","result_new","orig_onOptionSelect","cbOptions","checkedClassNames","uncheckedClassNames","UpdateChecked","toCheck","UpdateCheckbox","HTMLInputElement","orig_render_option","rendered","tabindex","orig_lock","orig_unlock","drag_item","sortable","orig_render_item","draggable","dragOver","moveitem","targetitem","dragitem","referenceNode","newNode","_referenceNode$parent","_newNode","isBefore","nextSibling","_referenceNode$parent2","_drag_item","headerClass","titleRowClass","labelClass","closeClass","close_link","_self$input","div","orig_onBlur","relatedTarget","preventScroll","test_input","cssText","style_name","clientWidth","orig_deleteSelection","orig_keydown","previousSibling","orig_canLoad","orig_clearActiveOption","orig_loadCallback","load_more_opt","default_pagination","pagination","loading_more","default_values","default_values_loaded","shouldLoadMore","scrollHeight","firstUrl","canLoadMore","setNextUrl","next_url","getUrl","clearPagination","first_option","restoreDefaults","no_more_results","createCoords","oppositeSideMap","right","bottom","evaluate","param","getSide","placement","getAlignment","getAxisLength","axis","getSideAxis","firstChar","getAlignmentAxis","getOppositeAlignmentPlacement","lrPlacement","rlPlacement","tbPlacement","btPlacement","getOppositeAxisPlacements","flipAlignment","alignment","side","isStart","getSideList","getOppositePlacement","rectToClientRect","computeCoordsFromPlacement","_ref","reference","floating","sideAxis","alignmentAxis","alignLength","isVertical","commonX","commonY","commonAlign","coords","detectOverflow","state","_await$platform$isEle","platform","rects","strategy","boundary","rootBoundary","elementContext","altBoundary","paddingObject","expandPaddingObject","getPaddingObject","clippingClientRect","getClippingRect","isElement","contextElement","getDocumentElement","offsetParent","getOffsetParent","offsetScale","getScale","elementClientRect","convertOffsetParentRelativeRectToViewportRelativeRect","originSides","hasWindow","getNodeName","isNode","getWindow","_node$ownerDocument","ownerDocument","defaultView","Node","Element","isHTMLElement","isShadowRoot","ShadowRoot","isOverflowElement","overflowX","overflowY","isTableElement","isTopLayer","_e","willChangeRe","containRe","isNotNone","isWebKitValue","isContainingBlock","elementOrCss","transform","scale","rotate","perspective","isWebKit","backdropFilter","willChange","contain","CSS","supports","isLastTraversableNode","getNodeScroll","scrollLeft","getParentNode","assignedSlot","host","getNearestOverflowAncestor","getOverflowAncestors","traverseIframes","_node$ownerDocument2","scrollableAncestor","isBody","win","frameElement","getFrameElement","visualViewport","getPrototypeOf","getCssDimensions","getComputedStyle$1","hasOffset","shouldFallback","unwrapElement","domElement","Number","isFinite","noOffsets","getVisualOffsets","offsetLeft","offsetTop","includeScale","isFixedStrategy","clientRect","visualOffsets","isFixed","floatingOffsetParent","shouldAddVisualOffsets","offsetWin","currentWin","currentIFrame","iframeScale","iframeRect","clientLeft","paddingLeft","clientTop","paddingTop","getWindowScrollBarX","leftScroll","getHTMLOffset","htmlRect","getClientRectFromClippingAncestor","clippingAncestor","visualViewportBased","windowScrollbarX","doc","bodyStyles","bodyMarginInline","compatMode","marginLeft","marginRight","clippingStableScrollbarWidth","abs","getViewportRect","scrollWidth","getDocumentRect","getInnerBoundingClientRect","hasFixedPositionAncestor","stopNode","getRectRelativeToOffsetParent","isOffsetParentAnElement","offsets","setLeftRTLScrollbarOffset","offsetRect","htmlOffset","isStaticPositioned","getTrueOffsetParent","polyfill","rawOffsetParent","svgOffsetParent","currentNode","getContainingBlock","topLayer","clippingAncestors","cache","cachedResult","currentContainingBlockComputedStyle","elementIsFixed","computedStyle","currentNodeIsContaining","getClippingElementAncestors","_c","firstRect","getElementRects","getOffsetParentFn","getDimensionsFn","getDimensions","floatingDimensions","getClientRects","isRTL","rectsAreEqual","autoUpdate","ancestorScroll","ancestorResize","elementResize","ResizeObserver","layoutShift","IntersectionObserver","animationFrame","referenceEl","cleanupIo","onMove","timeoutId","io","root","cleanup","_io","skip","threshold","elementRectForRootMargin","rootMargin","isFirstUpdate","handleObserve","entries","ratio","intersectionRatio","observeMove","frameId","reobserveFrame","resizeObserver","firstEntry","unobserve","cancelAnimationFrame","_resizeObserver","prevRefRect","frameLoop","nextRefRect","_resizeObserver2","offset","_middlewareData$offse","_middlewareData$arrow","middlewareData","diffCoords","mainAxisMulti","crossAxisMulti","rawValue","mainAxis","crossAxis","convertValueToCoords","arrow","alignmentOffset","flip","_middlewareData$flip","initialPlacement","checkMainAxis","checkCrossAxis","fallbackPlacements","specifiedFallbackPlacements","fallbackStrategy","fallbackAxisSideDirection","detectOverflowOptions","initialSideAxis","isBasePlacement","oppositePlacement","getExpandedPlacements","hasFallbackAxisSideDirection","placements","overflows","overflowsData","sides","mainAlignmentSide","getAlignmentSides","_middlewareData$flip2","_overflowsData$filter","nextIndex","nextPlacement","resetPlacement","_overflowsData$filter2","currentSideAxis","acc","_state$middlewareData","_state$middlewareData2","isYAxis","heightSide","widthSide","maximumClippingHeight","maximumClippingWidth","overflowAvailableHeight","overflowAvailableWidth","noShift","availableHeight","availableWidth","xMin","xMax","yMin","yMax","nextDimensions","computePosition","Map","mergedOptions","platformWithCache","middleware","platformWithDetectOverflow","statefulPlacement","resetCount","currentMiddleware","nextX","nextY","computePosition$1","Select","HTMLSelectElement","tomSelect","initTomSelect","destroyTomSelect","selectedValue","Option","hasPlaceholder","hasSelectedOption","dropdownMask","removeAutoUpdater","remove_button","clear_button","onInitialize","autofocus","onType","onDropdownOpen","zIndex","maxHeight","onDropdownClose","AlchemySitemap","searchInput","resultCounter","setupSearch","setupSortables","mutations","addedNodes","ELEMENT_NODE","setupSortable","childList","subtree","teardownSearch","handleSearch","handleClearSearch","filterPages","allPages","matchCount","firstMatch","pageElement","container","Sortable","animation","fallbackOnBody","swapThreshold","handle","onEnd","handleSort","to","oldIndex","newIndex","pageNode","move_admin_page_path","target_parent_id","parentId","new_position","pageData","pageEl","urlPathEl","updateFolderIcons","fromContainer","toContainer","fromParent","toParent","SORTABLE_OPTIONS","ghostClass","easing","onStart","onSort","parent_element_id","order_admin_elements_path","preview_text","SortableElements","put","_from","droppableElements","TagsAutocomplete","tags","tokenSeparators","openOnEnter","minimumInputLength","createSearchChoice","dataType","localeCompare","each","DARK_THEME","LIGHT_THEME","Tinymce","min_height","minHeight","tinymceIntersectionObserver","_initTinymceEditor","_setupThemeChangeListener","_removeThemeChangeListener","tinymce","editorId","configuration","editors","_setupEditor","editorContainer","darkModeMediaQuery","matchMedia","themeChangeHandler","_handleThemeChange","skin","content_css","customConfig","getAttributeNames","attributeName","replaceAll","preferredTheme","TinymceDefaults","language","UpdateCheck","credentials","responseJSON","showStatus","showError","Handlebars","compiler","main","lambda","escapeExpression","lookupProperty","nullContext","program","inverse","loc","line","column","useData","setDefaultAnimation","keyframes","opacity","duration","iconMap","resolver","mutator","svg","spriteSheet","baseSelector","targetSelector","baseNode","targets","registerIconLibrary","ImageCropper","initialized","cropper","defaultBox","default_box","aspectRatio","crop_from_form_field_id","crop_size_form_field_id","cropperOptions","viewMode","zoomable","checkCrossOrigin","checkOrientation","box","defaultBoxSize","Cropper","setData","canvas","getCanvasData","naturalWidth","setCropBoxData","getData","ImageOverlay","toggleClass","$previous","$next","initKeyboardNavigation","previous","checkedInputs","PictureSelector","selectAllButton","selectedItemTools","toggleCheckboxes","parentElementClassList","editMultiplePicturesUrl","displayNodeFolders","leftIconArea","onFinishDragging","move_api_path","recordId","NodeTree","nodeId","menu_item","recordType","toggle_folded_api_path","invertSwap","FixedElements","onCreateLink","link_admin_pages_path","parameterMapping","selected_tab","link_title","link_target","internalForm","attachmentSelect","updatePage","submitForm","linkFormType","internalLink","domIdSelect","linkType","elementAnchor","link_url_regexp","showValidationError","errors","Rails","forms","confirm","srcElement","isPressed"],"mappings":"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","x_google_ignoreList":[55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87]}
9
+ >>>>>>> 81677ebac (Update build artifacts)