alchemy_cms 8.1.9 → 8.2.0

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.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -1
  3. data/app/assets/builds/alchemy/admin.css +1 -1
  4. data/app/assets/builds/alchemy/alchemy_admin.min.js +2 -0
  5. data/app/assets/builds/alchemy/alchemy_admin.min.js.map +1 -0
  6. data/app/assets/builds/alchemy/dark-theme.css +1 -1
  7. data/app/assets/builds/alchemy/light-theme.css +1 -1
  8. data/app/assets/builds/alchemy/theme.css +1 -1
  9. data/app/assets/builds/alchemy/welcome.css +1 -1
  10. data/app/assets/builds/tinymce/skins/content/alchemy/content.min.css +1 -1
  11. data/app/assets/builds/tinymce/skins/content/alchemy-dark/content.min.css +1 -1
  12. data/app/assets/images/alchemy/icons-sprite.svg +1 -1
  13. data/app/components/alchemy/admin/current_user_name.rb +34 -0
  14. data/app/components/alchemy/admin/locale_select.rb +12 -8
  15. data/app/components/alchemy/admin/page_node.html.erb +3 -2
  16. data/app/components/alchemy/admin/picture_thumbnail.rb +1 -1
  17. data/app/components/alchemy/admin/preview_time_select.rb +55 -0
  18. data/app/components/alchemy/admin/publish_element_button.html.erb +41 -0
  19. data/app/components/alchemy/admin/publish_element_button.rb +13 -0
  20. data/app/components/alchemy/admin/timezone_select.rb +47 -0
  21. data/app/components/alchemy/ingredients/select_editor.rb +6 -1
  22. data/app/controllers/alchemy/admin/base_controller.rb +1 -0
  23. data/app/controllers/alchemy/admin/elements_controller.rb +54 -34
  24. data/app/controllers/alchemy/admin/pages_controller.rb +1 -0
  25. data/app/controllers/alchemy/admin/resources_controller.rb +11 -6
  26. data/app/controllers/alchemy/pages_controller.rb +1 -2
  27. data/app/helpers/alchemy/admin/base_helper.rb +4 -7
  28. data/app/helpers/alchemy/url_helper.rb +2 -10
  29. data/app/javascript/alchemy_admin/components/element_editor/publish_element_button.js +28 -27
  30. data/app/javascript/alchemy_admin/components/element_editor.js +11 -2
  31. data/app/javascript/alchemy_admin/components/message.js +5 -1
  32. data/app/javascript/alchemy_admin/components/uploader/file_upload.js +5 -5
  33. data/app/javascript/alchemy_admin/image_cropper.js +10 -6
  34. data/app/javascript/alchemy_admin/initializer.js +6 -33
  35. data/app/javascript/alchemy_admin/shoelace_theme.js +6 -2
  36. data/app/javascript/alchemy_admin/templates/compiled.js +1 -1
  37. data/app/javascript/alchemy_admin.js +12 -2
  38. data/app/models/alchemy/attachment.rb +1 -1
  39. data/app/models/alchemy/current.rb +5 -1
  40. data/app/models/alchemy/element/element_ingredients.rb +11 -3
  41. data/app/models/alchemy/element.rb +10 -0
  42. data/app/models/alchemy/ingredient.rb +2 -0
  43. data/app/models/alchemy/ingredients/select.rb +1 -2
  44. data/app/models/alchemy/page/etag_generator.rb +21 -0
  45. data/app/models/alchemy/page/url_path.rb +11 -2
  46. data/app/models/alchemy/page.rb +12 -2
  47. data/app/models/alchemy/page_version.rb +5 -5
  48. data/app/models/alchemy/picture.rb +19 -2
  49. data/app/models/alchemy/storage_adapter/active_storage.rb +9 -0
  50. data/app/models/alchemy/storage_adapter/dragonfly.rb +9 -0
  51. data/app/models/alchemy/storage_adapter.rb +1 -0
  52. data/app/models/concerns/alchemy/publishable.rb +20 -12
  53. data/app/models/concerns/alchemy/relatable_resource.rb +16 -2
  54. data/app/models/concerns/alchemy/touch_elements.rb +3 -3
  55. data/app/services/alchemy/element_preloader.rb +107 -0
  56. data/app/stylesheets/alchemy/_custom-properties.scss +1 -0
  57. data/app/stylesheets/alchemy/_mixins.scss +1 -1
  58. data/app/stylesheets/alchemy/_themes.scss +2 -0
  59. data/app/stylesheets/alchemy/admin/base.scss +2 -1
  60. data/app/stylesheets/alchemy/admin/elements.scss +22 -19
  61. data/app/stylesheets/alchemy/admin/form_fields.scss +3 -0
  62. data/app/stylesheets/alchemy/admin/forms.scss +14 -1
  63. data/app/stylesheets/alchemy/admin/frame.scss +9 -8
  64. data/app/stylesheets/alchemy/admin/notices.scss +1 -1
  65. data/app/stylesheets/alchemy/admin/popover.scss +37 -0
  66. data/app/stylesheets/alchemy/admin/selects.scss +4 -0
  67. data/app/stylesheets/alchemy/admin/shoelace.scss +16 -4
  68. data/app/stylesheets/alchemy/admin/toolbar.scss +8 -0
  69. data/app/stylesheets/alchemy/admin.scss +1 -0
  70. data/app/views/alchemy/admin/_header.html.erb +4 -0
  71. data/app/views/alchemy/admin/_left_menu.html.erb +24 -0
  72. data/app/views/alchemy/admin/_main_navi.html.erb +6 -0
  73. data/app/views/alchemy/admin/_top_menu.html.erb +6 -0
  74. data/app/views/alchemy/admin/_user_info.html.erb +5 -0
  75. data/app/views/alchemy/admin/crop.html.erb +6 -11
  76. data/app/views/alchemy/admin/elements/_header.html.erb +16 -6
  77. data/app/views/alchemy/admin/elements/_schedule.html.erb +62 -0
  78. data/app/views/alchemy/admin/elements/_toolbar.html.erb +1 -15
  79. data/app/views/alchemy/admin/elements/publish.turbo_stream.erb +28 -0
  80. data/app/views/alchemy/admin/nodes/index.html.erb +1 -1
  81. data/app/views/alchemy/admin/pages/_locked_pages.html.erb +5 -0
  82. data/app/views/alchemy/admin/pages/_publication_fields.html.erb +4 -4
  83. data/app/views/alchemy/admin/pages/_table.html.erb +1 -1
  84. data/app/views/alchemy/admin/pages/edit.html.erb +6 -2
  85. data/app/views/alchemy/admin/partials/_language_tree_select.html.erb +10 -10
  86. data/app/views/alchemy/admin/partials/_site_select.html.erb +6 -3
  87. data/app/views/alchemy/admin/pictures/index.html.erb +2 -2
  88. data/app/views/alchemy/admin/tinymce/_setup.html.erb +9 -16
  89. data/app/views/alchemy/admin/uploader/_setup.html.erb +1 -6
  90. data/app/views/alchemy/language_links/_language.html.erb +1 -2
  91. data/app/views/layouts/alchemy/admin.html.erb +2 -45
  92. data/config/importmap.rb +7 -2
  93. data/config/locales/alchemy.en.yml +35 -5
  94. data/lib/alchemy/admin/preview_time.rb +23 -0
  95. data/lib/alchemy/admin/preview_url.rb +13 -2
  96. data/lib/alchemy/admin/timezone.rb +56 -0
  97. data/lib/alchemy/configuration.rb +2 -0
  98. data/lib/alchemy/configurations/main.rb +13 -1
  99. data/lib/alchemy/tasks/tidy.rb +6 -7
  100. data/lib/alchemy/test_support/factories/element_factory.rb +2 -2
  101. data/lib/alchemy/test_support/relatable_resource_examples.rb +2 -2
  102. data/lib/alchemy/test_support/shared_publishable_examples.rb +44 -2
  103. data/lib/alchemy/upgrader.rb +3 -1
  104. data/lib/alchemy/version.rb +1 -1
  105. data/lib/alchemy_cms.rb +2 -0
  106. data/lib/generators/alchemy/install/install_generator.rb +2 -1
  107. data/vendor/javascript/handlebars.min.js +4 -4
  108. data/vendor/javascript/shoelace.min.js +1419 -1323
  109. data/vendor/javascript/sortable.min.js +2 -2
  110. data/vendor/javascript/tinymce.min.js +1 -1
  111. metadata +35 -1
@@ -0,0 +1,2 @@
1
+ import"handlebars";import"jquery";import"@ungap/custom-elements";import{Turbo as e}from"@hotwired/turbo-rails";import"select2";import t from"@rails/ujs";import"keymaster";import"clipboard";import s from"flatpickr";import i from"sortablejs";import"tinymce";import{setDefaultAnimation as n,registerIconLibrary as r}from"shoelace";import l from"cropperjs";const o=/\./;function a(e){const t=c(),s=Alchemy.translations;return s?o.test(e)?function(e,t){const s=t.split(o),i=e[s[0]];return i&&i[s[1]]||t}(s,e):s[e]||e:(console.warn(`Translations for locale ${t} not found!`),e)}function c(){return document.documentElement.lang?document.documentElement.lang:"en"}function d(e,t=void 0){let s=a(e);return t?s.replace(/%\{.+\}/,t):s}async function h(){const e=c();"en"!==e&&(await import(`select2/${e}.js`),$.extend($.fn.select2.defaults,$.fn.select2.locales[e]))}const u=[];function m(e){return!(!$(e.target).is("input, textarea")&&"?"===String.fromCharCode(e.which))||(_("/admin/help",{title:Alchemy.t("help"),size:"400x492"}),!1)}function p(e=document){e instanceof jQuery&&(e=e[0]),e===document&&(document.removeEventListener("keypress",m),document.addEventListener("keypress",m),u.forEach((e=>key.unbind(e))));const t=e.querySelectorAll(".search_input_field"),s=e.querySelectorAll(".search_field_clear, .js_filter_field_clear");key("alt+f",(function(){return key.setScope("search"),t.forEach((e=>e.focus({focusVisible:!0}))),!1})),u.push("alt+f"),key("esc","search",(function(){s.forEach((e=>e.click())),t.forEach((e=>e.blur()))})),u.push("esc"),e.querySelectorAll("[data-alchemy-hotkey]").forEach((function(e){const t=e.dataset.alchemyHotkey;key(t,(()=>e.click())),u.push(t)}))}function g(e){const t=document.createElement("template");return t.innerHTML=e,t.content.children[0]}let y=class{constructor(e,t="currentColor"){this.size=e,this.color=t,this.spinner=void 0}get el(){return this.spinner}spin(e){return void 0===e&&(e=document.body),this.spinner=g(`<alchemy-spinner size="${this.size}" color="${this.color}"></alchemy-spinner>`),e.append(this.spinner),this}stop(){this.spinner&&(this.spinner.remove(),this.spinner=void 0)}};const f=[],v={header_height:36,size:"400x300",padding:!0,title:"",modal:!0,overflow:"visible",ready:()=>{},closed:()=>{}};class b{constructor(e,t={}){this.url=e,this.options={...v,...t},this.$document=$(document),this.$window=$(window),this.$body=$("body");const s=this.options.size.split("x");this.width=parseInt(s[0],10),this.height=parseInt(s[1],10),this.build(),this.resize()}open(){this.dialog.trigger("Alchemy.DialogOpen"),this.bind_close_events(),window.requestAnimationFrame((()=>{if(this.dialog_container.addClass("open"),null!=this.overlay)return this.overlay.addClass("open")})),this.$body.addClass("prevent-scrolling"),f.push(this),this.load()}close(){return this.dialog.trigger("DialogClose.Alchemy"),this.$document.off("keydown"),this.dialog_container.removeClass("open"),null!=this.overlay&&this.overlay.removeClass("open"),this.$document.on("webkitTransitionEnd transitionend oTransitionEnd",(()=>{if(this.$document.off("webkitTransitionEnd transitionend oTransitionEnd"),this.dialog_container.remove(),null!=this.overlay&&this.overlay.remove(),this.$body.removeClass("prevent-scrolling"),f.pop(this),null!=this.options.closed)return this.options.closed()})),!0}load(){this.show_spinner(),$.get(this.url,(e=>{this.replace(e)})).fail((e=>{this.show_error(e)}))}reload(){this.dialog_body.empty(),this.load()}replace(e){this.remove_spinner(),this.dialog_body.hide(),this.dialog_body.html(e),this.init(),this.dialog[0].dispatchEvent(new CustomEvent("DialogReady.Alchemy",{bubbles:!0,detail:{body:this.dialog_body[0]}})),null!=this.options.ready&&this.options.ready(this.dialog_body),this.dialog_body.show()}show_spinner(){this.spinner=new y("medium"),this.spinner.spin(this.dialog_body[0])}remove_spinner(){this.spinner.stop()}init(){p(this.dialog_body),this.watch_remote_forms()}watch_remote_forms(){const e=$('[data-remote="true"]',this.dialog_body);e.on("ajax:success",(e=>{const t=e.detail[2];t.getResponseHeader("Content-Type").match(/javascript/)||(this.dialog_body.html(t.responseText),this.init())})),e.on("ajax:error",(e=>{const t=e.detail[1],s=e.detail[2];this.show_error(s,t)}))}show_error(e,t){if(422===e.status)return this.dialog_body.html(e.responseText),void this.init();const{error_body:s,error_header:i,error_type:n}=this.error_messages(e,t),r=$(`<alchemy-message type="${n}">\n <h1>${i}</h1>\n <p>${s}</p>\n </alchemy-message>`);this.dialog_body.html(r)}error_messages(e,t){let s,i,n="warning";switch(e.status){case 0:i="The server does not respond.",s="Please check server and try again.";break;case 403:i="You are not authorized!",s="Please close this window.";break;default:n="error",t?(i=t,console.error(e.responseText)):i=`${e.statusText} (${e.status})`,s="Please check log and try again."}return{error_header:i,error_body:s,error_type:n}}bind_close_events(){this.close_button.on("click",(()=>{this.close()})),this.dialog_container.addClass("closable").on("click",(e=>e.target!==this.dialog_container.get(0)||(this.close(),!1))),this.$document.keydown((e=>27!==e.which||(this.close(),!1)))}build(){this.dialog_container=$('<div class="alchemy-dialog-container" />'),this.dialog=$('<div class="alchemy-dialog" />'),this.dialog_body=$('<div class="alchemy-dialog-body" />'),this.dialog_header=$('<div class="alchemy-dialog-header" />'),this.dialog_title=$('<div class="alchemy-dialog-title" />'),this.close_button=$('<button class="alchemy-dialog-close"><alchemy-icon name="close"></alchemy-icon></button>'),this.dialog_title.text(this.options.title),this.dialog_header.append(this.dialog_title),this.dialog_header.append(this.close_button),this.dialog.append(this.dialog_header),this.dialog.append(this.dialog_body),this.dialog_container.append(this.dialog),this.options.modal&&this.dialog.addClass("modal"),this.options.padding&&this.dialog_body.addClass("padded"),this.options.modal&&(this.overlay=$('<div class="alchemy-dialog-overlay" />'),this.$body.append(this.overlay)),this.$body.append(this.dialog_container)}resize(){const{width:e,height:t}=this.getSize();this.dialog.css({width:e,"min-height":t,overflow:this.options.overflow}),"hidden"===this.options.overflow?this.dialog_body.css({height:t,overflow:"auto"}):this.dialog_body.css({"min-height":t,overflow:"visible"})}getSize(){const e=this.options.padding?16:0,t=this.$window.width(),s=this.$window.height();let i=this.width,n=this.height;return i>=t&&(i=t-e),n>=s&&(n=s-e-v.header_height),{width:i,height:n}}}function E(){const{length:e}=f;if(0!==e)return f[e-1]}function w(e){const t=E();if(null!=t)return t.options.closed=e,t.close()}function _(e,t){if(!e)throw"No url given! Please provide an url.";new b(e,t).open()}class k{constructor(e,t={}){this.message=e,this.options={...{size:"300x100",title:d("Please confirm"),ok_label:d("Yes"),cancel_label:d("No"),on_ok(){}},...t},this.#e(),this.#t()}open(){requestAnimationFrame((()=>{this.dialog.show()}))}#e(){const e=this.options.size.split("x")[0];this.dialog=g(`\n <sl-dialog label="${this.options.title}" style="--width: ${e}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 `),document.body.append(this.dialog)}#t(){this.cancelButton.addEventListener("click",(e=>{e.preventDefault(),this.options.on_cancel(),this.dialog.hide()})),this.okButton.addEventListener("click",(e=>{e.preventDefault(),this.options.on_ok(),this.dialog.hide()})),this.dialog.addEventListener("sl-request-close",(e=>{"overlay"===e.detail.source&&(this.options.on_cancel(),e.preventDefault())})),this.dialog.addEventListener("sl-after-hide",(()=>{this.dialog.remove()}))}get cancelButton(){return this.dialog.querySelector("button[type=reset]")}get okButton(){return this.dialog.querySelector("button[type=submit]")}}function L(e,t={}){return new Promise((s=>{new k(e,{...t,on_ok(){s(!0)},on_cancel(){s(!1)}}).open()}))}function S(e=!0){document.querySelector("alchemy-overlay").show=!!e}function C(e){let t=()=>{};$(e).is("form")?t=function(){const t=$(`<form action="${e.action}" method="POST" style="display: none" />`);t.append($(e).find("input")),t.appendTo("body"),S(),t.trigger("submit")}:$(e).is("a")&&(t=()=>Turbo.visit(e.pathname));return!(document.querySelectorAll("alchemy-element-editor.dirty").length>0)||(L(d("page_dirty_notice"),{title:d("warning"),ok_label:d("ok"),cancel_label:d("cancel")}).then((e=>{e&&(window.onbeforeunload=void 0,t())})),!1)}var x={checkPageDirtyness:C,PageLeaveObserver:function(){document.querySelectorAll("#main_navi a").forEach((e=>{e.addEventListener("click",(e=>{C(e.currentTarget)||e.preventDefault()}))}))}};function T(e){const t=document.getElementById("fixed-elements"),s=`fixed-element-${e}`;t.querySelector(`sl-tab[panel="${s}"]`).remove(),t.querySelector(`sl-tab-panel[name="${s}"]`).remove(),t.show("main-content-elements")}var A=Object.freeze({__proto__:null,createTab:function(e,t){const s=document.getElementById("fixed-elements"),i=`fixed-element-${e}`,n=`<sl-tab slot="nav" panel="${i}">${t}</sl-tab>`,r=`<sl-tab-panel name="${i}" style="--padding: 0" />`;s.innerHTML+=n+r,window.requestAnimationFrame((function(){s.show(i)}))},removeTab:T});function F(e,t="notice"){!function(e,t){const s=document.getElementById("flash_notices"),i=g(`\n <alchemy-message type="${t}" dismissable>\n ${e}\n </alchemy-message>\n `);s.append(i)}(e,t)}const q=/#[\w.~-]+$/;class I extends HTMLIFrameElement{#s;#i;#n;#r;constructor(){super(),this.addEventListener("load",this),this.#r=this.#l.bind(this)}handleEvent(e){"load"===e.type&&(this.#o(),this.#a(),this.#s?.call(this,e))}#l(e){"Alchemy.previewReady"===e.data.message&&(this.#o(),this.#a(),this.#s?.call(this,e))}connectedCallback(){let e=this.url;this.#c(),window.addEventListener("message",this.#r),window.localStorage.getItem("alchemy-preview-url")&&(e=window.localStorage.getItem("alchemy-preview-url"),this.previewUrlSelect.value=e),this.refresh(e)}disconnectedCallback(){key.unbind("alt+r"),window.removeEventListener("message",this.#r)}postMessage(e){this.contentWindow.postMessage(e,"*")}resize(e){this.style.width=`${e}px`}refresh(e){return this.#d(),this.src=e||this.url,this.#o(),this.#n=setTimeout((()=>{this.#a(),F(d("Preview failed to load"),"warning")}),5e3),new Promise((e=>{this.#s=e}))}set isDragged(e){this.style.transitionProperty=e?"none":null,this.style.pointerEvents=e?"none":null}#c(){this.reloadButton?.addEventListener("click",(e=>{e.preventDefault(),this.refresh()})),key("alt+r",(()=>this.refresh())),this.sizeSelect.addEventListener("change",(e=>{const t=e.target.value;""===t?this.style.width=null:this.resize(t)})),this.previewUrlSelect?.addEventListener("change",(e=>{const t=e.target.value;window.localStorage.setItem("alchemy-preview-url",t),this.refresh(t)}))}#d(){this.reloadButton.innerHTML.includes("alchemy-spinner")||(this.#i=this.reloadButton.innerHTML),this.reloadButton.innerHTML='<alchemy-spinner size="small"></alchemy-spinner>'}#a(){this.reloadButton.innerHTML=this.#i}#o(){this.#n&&(clearTimeout(this.#n),this.#n=null)}get url(){return this.getAttribute("url")}get sizeSelect(){return document.querySelector("select#preview_size")}get previewUrlSelect(){return document.querySelector("select#preview_url")}get reloadButton(){return document.querySelector("#reload_preview_button")}}function B(){document.getElementById("alchemy_preview_window").refresh()}customElements.define("alchemy-preview-window",I,{extends:"iframe"});class M{static updateIcon(e,t=!1){const s=document.querySelector(`[data-ingredient-id="${e}"]`);if(s){s.querySelector(".edit-ingredient-anchor-link alchemy-icon").setAttribute("icon-style",t?"fill":"line")}}}class z extends HTMLElement{constructor(){super(),this.actions={closeCurrentDialog:w,reloadPreview:B,removeFixedElement:T,updateAnchorIcon:M.updateIcon,hidePleaseWaitOverlay(){S(!1)}}}connectedCallback(){const e=this.actions[this.name];e?e(...this.params):console.error(`Unknown Alchemy action: ${this.name}`),this.remove()}get name(){return this.getAttribute("name")}get params(){return this.hasAttribute("params")?JSON.parse(this.getAttribute("params")):[]}}customElements.define("alchemy-action",z);class H extends HTMLElement{static properties={};static get observedAttributes(){return Object.keys(this.properties)}constructor(e={}){super(),this.options=e,this.changeComponent=!0,this.initialContent=this.innerHTML}async connectedCallback(){Object.keys(this.constructor.properties).forEach((e=>{this[e]=this.options[e]??this.constructor.properties[e].default})),this.getAttributeNames().forEach((e=>this._updateFromAttribute(e))),this._updateComponent(),await this.connected()}disconnectedCallback(){this.disconnected()}attributeChangedCallback(e){this._updateFromAttribute(e),this._updateComponent()}async connected(){}disconnected(){}render(){return this.initialContent}afterRender(){}dispatchCustomEvent(e,t={}){const s=new CustomEvent(`Alchemy.${e}`,{bubbles:!0,detail:t});this.dispatchEvent(s)}_updateComponent(){this.changeComponent&&(this.innerHTML=this.render(),this.changeComponent=!1,this.afterRender())}_updateFromAttribute(e){const t=this.getAttribute(e),s=e.split(/-|_/).reduce(((e,t)=>e+t.charAt(0).toUpperCase()+t.slice(1)));const i=!!(0===t.length||"true"===t)||t;this[s]!==i&&(this[s]=i,this.changeComponent=!0)}}function P(e,t){return e.replace(new RegExp(t,"gi"),(e=>`<em>${e}</em>`))}class D extends H{static properties={allowClear:{default:!1},selection:{default:void 0},placeholder:{default:""},queryParams:{default:"{}"},url:{default:""}};async connected(){await h(),this.input.classList.add("alchemy_selectbox"),$(this.input).select2(this.select2Config).on("select2-open",(e=>{this.onOpen(e)})).on("change",(e=>{this.onChange(e)}))}onChange(e){this.dispatchCustomEvent("RemoteSelect.Change",{removed:e.removed,added:e.added})}onOpen(e){setTimeout((()=>{document.querySelector("#select2-drop .select2-input").focus()}),100)}get input(){return this.getElementsByTagName("input")[0]}get select2Config(){return{placeholder:this.placeholder,allowClear:this.allowClear,initSelection:(e,t)=>{this.selection&&t(JSON.parse(this.selection))},ajax:this.ajaxConfig,formatSelection:e=>this._renderResult(e),formatResult:(e,t,s)=>this._renderListEntry(e,s.term)}}get ajaxConfig(){return{url:this.url,datatype:"json",quietMillis:300,data:(e,t)=>this._searchQuery(e,t),results:e=>this._parseResponse(e)}}_searchQuery(e,t){return{q:{name_cont:e,...JSON.parse(this.queryParams)},page:t}}_parseResponse(e){const t=e.meta;return{results:e.data,more:t.page*t.per_page<t.total_count}}_renderResult(){throw new Error("You need to define a _renderResult function on your sub class!")}_renderListEntry(){throw new Error("You need to define a _renderListEntry function on your sub class!")}_hightlightTerm(e,t){return P(e,t)}}customElements.define("alchemy-attachment-select",class extends D{_renderResult(e){return this._renderListEntry(e)}_renderListEntry(e,t){return`\n <div class="attachment-select--attachment">\n <alchemy-icon name="${e.icon_css_class}"></alchemy-icon>\n <span class="attachment-select--attachment-name">${this._hightlightTerm(e.name,t)}</span>\n </div>\n `}});class N extends HTMLElement{connectedCallback(){$(this).on("change",(function(e){const t=new Event("submit",{bubbles:!0,cancelable:!0});return e.target.form.dispatchEvent(t),!1}))}}customElements.define("alchemy-auto-submit",N);class O extends HTMLButtonElement{connectedCallback(){this.form?(this.form.addEventListener("submit",this),"true"==this.form.dataset.remote&&this.form.addEventListener("ajax:complete",this),this.form.addEventListener("turbo:submit-end",this)):console.warn("No form for button found!",this)}handleEvent(e){switch(e.type){case"submit":"disabled"===this.getAttribute("disabled")?(e.preventDefault(),e.stopPropagation()):this.disable();break;case"ajax:complete":case"turbo:submit-end":this.enable()}}disable(){const e=new y("small"),t=this.getBoundingClientRect();this.dataset.initialButtonText=this.innerHTML,this.setAttribute("disabled","disabled"),this.setAttribute("tabindex","-1"),this.classList.add("disabled"),this.style.width=`${t.width}px`,this.style.height=`${t.height}px`,this.innerHTML="&nbsp;",e.spin(this)}enable(){this.classList.remove("disabled"),this.removeAttribute("disabled"),this.removeAttribute("tabindex"),this.style.width=null,this.style.height=null,this.innerHTML=this.dataset.initialButtonText}}customElements.define("alchemy-button",O,{extends:"button"});customElements.define("alchemy-char-counter",class extends H{static properties={maxChars:{default:60}};connected(){this.translation=d("allowed_chars",this.maxChars),this.formField=this.getFormField(),this.formField&&(this.createDisplayElement(),this.countCharacters(),this.formField.addEventListener("keyup",(()=>this.countCharacters())))}getFormField(){const e=this.querySelectorAll("input, textarea");return e.length>0?e[0]:void 0}createDisplayElement(){this.display=document.createElement("small"),this.display.className="alchemy-char-counter",this.formField.after(this.display)}countCharacters(){const e=this.formField.value.length;this.display.textContent=`${e} ${this.translation}`,this.display.classList.toggle("too-long",e>this.maxChars)}});class R extends HTMLElement{constructor(){super(),this.innerHTML='\n <alchemy-icon name="clipboard"></alchemy-icon>\n ',this.clipboard=new ClipboardJS(this,{text:()=>this.getAttribute("content")}),this.clipboard.on("success",(()=>{F(this.getAttribute("success-text"))}))}disconnectedCallback(){this.clipboard.destroy()}}customElements.define("alchemy-clipboard-button",R);const U=e=>{const t=e.element[0],s=t.dataset.swatch||t.value;return`\n <div class="select-color-option">\n ${"custom_color"===t.value?'<alchemy-icon name="palette"></alchemy-icon>':`<span class="color-indicator" style="--color: ${s}"></span>`}\n <span>${e.text}</span>\n </div>`};class j extends HTMLElement{connectedCallback(){this.select?(this.#h(),$(this.select).on("change",(e=>this.#u("custom_color"===e.val)))):(this.colorInput?.addEventListener("input",this),this.textInput?.addEventListener("input",this),this.#u(!0))}handleEvent(e){switch(e.target){case this.colorInput:this.textInput.value=this.colorInput.value;break;case this.textInput:this.colorInput.value=this.textInput.value}}disconnectedCallback(){this.colorInput?.removeEventListener("input",this),this.textInput?.removeEventListener("input",this)}#h(){this.select.classList.add("alchemy_selectbox");const e={minimumResultsForSearch:10,formatResult:U,formatSelection:U};$(this.select).select2(e)}#u(e=!0){this.colorInput.disabled=!e}get colorInput(){return this.querySelector("input[type='color']")}get textInput(){return this.querySelector("input[type='text']")}get select(){return this.querySelector("select")}}customElements.define("alchemy-color-select",j);const W=c();customElements.define("alchemy-datepicker",class extends H{static properties={inputType:{default:"date"}};constructor(){super(),this.flatpickr=void 0}async connected(){"en"!==W&&await import(`flatpickr/${W}.js`),this.flatpickr=s(this.inputField,this.flatpickrOptions)}disconnected(){this.flatpickr.destroy()}get flatpickrOptions(){const e=/time/.test(this.inputType),t={locale:W.slice(0,2),altInput:!0,altFormat:d(`formats.${this.inputType}`),altInputClass:"flatpickr-input",enableTime:e,noCalendar:"time"===this.inputType,time_24hr:d("formats.time_24hr"),onValueUpdate(e,t,s){s.element.closest("alchemy-element-editor")?.setDirty(this.inputField)}};return e&&(t.dateFormat="Z"),t}get inputField(){return this.querySelector("input")}});class J extends HTMLAnchorElement{constructor(){super(),this.addEventListener("click",this)}handleEvent(e){this.disabled||this.openDialog(),e.preventDefault()}openDialog(){this.dialog=new b(this.getAttribute("href"),this.dialogOptions),this.dialog.open()}get dialogOptions(){return this.dataset.dialogOptions?JSON.parse(this.dataset.dialogOptions):{}}get disabled(){return this.classList.contains("disabled")}}customElements.define("alchemy-dialog-link",J,{extends:"a"});const V="application/json",X="text/vnd.turbo-stream.html";function Q(e){return"get"===e.toLowerCase()}function Y(e,t,s){const i=function(e){return{"Content-Type":"application/json; charset=utf-8",Accept:e,"X-Requested-With":"XMLHttpRequest","X-CSRF-Token":K()}}(s),n={method:e,headers:i};return t&&!Q(e)&&(n.body=JSON.stringify(t)),n}function K(){return document.querySelector('meta[name="csrf-token"]').attributes.content.textContent}function G(e,t){return te("GET",e,t)}function Z(e,t,s){return te("PATCH",e,t,s)}function ee(e,t,s=V){return te("POST",e,t,s)}async function te(e,t,s,i=V){const n=await fetch(function(e,t,s){const i=new URL(window.location.origin+e);return t&&Q(s)&&(i.search=new URLSearchParams(t).toString()),i.toString()}(t,s,e),Y(e,s,i)),r=n.headers.get("content-type"),l=r?.includes(V),o=r?.includes(X);let a=null;if(l?a=await n.json():o&&(a=await n.text(),"undefined"!=typeof Turbo&&Turbo.renderStreamMessage(a)),n.ok)return{data:a,status:n.status};throw a||new Error("An error occurred during the transaction")}class se extends HTMLElement{dataItem(e){return{id:`#${e}`,text:`#${e}`}}get selectElement(){return this.querySelector('select[is="alchemy-select"]')}}customElements.define("alchemy-dom-id-api-select",class extends se{#m=void 0;connectedCallback(){this.page=this.getAttribute("page")}async#p(){const e=(await G(Alchemy.routes.api_ingredients_path,{page_id:this.#m})).data.ingredients.filter((e=>e.data?.dom_id)).map((e=>this.dataItem(e.data.dom_id))),t=e.length>0?d("None"):d("No anchors found");this.selectElement.setOptions(e,t),this.selectElement.enable()}#g(){requestAnimationFrame((()=>{this.selectElement.disable(),this.selectElement.setOptions([],d("Select a page first"))}))}set page(e){this.#m=e,e?this.#p():this.#g()}}),customElements.define("alchemy-dom-id-preview-select",class extends se{connectedCallback(){requestAnimationFrame((()=>{const e=document.getElementById("alchemy_preview_window"),t=e.contentDocument?.querySelectorAll("[id]")||[];if(t.length>0){const e=Array.from(t).map((e=>this.dataItem(e.id)));this.selectElement.setOptions(e,d("None"))}}))}});class ie extends HTMLElement{#y;connectedCallback(){this.#y=this.scheduleButton.getAttribute("variant"),this.publishButton.addEventListener("click",this),this.dropdown.addEventListener("sl-show",this),this.dropdown.addEventListener("sl-hide",this)}disconnectedCallback(){this.publishButton.removeEventListener("click",this),this.dropdown.removeEventListener("sl-show",this),this.dropdown.removeEventListener("sl-hide",this)}handleEvent(e){switch(e.type){case"click":this.publishButton.loading=!0;break;case"sl-show":this.scheduleButton.setAttribute("variant","primary");break;case"sl-hide":this.scheduleButton.setAttribute("variant",this.#y)}}get publishButton(){return this.querySelector("sl-button[type='submit']")}get dropdown(){return this.querySelector("sl-dropdown")}get scheduleButton(){return this.querySelector("sl-button[slot='trigger']")}}customElements.define("alchemy-publish-element-button",ie);class ne extends HTMLElement{constructor(){super(),this.button?.addEventListener("click",this)}async handleEvent(){if(await L(this.message)){const e=await te("DELETE",this.url);this.#f(e.data)}}#f(e){const t=this.closest("alchemy-element-editor");t.addEventListener("transitionend",(()=>{t.fixed&&T(t.elementId),t.remove()})),t.classList.add("dismiss"),F(e.message),e.pageHasUnpublishedChanges&&re(e),B()}get url(){return this.getAttribute("href")}get message(){return this.getAttribute("message")}get button(){return this.querySelector("button")}}function re(e){document.dispatchEvent(new CustomEvent("alchemy:page-dirty",{detail:{tooltip:e.publishButtonTooltip}}))}customElements.define("alchemy-delete-element-button",ne);class le extends HTMLElement{constructor(){super(),this.addEventListener("click",this),this.addEventListener("alchemy:element-update-title",this),this.addEventListener("ajax:complete",this),$(this.form).on("change",this.onChange),this.header?.addEventListener("dblclick",(()=>{this.toggle()})),this.toggleButton?.addEventListener("click",(e=>{e.target.closest("alchemy-element-editor")===this&&this.toggle()}))}connectedCallback(){this.classList.contains("ui-sortable-placeholder")||this.hasAttribute("created")&&(this.focusElement(),this.previewWindow?.refresh().then((()=>{this.focusElementPreview()})),this.removeAttribute("created"))}handleEvent(e){switch(e.type){case"click":e.target.closest("alchemy-element-editor")===this&&this.onClickElement();break;case"ajax:complete":if(e.target===this.body){const t=e.detail[0];e.stopPropagation(),this.onSaveElement(t)}break;case"alchemy:element-update-title":this.hasEditors||e.target!=this.firstChild||this.setTitle(e.detail.title)}}onChange(e){const t=e.target;if(!t.classList.contains("nested-elements"))return this.closest("alchemy-element-editor").setDirty(t),e.stopPropagation(),!1}async focusElement(){document.querySelector("#fixed-elements")&&await this.selectTabForElement(),await this.expand(),this.selectElement(!0)}focusElementPreview(){this.previewWindow?.postMessage({message:"Alchemy.focusElement",element_id:this.elementId})}onClickElement(){this.selectElement(),this.focusElementPreview()}onSaveElement(e){const t=JSON.parse(e.responseText);if(this.setClean(),422===e.status){const e=t.warning;t.ingredientsWithErrors.forEach((e=>{const t=this.querySelector(`[data-ingredient-id="${e.id}"]`),s=g(`<small class="error">${e.errorMessage}</small>`);t?.appendChild(s),t?.classList.add("validation_failed")})),F(e,"warn"),this.elementErrors.classList.remove("hidden")}else F(t.notice),this.previewWindow?.refresh().then((()=>{this.focusElementPreview()})),this.updateTitle(t.previewText),t.ingredientAnchors.forEach((e=>{M.updateIcon(e.ingredientId,e.active)})),t.pageHasUnpublishedChanges&&re(t)}scrollToElement(){setTimeout((()=>{this.scrollIntoView({behavior:"smooth"})}),50)}selectElement(e=!1){document.querySelectorAll("alchemy-element-editor.selected").forEach((e=>{e.classList.remove("selected")})),window.requestAnimationFrame((()=>{this.classList.add("selected")})),e&&this.scrollToElement()}selectTabForElement(){return new Promise(((e,t)=>{const s=document.querySelector("#fixed-elements"),i=this.closest("sl-tab-panel");s&&i?(s.show(i.getAttribute("name")),e()):t(new Error("No tabs present"))}))}setClean(){this.dirty=!1,window.onbeforeunload=null,this.elementErrors.classList.add("hidden"),this.hasEditors&&this.body.querySelectorAll(".ingredient-editor").forEach((e=>{e.classList.remove("dirty","validation_failed"),e.querySelectorAll("small.error").forEach((e=>e.remove()))}))}setDirty(e){this.hasEditors&&(this.dirty=!0,window.onbeforeunload||(window.onbeforeunload=e=>e.preventDefault()),e?.closest(".ingredient-editor")?.classList.add("dirty"))}setTitle(e){this.querySelector(".element-header .preview_text_quote").textContent=e}async toggle(){this.collapsed?await this.expand():await this.collapse()}collapse(){if(this.collapsed||this.compact||this.fixed)return Promise.resolve("Element is already collapsed.");const e=new Alchemy.Spinner("small");return e.spin(this.toggleButton),this.toggleIcon?.classList?.add("hidden"),ee(Alchemy.routes.collapse_admin_element_path(this.elementId)).then((e=>{const t=e.data;if(this.collapsed=!0,this.toggleButton?.setAttribute("title",t.title),t.nestedElementIds.length){const e=t.nestedElementIds.map((e=>`#element_${e}`)).join(", ");this.querySelectorAll(e).forEach((e=>{e.collapsed=!0,e.toggleButton?.setAttribute("title",t.title)}))}})).catch((e=>{F(e.message,"error"),console.error(e)})).finally((()=>{this.toggleIcon?.classList?.remove("hidden"),e.stop()}))}expand(){if(this.expanded&&!this.compact)return Promise.resolve("Element is already expanded.");if(this.compact&&this.parentElementEditor)return this.parentElementEditor.expand();{const e=new Alchemy.Spinner("small");return e.spin(this.toggleButton),this.toggleIcon?.classList.add("hidden"),new Promise(((t,s)=>{ee(Alchemy.routes.expand_admin_element_path(this.elementId)).then((e=>{const s=e.data;if(s.parentElementIds.length){const e=s.parentElementIds.map((e=>`#element_${e}`)).join(", ");document.querySelectorAll(e).forEach((e=>{e.collapsed=!1,e.toggleButton?.setAttribute("title",s.title)}))}this.collapsed=!1,this.toggleButton?.setAttribute("title",s.title),t()})).catch((e=>{F(e.message,"error"),console.error(e),s(e)})).finally((()=>{this.toggleIcon?.classList?.remove("hidden"),e.stop()}))}))}}updateTitle(e){this.setTitle(e),this.dispatchEvent(new CustomEvent("alchemy:element-update-title",{bubbles:!0,detail:{title:e}}))}set published(e){e?this.classList.remove("element-hidden"):this.classList.add("element-hidden")}get published(){return!this.classList.contains("hidden")}get compact(){return null!==this.getAttribute("compact")}get fixed(){return null!==this.getAttribute("fixed")}set collapsed(e){this.classList.toggle("folded",e),this.classList.toggle("expanded",!e),this.toggleIcon&&(this.toggleIcon.name=e?"arrow-left-s":"arrow-down-s")}get collapsed(){return this.classList.contains("folded")}get expanded(){return!this.collapsed}set dirty(e){this.classList.toggle("dirty",e)}get dirty(){return this.classList.contains("dirty")}get header(){return this.querySelector(".element-header")}get body(){return this.querySelector(this.bodySelector)}get bodySelector(){return`#${this.id} > .element-body`}get footer(){return this.querySelector(`#${this.id} > .element-footer`)}get toggleButton(){return this.querySelector(".element-toggle")}get toggleIcon(){return this.toggleButton?.querySelector("alchemy-icon")}get elementErrors(){return this.body.querySelector(".element_errors")}get elementId(){return this.dataset.elementId}get elementName(){return this.dataset.elementName}get hasEditors(){return!!this.body?.querySelector(".element-ingredient-editors")}get hasChildren(){return!!this.querySelector(".nested-elements")}get firstChild(){return this.querySelector("alchemy-element-editor")}get form(){return this.querySelector("form.element-body")}get parentElementEditor(){return this.parentElement?.closest("alchemy-element-editor")}get previewWindow(){return document.getElementById("alchemy_preview_window")}}customElements.define("alchemy-element-editor",le);const oe=e=>`\n <div class="element-select-name">\n ${e.icon}<span>${e.text}</span>\n </div>\n `;class ae extends HTMLElement{constructor(){super()}connectedCallback(){const e=this.options,t={minimumResultsForSearch:3,dropdownAutoWidth:!0,data:()=>({results:e}),formatResult:(e,t,s)=>{let i;return""===e.id?e.text:(i=""!==s.term?P(e.text,s.term):e.text,((e,t,s)=>{const i=s?`<div class="element-select-description">${s}</div>`:"";return`\n <div class="element-select-item">\n ${oe({icon:e,text:t})}\n ${i}\n </div>\n `})(e.icon,i,e.hint))},formatSelection:oe,placeholder:this.placeholder};$(this.inputField).select2(t)}get options(){return JSON.parse(this.getAttribute("options"))}get placeholder(){return this.getAttribute("placeholder")}get inputField(){return this.querySelector("input")}}customElements.define("alchemy-element-select",ae);class ce extends HTMLElement{#v=!0;#b=null;constructor(){super(),this.#c()}connectedCallback(){this.toggleButton?.addEventListener("click",(e=>{e.preventDefault(),this.toggle()})),window.location.hash&&this.focusElementEditor(window.location.hash),this.resize()}collapseAllElements(){this.querySelectorAll("alchemy-element-editor:not([compact]):not([fixed])").forEach((e=>e.collapse()))}toggle(){this.#v?this.hide():this.show()}show(){document.body.classList.add("elements-window-visible"),this.#v=!0,this.toggleButton.closest("sl-tooltip").content=Alchemy.t("Hide elements"),this.toggleButton.querySelector("alchemy-icon").setAttribute("name","menu-unfold"),this.resize()}hide(){document.body.classList.remove("elements-window-visible"),document.body.style.removeProperty("--elements-window-width"),this.#v=!1,this.toggleButton.closest("sl-tooltip").content=Alchemy.t("Show elements"),this.toggleButton.querySelector("alchemy-icon").setAttribute("name","menu-fold")}resize(e){void 0===e&&(e=this.widthFromCookie),e&&(document.body.style.setProperty("--elements-window-width",`${e}px`),document.cookie=`alchemy-elements-window-width=${e}; SameSite=Lax; Path=/;`)}focusElementEditor(e){const t=document.querySelector(e);t instanceof le&&t.focusElement()&&t.focusElementPreview()}get collapseButton(){return this.querySelector("#collapse-all-elements-button")}get toggleButton(){return document.querySelector("#element_window_button")}get previewWindow(){return document.getElementById("alchemy_preview_window")}get turboFrame(){return this.#b||(this.#b=this.closest("turbo-frame")),this.#b}get widthFromCookie(){return document.cookie.split("; ").find((e=>e.startsWith("alchemy-elements-window-width=")))?.split("=")[1]}set isDragged(e){this.turboFrame.style.transitionProperty=e?"none":null,this.turboFrame.style.pointerEvents=e?"none":null}#c(){this.collapseButton?.addEventListener("click",(()=>{this.collapseAllElements()})),window.addEventListener("message",(e=>{const t=e.data;if("Alchemy.focusElementEditor"==t?.message){const e=document.getElementById(`element_${t.element_id}`);this.show(),e?.focusElement()}})),document.body.addEventListener("click",(e=>{e.target.closest("alchemy-element-editor")||(this.querySelectorAll("alchemy-element-editor").forEach((e=>{e.classList.remove("selected")})),this.previewWindow?.postMessage({message:"Alchemy.blurElements"}))}))}}customElements.define("alchemy-elements-window",ce);class de extends HTMLElement{#E=!1;#w=null;#_=null;constructor(){super(),this.addEventListener("mousedown",this),window.addEventListener("mousemove",this),window.addEventListener("mouseup",this)}handleEvent(e){switch(e.type){case"mousedown":e.stopPropagation(),this.onMouseDown();break;case"mouseup":this.onMouseUp();break;case"mousemove":this.#E&&this.onDrag(e.pageX)}}onMouseDown(){this.#E=!0,this.elementsWindow.isDragged=!0,this.previewWindow.isDragged=!0,this.classList.add("is-dragged")}onMouseUp(){this.#E=!1,this.elementsWindow.isDragged=!1,this.previewWindow.isDragged=!1,this.classList.remove("is-dragged")}onDrag(e){const t=window.innerWidth-e;this.elementsWindow.resize(t)}get elementsWindow(){return this.#w||(this.#w=document.querySelector("alchemy-elements-window")),this.#w}get previewWindow(){return this.#_||(this.#_=document.getElementById("alchemy_preview_window")),this.#_}}customElements.define("alchemy-elements-window-handle",de);class he extends HTMLElement{constructor(){super(),this.deleteLink=this.querySelector(".remove_file_link"),this.fileIcon=this.querySelector(".file_icon"),this.fileName=this.querySelector(".file_name"),this.formFieldId=this.deleteLink?.dataset.formFieldId,this.formField=this.querySelector(`#${this.formFieldId}`),this.deleteLink?.addEventListener("click",this)}handleEvent(e){"click"===e.type&&this.removeFile(),e.stopPropagation()}removeFile(){this.formField.value="",this.fileIcon.innerHTML="",this.fileName.innerHTML="",this.deleteLink?.classList.add("hidden"),this.closest("alchemy-element-editor").setDirty(this.formField)}}customElements.define("alchemy-file-editor",he);class ue extends HTMLElement{#k;constructor(){super(),this.#c()}#c(){this.hotkey&&key(this.hotkey,(()=>(this.filterField.focus(),!1))),this.filterField.addEventListener("keyup",(()=>{clearTimeout(this.#k),this.#k=setTimeout((()=>{const e=this.filterField.value;this.clearButton.style.visibility=e?"visible":"hidden",this.filter(e)}),this.debounceTime)})),this.clearButton.addEventListener("click",(e=>{e.preventDefault(),this.clear()})),this.filterField.addEventListener("focus",(()=>key.setScope("list_filter"))),key("esc","list_filter",(()=>{this.clear(),this.filterField.blur()}))}disconnectedCallback(){this.hotkey&&key.unbind(this.hotkey),key.unbind("esc","list_filter")}filter(e){""===e&&(this.clearButton.style.visibility="hidden");const t=[],s=new Set,i=e.toLowerCase();this.items.forEach((e=>{const n=e.getAttribute(this.nameAttribute)?.toLowerCase();if(-1!==n.indexOf(i)){t.push(e),s.add(e);let i=e.parentElement?.closest(this.itemsSelector);for(;i;)s.add(i),i=i.parentElement?.closest(this.itemsSelector)}})),this.items.forEach((e=>{e.classList.toggle("hidden",!s.has(e))})),1===t.length&&t[0].scrollIntoView({behavior:"smooth",block:"nearest"})}clear(){this.filterField.value="",this.clearButton.style.visibility="hidden",this.items.forEach((e=>e.classList.remove("hidden")))}get nameAttribute(){return this.getAttribute("name-attribute")||"name"}get clearButton(){return this.querySelector('button[type="button"]')}get filterField(){return this.querySelector('input[type="text"]')}get items(){return document.querySelectorAll(this.itemsSelector)}get itemsSelector(){return this.getAttribute("items-selector")}get debounceTime(){return parseInt(this.getAttribute("debounce-time"))||150}get hotkey(){return this.getAttribute("hotkey")}}customElements.define("alchemy-list-filter",ue);class me extends HTMLElement{#L;constructor(){super(),this.#L=this.innerHTML,(this.dismissable||"error"===this.type)&&this.addEventListener("click",this)}handleEvent(e){"click"===e.type&&this.dismiss()}connectedCallback(){this.innerHTML=`\n <alchemy-icon name="${this.iconName}"></alchemy-icon>\n ${this.dismissable&&"error"===this.type?'<alchemy-icon name="close"></alchemy-icon>':""}\n ${this.#L}\n `,this.dismissable&&"error"!==this.type&&setTimeout((()=>{this.dismiss()}),this.dismissDelay)}dismiss(){this.addEventListener("transitionend",(()=>this.remove())),this.classList.add("dismissed")}get dismissable(){return this.hasAttribute("dismissable")}get icon(){return this.getAttribute("icon")}get type(){return this.getAttribute("type")||"notice"}get dismissDelay(){return parseInt(this.noticesWrapper?.dataset.autoDismissDelay||5e3)}get iconName(){switch(this.icon||this.type){case"warning":case"warn":case"alert":return"alert";case"notice":return"check";case"info":case"hint":return"information";case"error":return"bug";default:return this.type}}get noticesWrapper(){return this.closest("#flash_notices")}}customElements.define("alchemy-message",me);class pe extends HTMLElement{connectedCallback(){F(this.message,this.getAttribute("type")||"notice"),this.remove()}get message(){return this.getAttribute("message")||this.innerHTML}}customElements.define("alchemy-growl",pe);class ge extends HTMLElement{static get observedAttributes(){return["name","size","icon-style"]}constructor(){super(),this.spriteUrl=document.querySelector('link[rel="preload"][as="image"]').getAttribute("href")}connectedCallback(){this.render()}attributeChangedCallback(){this.render()}render(){const e=this.size?` icon--${this.size}`:"";this.innerHTML=`<svg class="icon${e}"><use href="${this.spriteUrl}#ri-${this.iconName}${this.style}" /></svg>`}set name(e){this.setAttribute("name",e)}get iconName(){return this.getAttribute("name")}get size(){return this.getAttribute("size")}get style(){const e=this.getAttribute("icon-style");switch(e){case"none":return"";case null:return"-line";default:return`-${e}`}}}customElements.define("alchemy-icon",ge);class ye extends HTMLDetailsElement{#S="Alchemy.expanded_ingredient_groups";constructor(){super(),this.addEventListener("toggle",this),this.isInLocalStorage&&(this.open=!0)}handleEvent(){let e=this.localStorageItem;this.open?(this.toggleIcon.name="arrow-down-s",this.isInLocalStorage||e.push(this.id)):(this.toggleIcon.name="arrow-left-s",e=e.filter((e=>e!==this.id))),localStorage.setItem(this.#S,JSON.stringify(e))}get isInLocalStorage(){return this.localStorageItem.includes(this.id)}get localStorageItem(){const e=localStorage.getItem(this.#S);if(!e)return[];try{return JSON.parse(e)}catch(e){return console.error(e),[]}}get toggleIcon(){return this.querySelector("alchemy-icon")}}customElements.define("alchemy-ingredient-group",ye,{extends:"details"});class fe extends HTMLButtonElement{constructor(){super(),this.addEventListener("click",this),this.classList.add("icon_button"),this.setAttribute("type","button"),this.innerHTML='<alchemy-icon name="link" icon-style="m"></alchemy-icon>'}handleEvent(e){new Alchemy.LinkDialog({url:this.linkUrl,title:this.linkTitle,target:this.linkTarget,type:this.linkClass}).open().then((e=>this.setLink(e))),e.preventDefault()}setLink(e){""===e.url?(this.classList.remove("linked"),this.dispatchEvent(new CustomEvent("alchemy:unlink",{bubbles:!0}))):(this.classList.add("linked"),this.dispatchEvent(new CustomEvent("alchemy:link",{bubbles:!0,detail:e})))}get linkUrl(){return this.linkButtons.linkUrlField.value}get linkTitle(){return this.linkButtons.linkTitleField.value}get linkTarget(){return this.linkButtons.linkTargetField.value}get linkClass(){return this.linkButtons.linkClassField.value}get linkButtons(){return this.closest("alchemy-link-buttons")}}customElements.define("alchemy-link-button",fe,{extends:"button"});class ve extends HTMLButtonElement{constructor(){super(),this.addEventListener("click",this),this.classList.add("icon_button"),this.setAttribute("type","button"),this.linked=this.linked,this.innerHTML='<alchemy-icon name="link-unlink" icon-style="m"></alchemy-icon>'}handleEvent(e){this.linked&&(this.linked=!1,this.blur(),this.dispatchEvent(new CustomEvent("alchemy:unlink",{bubbles:!0}))),e.preventDefault()}set linked(e){e?(this.classList.replace("disabled","linked"),this.removeAttribute("tabindex")):(this.classList.replace("linked","disabled"),this.setAttribute("tabindex","-1"))}get linked(){return this.classList.contains("linked")}}customElements.define("alchemy-unlink-button",ve,{extends:"button"});class be extends HTMLElement{constructor(){super(),this.addEventListener("alchemy:link",this),this.addEventListener("alchemy:unlink",this)}handleEvent(e){switch(e.type){case"alchemy:link":this.setLink(e.detail);break;case"alchemy:unlink":this.removeLink()}e.stopPropagation()}setLink(e){this.linkUrlField.value=e.url,this.linkUrlField.dispatchEvent(new Event("change")),this.linkTitleField.value=e.title,this.linkClassField.value=e.type,this.linkTargetField.value=e.target,this.unlinkButton.linked=!0,this.setElementDirty()}removeLink(){this.linkUrlField.value="",this.linkUrlField.dispatchEvent(new Event("change")),this.linkTitleField.value="",this.linkClassField.value="",this.linkTargetField.value="",this.linkButton.classList.remove("linked"),this.unlinkButton.linked=!1,this.setElementDirty()}setElementDirty(){this.elementEditor.setDirty(this)}get linkButton(){return this.querySelector('[is="alchemy-link-button"]')}get unlinkButton(){return this.querySelector('[is="alchemy-unlink-button"]')}get ingredientEditor(){const e=this.dataset.ingredientId;return this.parentElement.closest(`[data-ingredient-id='${e}']`)}get elementEditor(){return this.closest("alchemy-element-editor")}get linkUrlField(){return this.ingredientEditor.querySelector("[data-link-value]")}get linkTitleField(){return this.ingredientEditor.querySelector("[data-link-title]")}get linkTargetField(){return this.ingredientEditor.querySelector("[data-link-target]")}get linkClassField(){return this.ingredientEditor.querySelector("[data-link-class]")}}customElements.define("alchemy-link-buttons",be);function Ee(e){let t=0===e?0:Math.floor(Math.log(e)/Math.log(1024));return t>3&&(t=3),(e/Math.pow(1024,t)).toFixed(2)+" "+["B","kB","MB","GB"][t]}customElements.define("alchemy-node-select",class extends D{_searchQuery(e,t){return{filter:{name_or_page_name_cont:e,...JSON.parse(this.queryParams)},page:t}}_renderResult(e){return this._renderListEntry(e)}_renderListEntry(e,t){const s=e.ancestors.map((e=>e.name)),i='<alchemy-icon name="arrow-right-s"></alchemy-icon>';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 ${s.length>0?s.join(i)+i:""}\n </span>\n <span class="node-select--node-name">\n ${this._hightlightTerm(e.name,t)}\n </span>\n </div>\n <div class="node-select--node-url">\n ${e.url||""}\n </div>\n </div>\n `}});class we extends H{constructor(){super(),this.file=null,this.request=null,this.progressEventLoaded=0,this.progressEventTotal=0,this.className="in-progress",this.valid=!0,this.value=0}initialize(e,t){this.file=e,this.request=t,this.progressEventTotal=e?e.size:0,this._validateFile(),this._addRequestEventListener()}render(){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="${d("Abort upload")}">\n <button class="icon_button" aria-label="${d("Abort upload")}">\n <alchemy-icon name="close"></alchemy-icon>\n </button>\n </sl-tooltip>\n `}afterRender(){if(this.querySelector("button").addEventListener("click",(()=>this.cancel())),this.file?.type.includes("image")){const e=new FileReader;e.readAsDataURL(this.file),e.addEventListener("load",(()=>{const t=new Image;t.src=e.result,this.prepend(t)}))}}cancel(){this.finished||(this.status="canceled",this.request?.abort(),this.dispatchCustomEvent("FileUpload.Change"))}_validateFile(){const e=Alchemy.uploader_defaults,t=e.file_size_limit*Math.pow(1024,2);let s;this.file?.size>t&&(s=d("Uploaded bytes exceed file size"));const i=this.file?.type.includes("image")?e.allowed_filetypes.alchemy_pictures:e.allowed_filetypes.alchemy_attachments;i.includes("*")||i.includes(this.file?.type.replace(/^\w+\/(\w+)(\+\w+)?/i,"$1"))||(s=d("File type not allowed")),s&&(this.valid=!1,this.errorMessage=s)}_addRequestEventListener(){this.request&&(this.request.upload.onprogress=e=>{this.progressEvent=e},this.request.onload=()=>{this.request.status<400?(this.status="successful",F(this.responseMessage)):(this.status="failed",this.errorMessage=this.responseMessage),this.dispatchCustomEvent("FileUpload.Change")},this.request.onerror=()=>{this.errorMessage=d("An error occurred during the transaction")})}get active(){return this.valid&&"canceled"!==this.status}get errorMessage(){return this._errorMessage||""}set errorMessage(e){this._errorMessage=e;const t=this.querySelector(".error-message");t&&(t.textContent=e),F(e,"error")}get finished(){return["canceled","successful","failed"].includes(this.status)}get loadedSize(){return`${Ee(this.progressEventLoaded)} / ${Ee(this.progressEventTotal)}`}get progressElement(){return this.querySelector("sl-progress-bar")}set progressEvent(e){this.progressEventLoaded=e.loaded,this.progressEventTotal=e.total,this.value=Math.round(e.loaded/e.total*100),this.querySelector(".loaded-size").textContent=this.loadedSize}get responseMessage(){try{return JSON.parse(this.request.responseText).message}catch(e){return`${this.request.status}: ${this.request.statusText}`}}get status(){return this._status}set status(e){this._status=e,this.className=e,this.progressElement?.toggleAttribute("indeterminate","upload-finished"===e)}get valid(){return this._valid}set valid(e){this._valid=e,this.classList.toggle("invalid",!e)}get value(){return this._value}set value(e){this._value=e,this.progressElement&&(this.progressElement.value=e),100===e&&(this.status="upload-finished"),this.dispatchCustomEvent("FileUpload.Change")}}customElements.define("alchemy-file-upload",we);class _e extends H{#v=!1;constructor(){super(),this.buttonLabel=d("Cancel all uploads"),this.fileUploads=[],this.fileCount=0,this.className="in-progress",this.visible=!0,this.handleFileChange=()=>this._updateView()}initialize(e=[]){this.fileUploads=e,this.fileCount=e.length}afterRender(){this.actionButton=this.querySelector("button"),this.actionButton.addEventListener("click",(()=>{this.finished?this.onComplete(this.status):this.cancel()})),this.fileUploads.forEach((e=>{this.querySelector(".single-uploads").append(e)}))}cancel(){this._activeUploads().forEach((e=>{e.cancel()})),this._setupCloseButton()}connected(){this._updateView(),this.addEventListener("Alchemy.FileUpload.Change",this.handleFileChange)}disconnected(){this.removeEventListener("Alchemy.FileUpload.Change",this.handleFileChange)}onComplete(e){}render(){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: ${this.fileCount>3?3:this.fileCount}"></div>\n <div class="overall-upload-value value-text"></div>\n `}_activeUploads(){return this.fileUploads.filter((e=>e.active))}_setupCloseButton(){this.buttonLabel=d("Close"),this.actionButton.ariaLabel=this.buttonLabel,this.actionButton.parentElement.content=this.buttonLabel}_sumFileProgresses(e){return this._activeUploads().reduce(((t,s)=>s[e]+t),0)}_updateView(){const e=this.status;this.className=e,this.progressElement.value=this.totalProgress,this.progressElement.toggleAttribute("indeterminate","upload-finished"===e),this.querySelector(".overall-progress-value > span").textContent=this.overallProgressValue,this.querySelector(".overall-upload-value").textContent=this.overallUploadSize,this.finished?(this._setupCloseButton(),this.onComplete(e)):this.visible=!0}get finished(){return this._activeUploads().every((e=>e.finished))}get overallUploadSize(){this._activeUploads().filter((e=>e.value>=100)).length;return this.totalProgress,this._activeUploads().length,`${Ee(this._sumFileProgresses("progressEventLoaded"))} / ${Ee(this._sumFileProgresses("progressEventTotal"))}`}get overallProgressValue(){const e=this._activeUploads().filter((e=>e.value>=100)).length;return`${this.totalProgress}% (${e} / ${this._activeUploads().length})`}get progressElement(){return this.querySelector("sl-progress-bar")}get status(){const e=this._activeUploads().map((e=>e.className));return e.includes("failed")?"failed":0===e.length?"canceled":e.every((t=>t===e[0]))?e[0]:"in-progress"}get totalProgress(){const e=this._activeUploads().reduce(((e,t)=>e+t.file.size),0);let t=Math.ceil(this._activeUploads().reduce(((t,s)=>{const i=s.file.size/e;return s.value*i+t}),0));return t>100&&(t=100),t}get visible(){return this.#v}set visible(e){this.classList.toggle("visible",e),this.#v=e}}customElements.define("alchemy-upload-progress",_e);customElements.define("alchemy-uploader",class extends H{static properties={dropzone:{default:!1}};connected(){this.fileInput.addEventListener("change",(e=>{this._uploadFiles(Array.from(e.target.files))})),this.dropzone&&this._dragAndDropBehavior(),this.addEventListener("Alchemy.upload.successful",this)}handleEvent(e){if("Alchemy.upload.successful"===e.type)this._handleUploadComplete()}_handleUploadComplete(){setTimeout((()=>{const e=this.redirectUrl,t=this.closest("turbo-frame");this.uploadProgress.visible=!1,e&&(t?(t.setAttribute("src",e),t.reload()):Turbo.visit(e))}),750)}_dragAndDropBehavior(){const e=document.querySelector(this.dropzone);let t=!1;const s=s=>{t!==s&&(t=s,e.classList.toggle("dragover"))};e.addEventListener("dragleave",(()=>s(!1))),e.addEventListener("drop",(async e=>{e.preventDefault(),s(!1);const t=[...e.dataTransfer.items].map((e=>e.getAsFile()));this._uploadFiles(t)})),e.addEventListener("dragover",(e=>{e.preventDefault(),s(!0)}))}_uploadFiles(e){let t=0;const s=e.map((e=>{const s=new XMLHttpRequest,i=new we;return i.initialize(e,s),Alchemy.uploader_defaults.upload_limit-1<t?(i.valid=!1,i.errorMessage=d("Maximum number of files exceeded")):i.valid&&(t++,this._submitFile(s,e)),i}));this._createProgress(s)}_submitFile(e,t){const s=this.querySelector("form"),i=new FormData(s);i.set(this.fileInput.name,t),e.open("POST",s.action),e.setRequestHeader("X-CSRF-Token",K()),e.setRequestHeader("X-Requested-With","XMLHttpRequest"),e.setRequestHeader("Accept","application/json"),e.send(i)}_createProgress(e){this.uploadProgress&&(this.uploadProgress.cancel(),document.body.removeChild(this.uploadProgress)),this.uploadProgress=new _e,this.uploadProgress.initialize(e),this.uploadProgress.onComplete=e=>{this.dispatchCustomEvent(`upload.${e}`)},document.body.append(this.uploadProgress)}get fileInput(){return this.querySelector("input[type='file']")}get redirectUrl(){return this.getAttribute("redirect-url")}});customElements.define("alchemy-overlay",class extends H{render(){return`\n <alchemy-spinner></alchemy-spinner>\n <div id="overlay_text_box">\n <span id="overlay_text">${this.getAttribute("text")}</span>\n </div>\n `}set show(e){this.classList.toggle("visible",e)}});const ke="BUTTON";class Le extends HTMLElement{connectedCallback(){this.pageId=this.getAttribute("page-id"),this.folded=this.hasAttribute("folded"),this.folderButton?.addEventListener("click",this)}disconnectedCallback(){this.folderButton?.removeEventListener("click",this)}async handleEvent(e){"click"===e.type&&await this.handleFolderClick(e)}async handleFolderClick(e){e.preventDefault(),e.stopPropagation();const t=e.currentTarget;t.innerHTML="";const s=new y("small");s.spin(t);try{await Z(Alchemy.routes.fold_admin_page_path(this.pageId),null,"text/vnd.turbo-stream.html"),this.folded=!this.folded,this.toggleAttribute("folded",this.folded),this.toggleChildren(),this.updateFolderIcon()}catch(e){F(e.message||e,"error"),this.updateFolderIcon()}finally{s.stop()}}toggleChildren(){const e=this.querySelector(`#page_${this.pageId}_children`);e&&e.classList.toggle("hidden",this.folded)}updateFolderIcon(){if(this.folderButton){const e=this.folded?"arrow-right-s":"arrow-down-s";this.folderButton.innerHTML=`<alchemy-icon name="${e}"></alchemy-icon>`}}updateFolderButton(){const e=this.querySelector(".page_folder");if(!e)return;const t=this.hasChildren||this.folded;if(t&&"SPAN"===e.tagName){const t=this.folded?"arrow-right-s":"arrow-down-s";e.outerHTML=`<button class="page_folder icon_button">\n <alchemy-icon name="${t}"></alchemy-icon>\n </button>`,this.folderButton?.addEventListener("click",this)}else t||e.tagName!==ke?t&&e.tagName===ke&&this.updateFolderIcon():e.outerHTML='<span class="page_folder"></span>'}get hasChildren(){const e=this.querySelector(`#page_${this.pageId}_children`);return!!e&&e.querySelectorAll(":scope > alchemy-page-node").length>0}get folderButton(){return this.querySelector("button.page_folder")}}customElements.define("alchemy-page-node",Le);class Se extends HTMLElement{connectedCallback(){const e=this.querySelector("alchemy-datepicker:has(#page_public_on)"),t=this.querySelector("alchemy-datepicker:has(#page_public_until)"),s=this.querySelector(".page-publication-date-fields"),i=this.querySelector("#page_public");i&&i.addEventListener("click",(function(i){const n=i.target,r=new Date;n.checked?(s.classList.remove("hidden"),e.flatpickr.setDate(r)):(s.classList.add("hidden"),e.flatpickr.clear()),t.flatpickr?.clear()}))}}customElements.define("alchemy-page-publication-fields",Se);customElements.define("alchemy-page-select",class extends D{get pageId(){return this.selection?JSON.parse(this.selection).id:void 0}_searchQuery(e,t){return{q:{name_cont:e,...JSON.parse(this.queryParams)},page:t}}_parseResponse(e){const t=e.meta;return{results:e.pages,more:t.page*t.per_page<t.total_count}}_renderResult(e){return e.text||e.name}_renderListEntry(e,t){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(e.name,t)}</span>\n <span class="page-select--site-name">${e.site.name}</span>\n </div>\n <div class="page-select--bottom">\n <span class="page-select--page-urlname">${e.url_path}</span>\n <span class="page-select--language-code">${e.language_code}</span>\n </div>\n </div>\n `}});class Ce extends HTMLElement{constructor(){super(),this.addEventListener("change",this)}handleEvent(e){if("change"===e.type)this.onChange()}onChange(){const e=new URL(this.getAttribute("url")),t=this.querySelector("select");e.searchParams.set("language_id",t.value),Turbo.visit(e,{frame:"picture_descriptions"})}}customElements.define("alchemy-picture-description-select",Ce);class xe extends HTMLElement{constructor(){super(),this.cropFromField=this.querySelector("[data-crop-from]"),this.cropSizeField=this.querySelector("[data-crop-size]"),this.pictureIdField=this.querySelector("[data-picture-id]"),this.targetSizeField=this.querySelector("[data-target-size]"),this.imageCropperField=this.querySelector("[data-image-cropper]"),this.image=this.querySelector("img"),this.pictureThumbnail=this.querySelector("alchemy-picture-thumbnail"),this.deleteButton=this.querySelector(".picture_tool.delete"),this.cropLink=this.querySelector(".crop_link"),this.targetSize=this.targetSizeField.dataset.targetSize,this.pictureId=this.pictureIdField.value,this.update=function(e,t){let s;return function(...i){const n=this;clearTimeout(s),s=setTimeout((()=>e.apply(n,i)),t)}}((()=>{this.updateImage(),this.updateCropLink()}),125),this.deleteButton?.addEventListener("click",this.removeImage.bind(this))}connectedCallback(){this.observer=new MutationObserver(this.mutationCallback.bind(this)),this.observer.observe(this.cropFromField,{attributes:!0}),this.observer.observe(this.cropSizeField,{attributes:!0}),this.observer.observe(this.pictureIdField,{attributes:!0})}disconnectedCallback(){this.observer.disconnect()}mutationCallback(e){for(const t of e)"pictureId"in t.target.dataset&&(this.cropFromField.value="",this.cropSizeField.value="",this.pictureId=t.target.value),this.update()}updateImage(){this.pictureId&&(this.pictureThumbnail.loading=!0,G(Alchemy.routes.url_admin_picture_path(this.pictureId),{crop:this.imageCropperEnabled,crop_from:this.cropFrom,crop_size:this.cropSize,flatten:!0,size:"160x120"}).then((({data:e})=>{this.pictureThumbnail.src=e.url,this.pictureThumbnail.image.alt=e.alt,this.pictureThumbnail.image.title=e.title,this.setElementDirty()})).catch((e=>{console.error(e.message||e),F(e.message||e,"error")})))}removeImage(){this.pictureThumbnail.innerHTML='<alchemy-icon name="image" size="xl"></alchemy-icon>',this.pictureIdField.value="",this.image=null,this.cropLink.classList.add("disabled"),this.setElementDirty()}setElementDirty(){this.closest(".element-editor").setDirty(this)}updateCropLink(){this.pictureId&&this.imageCropperEnabled&&(this.cropLink.classList.remove("disabled"),this.cropLink.href.match(/(picture_id=)\d+/)?this.cropLink.href=this.cropLink.href.replace(/(picture_id=)\d+/,"$1"+this.pictureId):this.cropLink.href=this.cropLink.href+`&picture_id=${this.pictureId}`)}get cropFrom(){return""===this.cropFromField.value?this.defaultCropFrom.join("x"):this.cropFromField.value}get cropSize(){return""===this.cropSizeField.value?this.defaultCropSize.join("x"):this.cropSizeField.value}get defaultCropSize(){if(!this.imageCropperEnabled)return[];const e=this.targetSize.split("x").map((e=>parseInt(e))),t=(s=e[0]/this.imageFileWidth,i=e[1]/this.imageFileHeight,s>=i?s:i);var s,i;return[Math.round(e[0]/t),Math.round(e[1]/t)]}get defaultCropFrom(){if(!this.imageCropperEnabled)return[];const e=this.defaultCropSize;return[Math.round((this.imageFileWidth-e[0])/2),Math.round((this.imageFileHeight-e[1])/2)]}get imageFileWidth(){return parseInt(this.pictureIdField.dataset.imageFileWidth)}get imageFileHeight(){return parseInt(this.pictureIdField.dataset.imageFileHeight)}get imageCropperEnabled(){return"true"===this.targetSizeField.dataset.imageCropper}}customElements.define("alchemy-picture-editor",xe);class Te extends HTMLElement{constructor(){super(),this.classList.add("thumbnail_background"),this.spinner=new y("small"),this.src&&this.start()}handleEvent(e){switch(e.type){case"load":this.#C();break;case"error":this.#x(e)}}connectedCallback(){this.#T()}disconnectedCallback(){this.image?.removeEventListener("load",this),this.image?.removeEventListener("error",this),this.stop()}createImage(e=this.src,t=this.name){this.image=new Image,this.image.src=e,t&&(this.image.alt=t),this.image.loading="lazy"}start(e){this.createImage(e),this.image.addEventListener("load",this),this.image.addEventListener("error",this),this.load()}load(){this.image?.complete||(this.setAttribute("loading","loading"),this.innerHTML="",this.spinner.spin(this))}stop(){this.classList.remove("loading"),this.spinner.stop()}#C(){this.spinner.stop(),this.removeAttribute("loading")}#x(e){const t=`Could not load ${this.image.src}`,s=this.closest(".ingredient-editor");this.spinner.stop(),this.innerHTML=`\n <sl-tooltip content="${t}" ${s?"hoist":""}>\n <alchemy-icon name="alert" class="error"></alchemy-icon>\n </sl-tooltip>\n `,console.error(t,e)}#T(){this.image?.complete?this.replaceChildren(this.image):this.image&&this.append(this.image)}set loading(e){e?this.load():this.stop()}set src(e){this.start(e),this.#T()}get name(){return this.getAttribute("name")}get src(){return this.getAttribute("src")}}customElements.define("alchemy-picture-thumbnail",Te);class Ae extends HTMLElement{constructor(){super(),this.addEventListener("submit",this)}connectedCallback(){document.addEventListener("alchemy:page-dirty",this)}disconnectedCallback(){document.removeEventListener("alchemy:page-dirty",this)}handleEvent(e){switch(e.type){case"alchemy:page-dirty":this.markDirty(e.detail);break;case"submit":this.button.loading=!0}}markDirty(e){this.button.variant="primary",this.button.disabled=!1,this.tooltip.content=e.tooltip}get button(){return this.querySelector("sl-button")}get tooltip(){return this.querySelector("sl-tooltip")}}customElements.define("alchemy-publish-page-button",Ae);class $e extends HTMLSelectElement{#A;connectedCallback(){this.classList.add("alchemy_selectbox"),this.#A=$(this).select2({minimumResultsForSearch:5,dropdownAutoWidth:!0,allowClear:!!this.allowClear}),this.allowClear||this.multiple||this.#A.prev(".select2-container").find(".select2-search-choice-close").remove()}enable(){this.removeAttribute("disabled"),this.#$()}disable(){this.setAttribute("disabled","disabled"),this.#$()}setOptions(e,t=void 0){let s=this.value;this.innerHTML="",t&&this.add(new Option(t,"")),e.forEach((e=>{this.add(new Option(e.text,e.id,!1,e.id===s))})),this.#$()}#$(){this.#A.trigger("change")}get allowClear(){return this.dataset.hasOwnProperty("allowClear")||this.multiple}}customElements.define("alchemy-select",$e,{extends:"select"});class Fe extends HTMLElement{connectedCallback(){this.searchInput=document.querySelector(".search_input_field"),this.clearButton=document.querySelector("#search_field_clear"),this.resultCounter=document.querySelector("#page_filter_result"),this.setupSearch(),requestAnimationFrame((()=>{this.setupSortables()})),this.observer=new MutationObserver((e=>{e.forEach((e=>{e.addedNodes.forEach((e=>{e.nodeType===Node.ELEMENT_NODE&&(e.classList?.contains("children")&&this.setupSortable(e),e.querySelectorAll(".children").forEach((e=>this.setupSortable(e))))}))}))})),this.observer.observe(this,{childList:!0,subtree:!0})}disconnectedCallback(){this.teardownSearch(),this.observer?.disconnect()}setupSearch(){this.searchInput?.addEventListener("input",this),this.clearButton?.addEventListener("click",this)}teardownSearch(){this.searchInput?.removeEventListener("input",this),this.clearButton?.removeEventListener("click",this)}handleEvent(e){"input"===e.type&&e.target===this.searchInput?this.handleSearch(e):"click"===e.type&&e.target===this.clearButton&&this.handleClearSearch(e)}handleSearch(e){const t=e.target.value.toLowerCase().trim();""!==t?this.filterPages(t):this.clearFilter()}filterPages(e){const t=this.querySelectorAll(".sitemap_page");let s=0,i=null;t.forEach((t=>{(t.getAttribute("name")||"").toLowerCase().includes(e)?(t.classList.add("highlight"),t.classList.remove("no-match"),s++,i||(i=t)):(t.classList.remove("highlight"),t.classList.add("no-match"))})),1===s?(this.resultCounter.textContent=`1 ${d("page_found")}`,this.resultCounter.style.display="block"):s>1?(this.resultCounter.textContent=`${s} ${d("pages_found")}`,this.resultCounter.style.display="block"):this.resultCounter.style.display="none",i&&i.scrollIntoView({behavior:"smooth",block:"center"})}clearFilter(){this.querySelectorAll(".sitemap_page").forEach((e=>{e.classList.remove("highlight","no-match")})),this.resultCounter.style.display="none"}handleClearSearch(e){e.preventDefault(),this.searchInput.value="",this.clearFilter()}setupSortable(e){new i(e,{group:"pages",animation:150,fallbackOnBody:!0,swapThreshold:.65,handle:".page-icon.handle",draggable:"alchemy-page-node",onEnd:e=>this.handleSort(e)})}setupSortables(){this.querySelectorAll(".children").forEach((e=>this.setupSortable(e)))}async handleSort(e){if(e.from===e.to&&e.oldIndex===e.newIndex)return;const t=e.item,s=t.pageId,i=Alchemy.routes.move_admin_page_path(s),n={target_parent_id:e.to.dataset.parentId,new_position:e.newIndex};S(!0);try{const r=await Z(i,n),l=await r.data,o=t.querySelector(`#page_${s}`);if(o){const e=o.querySelector(".sitemap_url");e&&l.url_path&&(e.textContent=l.url_path)}this.updateFolderIcons(e.from,e.to),F(d("Successfully moved page"))}catch(e){F(e.message||e,"error"),window.location.reload()}finally{S(!1)}}updateFolderIcons(e,t){const s=e.closest("alchemy-page-node");if(s?.updateFolderButton(),e!==t){const e=t.closest("alchemy-page-node");e?.updateFolderButton()}}}customElements.define("alchemy-sitemap",Fe);const qe={draggable:".element-editor",handle:".element-handle.draggable",ghostClass:"dragged",animation:150,swapThreshold:.65,easing:"cubic-bezier(1, 0, 0, 1)"};function Ie(e){const t=e.item.dataset.elementName;document.querySelectorAll(`[data-droppable-elements~="${t}"]`).forEach((e=>e.classList.add("droppable-elements")))}function Be(e){const t=e.item,s=e.to.parentElement.closest(".element-editor"),i={element_id:t.dataset.elementId,position:e.newIndex+1};s&&(i.parent_element_id=s.dataset.elementId),e.target===e.to&&ee(Alchemy.routes.order_admin_elements_path,i).then((e=>{const s=e.data;F(s.message),s.pageHasUnpublishedChanges&&re(s),B(),t.updateTitle(s.preview_text)}))}function Me(){document.querySelectorAll("[data-droppable-elements]").forEach((e=>e.classList.remove("droppable-elements")))}class ze extends HTMLElement{connectedCallback(){const e={name:this.dataset.elementName,put:(e,t,s)=>e.el.dataset.droppableElements.split(" ").includes(s.dataset.elementName)};new i(this,{...qe,onStart:Ie,onSort:Be,onEnd:Me,group:e})}}customElements.define("alchemy-sortable-elements",ze);customElements.define("alchemy-spinner",class extends H{static properties={size:{default:"medium"},color:{default:"currentColor"}};render(){return this.className=`spinner spinner--${this.size}`,`\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 `}});class He extends HTMLElement{async connectedCallback(){await h(),this.classList.add("autocomplete_tag_list"),$(this.input).select2(this.select2Config)}get input(){return this.getElementsByTagName("input")[0]}get select2Config(){return{tags:!0,tokenSeparators:[","],openOnEnter:!1,minimumInputLength:1,createSearchChoice:this.#F,ajax:{url:this.getAttribute("url"),dataType:"json",data:e=>({term:e}),results:e=>({results:e})},initSelection:this.#q}}#F(e,t){if(0===$(t).filter((function(){return 0===this.text.localeCompare(e)})).length)return{id:e,text:e}}#q(e,t){const s=[];$(e.val().split(",")).each((function(){s.push({id:this.trim(),text:this})})),t(s)}}customElements.define("alchemy-tags-autocomplete",He);const Pe="alchemy-dark",De="alchemy";customElements.define("alchemy-tinymce",class extends H{#I=null;connected(){this.className="tinymce_container";const e={root:document.getElementById("element_area"),rootMargin:"0px",threshold:[.05]};this.tinymceIntersectionObserver=new IntersectionObserver(((e,t)=>{e.forEach((e=>{e.intersectionRatio>0&&(this._initTinymceEditor(),t.unobserve(e.target))}))}),e),this.tinymceIntersectionObserver.observe(this),this._setupThemeChangeListener()}disconnected(){null!==this.tinymceIntersectionObserver&&this.tinymceIntersectionObserver.disconnect(),this._removeThemeChangeListener(),tinymce.get(this.editorId)?.remove(this.editorId)}render(){return`\n ${this.initialContent}\n <alchemy-spinner size="small"></alchemy-spinner>\n `}afterRender(){this.style.minHeight=`${this.minHeight}px`,this.editor.style.display="none"}_initTinymceEditor(){tinymce.init(this.configuration).then((e=>{e.forEach((e=>this._setupEditor(e)))}))}_setupEditor(e){e.show();const t=this.getElementsByTagName("alchemy-spinner")[0];t&&t.remove(),this.elementEditor&&(e.on("dirty",(e=>{this.elementEditor.setDirty(e.target.editorContainer)})),e.on("click",(()=>this.elementEditor.onClickElement(!1))))}_setupThemeChangeListener(){this.darkModeMediaQuery=window.matchMedia("(prefers-color-scheme: dark)"),this.themeChangeHandler=e=>this._handleThemeChange(e),this.darkModeMediaQuery.addEventListener("change",this.themeChangeHandler)}_removeThemeChangeListener(){this.darkModeMediaQuery&&this.themeChangeHandler&&this.darkModeMediaQuery.removeEventListener("change",this.themeChangeHandler)}_handleThemeChange(e){const t=tinymce.get(this.editorId);if(t){const s=e.matches?Pe:De,i=e.matches?Pe:De;t.remove(),tinymce.init({content_css:i,...this.configuration,skin:s}).then((e=>{e.forEach((e=>this._setupEditor(e)))}))}}get configuration(){const e={};this.getAttributeNames().forEach((t=>{if(!["class","id","is","name","style"].includes(t)){const s=this.getAttribute(t),i=t.replaceAll("-","_");if(s===t||""===s)e[i]=!0;else try{e[i]=JSON.parse(s)}catch(t){e[i]=s}}}));const t={content_css:this.preferredTheme,...Alchemy.TinymceDefaults,...e,language:c(),selector:`#${this.editorId}`,skin:this.preferredTheme};return t.height=t.min_height,t}get preferredTheme(){return window.matchMedia("(prefers-color-scheme: dark)").matches?Pe:De}get editorId(){return this.editor.id}get editor(){return this.getElementsByTagName("textarea")[0]}get elementEditor(){return document.getElementById(this.editorId).closest("alchemy-element-editor")}get minHeight(){return this.#I||this.configuration.min_height}set minHeight(e){this.#I=e}});class Ne extends HTMLElement{async connectedCallback(){const e=new y("small");e.spin(this);try{const e=await fetch(this.url,{credentials:"include"}),t=await e.json();e.ok?this.showStatus(t):this.showError(e)}catch(e){this.showError(e)}finally{e.stop()}}get url(){return this.getAttribute("url")}showStatus(e){"true"==e.status?this.querySelector(".update_available").classList.remove("hidden"):this.querySelector(".up_to_date").classList.remove("hidden")}showError(e){this.querySelector(".error").classList.remove("hidden"),console.error("[alchemy] Error fetching update status",e)}}var Oe;customElements.define("alchemy-update-check",Ne),Oe=Handlebars.template,(Handlebars.templates=Handlebars.templates||{})["node_folder.hbs"]=Oe({0:function(e,t,s,i,n){return"right"},1:function(e,t,s,i,n){return"down"},compiler:[8,">= 4.3.0"],main:function(e,t,s,i,n){var r,l=e.lambda,o=e.escapeExpression,a=e.lookupProperty||function(e,t){if(Object.prototype.hasOwnProperty.call(e,t))return e[t]};return'<a class="node_folder" data-record-id="'+o(l(null!=(r=null!=t?a(t,"node"):t)?a(r,"id"):r,t))+'" data-record-type="'+o(l(null!=(r=null!=t?a(t,"node"):t)?a(r,"type"):r,t))+'">\n <alchemy-icon name="arrow-'+(null!=(r=a(s,"if").call(null!=t?t:e.nullContext||{},null!=(r=null!=t?a(t,"node"):t)?a(r,"folded"):r,{name:"if",hash:{},fn:e.program(0,n,0),inverse:e.program(1,n,0),data:n,loc:{start:{line:2,column:28},end:{line:2,column:72}}}))?r:"")+'-s"></alchemy-icon>\n</a>\n'},useData:!0}),n("tooltip.show",{keyframes:[{transform:"translateY(10px)",opacity:"0"},{transform:"translateY(0)",opacity:"1"}],options:{duration:100}}),n("tooltip.hide",{keyframes:[{transform:"translateY(0)",opacity:"1"},{transform:"translateY(10px)",opacity:"0"}],options:{duration:100}}),n("dialog.show",{keyframes:[{transform:"scale(0.98)",opacity:"0"},{transform:"scale(1)",opacity:"1"}],options:{duration:150}}),n("dialog.hide",{keyframes:[{transform:"scale(1)",opacity:"1"},{transform:"scale(0.98)",opacity:"0"}],options:{duration:150}});const Re=document.querySelector('link[rel="preload"][as="image"]').getAttribute("href"),Ue={"x-lg":"close",caret:"arrow-down-s"},je={resolver:e=>`${Re}#ri-${Ue[e]||e}-line`,mutator:e=>{e.setAttribute("fill","currentColor"),e.setAttribute("viewBox","0 0 24 24")},spriteSheet:!0};function We(e,t,s,i){document.querySelectorAll(t).forEach((t=>{t.addEventListener(e,(e=>{const n=Array.from(t.querySelectorAll(s));let r=e.target;for(;r!==t;){if(n.includes(r))return void i.call(r,e);r=r.parentElement}}))}))}r("default",je),r("system",je);class Je{#B=!1;#M=null;#z=null;#H=null;constructor(e,t){this.image=e,this.defaultBox=t.default_box,this.aspectRatio=t.ratio,this.#z=document.getElementById(t.crop_from_form_field_id),this.#H=document.getElementById(t.crop_size_form_field_id),this.elementId=t.element_id,this.dialog=Alchemy.currentDialog(),this.dialog&&(this.dialog.options.closed=()=>this.destroy(),this.bind()),this.init()}get cropperOptions(){return{aspectRatio:this.aspectRatio,viewMode:1,zoomable:!1,checkCrossOrigin:!1,checkOrientation:!1,data:this.box,cropend:()=>{const e=this.#M.getData(!0);this.update(e)}}}get cropFrom(){if(this.#z?.value)return this.#z.value.split("x").map((e=>parseInt(e)))}get cropSize(){if(this.#H?.value)return this.#H.value.split("x").map((e=>parseInt(e)))}get box(){return this.cropFrom&&this.cropSize?{x:this.cropFrom[0],y:this.cropFrom[1],width:this.cropSize[0],height:this.cropSize[1]}:this.defaultBoxSize}get defaultBoxSize(){return{x:this.defaultBox[0],y:this.defaultBox[1],width:this.defaultBox[2],height:this.defaultBox[3]}}init(){this.#B||(this.#M=new l(this.image,this.cropperOptions),this.#B=!0)}update(e){this.#z.value=`${e.x}x${e.y}`,this.#z.dispatchEvent(new Event("change")),this.#H.value=`${e.width}x${e.height}`,this.#H.dispatchEvent(new Event("change"))}reset(){this.#M.setData(this.defaultBoxSize),this.update(this.defaultBoxSize)}destroy(){return this.#M&&this.#M.destroy(),this.#B=!1,!0}bind(){this.dialog.dialog_body.find('button[type="submit"]').on("click",(()=>(document.querySelector(`[data-element-id='${this.elementId}']`).setDirty(),this.dialog.close(),!1))),this.dialog.dialog_body.find('button[type="reset"]').on("click",(()=>(this.reset(),!1)))}}class Ve extends b{constructor(e,t={}){super(e,t)}init(){$(".zoomed-picture-background").on("click",(e=>{if(e.stopPropagation(),"IMG"!==e.target.nodeName)return this.close(),!1})),$(".picture-overlay-handle").on("click",(e=>(this.dialog.toggleClass("hide-form"),!1))),this.$previous=$(".previous-picture"),this.$next=$(".next-picture"),this.#P(),super.init()}previous(){null!=this.$previous[0]&&this.$previous[0].click()}next(){null!=this.$next[0]&&this.$next[0].click()}build(){this.dialog_container=$('<div class="alchemy-image-overlay-container" />'),this.dialog=$('<div class="alchemy-image-overlay-dialog" />'),this.dialog_body=$('<div class="alchemy-image-overlay-body" />'),this.close_button=$('<a class="alchemy-image-overlay-close">\n <alchemy-icon name="close" size="xl"></alchemy-icon>\n </a>'),this.dialog.append(this.close_button),this.dialog.append(this.dialog_body),this.dialog_container.append(this.dialog),this.overlay=$('<div class="alchemy-image-overlay" />'),this.$body.append(this.overlay),this.$body.append(this.dialog_container)}#P(){this.$document.keydown((e=>{if("INPUT"===e.target.nodeName||"TEXTAREA"===e.target.nodeName)return!0;switch(e.which){case 37:return this.previous(),!1;case 39:return this.next(),!1;default:return!0}}))}}function Xe(){return document.querySelectorAll("#picture_archive input:checked")}function Qe(){const e=document.querySelector("#select_all_pictures"),t=document.querySelector(".selected_item_tools");We("click",".toolbar_buttons","a#select_all_pictures",(s=>{s.preventDefault(),e.classList.toggle("active");const i=e.classList.contains("active");!function(e){document.querySelectorAll(".picture_tool.select input[type='checkbox']").forEach((t=>{t.checked=e,t.closest(".picture_thumbnail").classList.toggle("active",e)}))}(i),t.classList.toggle("hidden",!i)})),We("change",".picture_tool.select","input",(e=>{t.classList.toggle("hidden",0===Xe().length);const s=e.target.parentElement.classList,i=e.target.checked;s.toggle("visible",i)})),We("click",".selected_item_tools","a#edit_multiple_pictures",(e=>{e.preventDefault();_(function(e){const t=new URL(e);return Xe().forEach((e=>t.searchParams.append(e.name,e.value))),t.toString()}(e.target.href),{title:e.target.title,size:"400x295"})}))}function Ye(){document.querySelectorAll("li.menu-item").forEach((e=>{const t=e.querySelector(".nodes_tree-left_images"),s=e.querySelector(".children"),i={folded:"true"===e.dataset.folded,id:e.dataset.id,type:e.dataset.type};s.children.length>0||i.folded?t.innerHTML=Handlebars.templates["node_folder.hbs"]({node:i}):t.innerHTML="&nbsp;"}))}function Ke(e){Z(Alchemy.routes[e.item.dataset.type].move_api_path(e.item.dataset.id),{target_parent_id:e.to.dataset.recordId,new_position:e.newIndex}).then((()=>{F(Alchemy.t("Successfully moved menu item")),Ye()})).catch((e=>{F(e.message||e,"error")}))}function Ge(){We("click",".nodes_tree",".node_folder",(function(){const e=this.dataset.recordId,t=this.closest("li.menu-item"),s=Alchemy.routes[this.dataset.recordType].toggle_folded_api_path(e),i=t.querySelector(".children");Z(s).then((()=>{i.classList.toggle("folded"),t.dataset.folded="true"==t.dataset.folded?"false":"true",Ye()})).catch((e=>{F(e.message||e)}))})),Ye(),document.querySelectorAll(".nodes_tree ul.children").forEach((e=>{new i(e,{group:"nodes",animation:150,fallbackOnBody:!0,swapThreshold:.65,handle:".node_name",invertSwap:!0,onEnd:Ke})}))}void 0===window.Alchemy&&(window.Alchemy={}),Object.assign(Alchemy,{closeCurrentDialog:w,currentDialog:E,...x,t:d,FixedElements:A,growl:F,LinkDialog:class extends b{#D;constructor(e){const t=new URL(Alchemy.routes.link_admin_pages_path,window.location),s={url:e.url,selected_tab:e.type,link_title:e.title,link_target:e.target};Object.keys(s).forEach((e=>{s[e]&&t.searchParams.set(e,s[e])})),super(t.href,{size:"600x320",title:d("Link")})}replace(e){super.replace(e),this.#c()}open(){return super.open(),new Promise((e=>this.#D=e))}#c(){const e=document.querySelector('[data-link-form-type="internal"]'),t=document.querySelector('[data-link-form-type="file"] alchemy-attachment-select');e.addEventListener("Alchemy.RemoteSelect.Change",(e=>{this.#N(e.detail.added)})),t.addEventListener("Alchemy.RemoteSelect.Change",(e=>{const t=e.detail.added;document.getElementById("file_link").value=t?t.url:""})),document.querySelectorAll("[data-link-form-type]").forEach((e=>{e.addEventListener("submit",(e=>{e.preventDefault(),this.#O(e.target.dataset.linkFormType)}))}))}#N(e=null){const t=document.getElementById("internal_link"),s=document.querySelector('[data-link-form-type="internal"] alchemy-dom-id-api-select');t.value=e?e.url_path:"",s.page=e?e.id:void 0}#O(e){const t=document.getElementById("element_anchor");let s=document.getElementById(`${e}_link`).value;if("internal"===e&&""!==t.value)s=s.replace(q,"")+t.value;else if("external"===e&&!s.match(Alchemy.link_url_regexp))return void this.#R();this.#D({url:s.trim(),title:document.getElementById(`${e}_link_title`).value,target:document.getElementById(`${e}_link_target`)?.value,type:e}),this.close()}#R(){const e=document.getElementById("errors");e.querySelector("ul").innerHTML=`<li>${Alchemy.t("url_validation_failed")}</li>`,e.style.display="block"}},pleaseWaitOverlay:S,Spinner:y,reloadPreview:B}),t.start(),e.config.forms.confirm=L,document.addEventListener("turbo:load",(function(){document.documentElement.classList.remove("no-js"),p(),document.querySelectorAll(".please_wait").forEach((e=>{e.addEventListener("click",S)})),document.querySelectorAll("a.button").forEach((e=>{e.setAttribute("tabindex",0)})),key.filter=function(e){let t=(e.target||e.srcElement).tagName;return key.isPressed("esc")||!("INPUT"===t||"SELECT"===t||"TEXTAREA"===t)}}));export{Je as ImageCropper,Ve as ImageOverlay,Ge as NodeTree,D as RemoteSelect,We as on,Qe as pictureSelector};
2
+ //# sourceMappingURL=alchemy_admin.min.js.map