
/* /html_builder/static/src/builder.js */
odoo.define('@html_builder/builder',['@html_editor/editor','@odoo/owl','@web/core/hotkeys/hotkey_hook','@web/core/l10n/translation','@web/core/ui/ui_service','@web/core/utils/hooks','@web/core/utils/ui','@html_builder/sidebar/invisible_elements_panel','@html_builder/sidebar/block_tab','@html_builder/sidebar/customize_tab','@html_builder/snippets/snippet_service','@html_builder/utils/utils_css','@html_editor/utils/resource','@html_editor/utils/formatting','@html_builder/utils/utils'],function(require){'use strict';let __exports={};const{Editor}=require("@html_editor/editor");const{Component,EventBus,onMounted,onWillDestroy,onWillStart,onWillUnmount,onWillUpdateProps,status,useRef,useState,useSubEnv,}=require("@odoo/owl");const{useHotkey}=require("@web/core/hotkeys/hotkey_hook");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{SIZES,MEDIAS_BREAKPOINTS}=require("@web/core/ui/ui_service");const{useService}=require("@web/core/utils/hooks");const{addLoadingEffect:addButtonLoadingEffect}=require("@web/core/utils/ui");const{InvisibleElementsPanel}=require("@html_builder/sidebar/invisible_elements_panel");const{BlockTab}=require("@html_builder/sidebar/block_tab");const{CustomizeTab}=require("@html_builder/sidebar/customize_tab");const{useSnippets}=require("@html_builder/snippets/snippet_service");const{setBuilderCSSVariables}=require("@html_builder/utils/utils_css");const{withSequence}=require("@html_editor/utils/resource");const{getHtmlStyle}=require("@html_editor/utils/formatting");const{isVisible}=require("@html_builder/utils/utils");const ONLY_ALLOW_INLINE_TAGS=new Set([...["a","em","strong","small","s","cite","q","abbr","data","time","code"],...["samp","sub","sup","i","b","u","mark","bdi","span","label","button"],]);const Builder=__exports.Builder=class Builder extends Component{static template="html_builder.Builder";static components={BlockTab,CustomizeTab};static props={closeEditor:{type:Function,optional:true},reloadEditor:{type:Function,optional:true},onEditorLoad:{type:Function,optional:true},installSnippetModule:{type:Function,optional:true},snippetsName:{type:String},toggleMobile:{type:Function},overlayRef:{type:Function},iframeLoaded:{type:Object},isMobile:{type:Boolean},Plugins:{type:Array,optional:true},config:{type:Object,optional:true},getThemeTab:{type:Function,optional:true},editableSelector:{type:String},themeTabDisplayName:{type:String,optional:true},slots:{type:Object,optional:true},getCustomizeTranslationTab:{type:Function,optional:true},};static defaultProps={config:{},themeTabDisplayName:_t("Theme"),};setup(){this.ThemeTab=this.props.getThemeTab?.();this.CustomizeTranslationTab=this.props.getCustomizeTranslationTab?.();this.builder_sidebarRef=useRef("builder_sidebar");this.state=useState({canUndo:false,canRedo:false,activeTab:this.props.config.initialTab||"blocks",currentOptionsContainers:undefined,});this.invisibleElementsPanelState=useState({invisibleEls:[],invisibleSelector:this.getInvisibleSelector(),});useHotkey("control+z",()=>this.undo());useHotkey("control+y",()=>this.redo());useHotkey("control+shift+z",()=>this.redo());this.orm=useService("orm");this.ui=useService("ui");this.notification=useService("notification");this.snippetModel=useSnippets(this.props.snippetsName);this.lastTrigerUpdateId=0;this.editorBus=new EventBus();this.colorPresetToShow=null;this.activeTargetEl=null;const mobileBreakpoint=this.props.config.mobileBreakpoint??"lg";this.editor=new Editor({Plugins:this.props.Plugins,...this.props.config,mobileBreakpoint,isMobileView:(targetEl)=>{const mobileViewThreshold=MEDIAS_BREAKPOINTS[SIZES[mobileBreakpoint.toUpperCase()]].minWidth;const clientWidth=targetEl.ownerDocument.defaultView?.frameElement?.clientWidth||targetEl.ownerDocument.documentElement.clientWidth;return!!clientWidth&&clientWidth<mobileViewThreshold;},onChange:({isPreviewing})=>{if(!isPreviewing){this.state.canUndo=this.editor.shared.history.canUndo();this.state.canRedo=this.editor.shared.history.canRedo();this.updateInvisibleEls();this.editorBus.trigger("UPDATE_EDITING_ELEMENT");this.triggerDomUpdated();this.props.config.onChange?.();}},reloadEditor:async(param={})=>{await this.props.reloadEditor?.({initialTab:this.state.activeTab,...param,});},closeEditor:async()=>{await this.props.closeEditor?.();},installSnippetModule:(snippet)=>this.props.installSnippetModule?.(snippet),resources:{trigger_dom_updated:()=>{this.triggerDomUpdated();},on_mobile_preview_clicked:withSequence(20,()=>{this.triggerDomUpdated();}),before_save_handlers:()=>{const snippetMenuEl=this.builder_sidebarRef.el;const saveButton=snippetMenuEl.querySelector("[data-action='save']");delete this.removeLoadingEffect;if(saveButton){this.removeLoadingEffect=addButtonLoadingEffect(snippetMenuEl.querySelector("[data-action='save']"));}
this.actionButtonEls=snippetMenuEl.querySelectorAll("[data-action]");for(const actionButtonEl of this.actionButtonEls){actionButtonEl.disabled=true;}},after_save_handlers:()=>{for(const actionButtonEl of this.actionButtonEls){actionButtonEl.removeAttribute("disabled");}
this.removeLoadingEffect?.();},on_snippet_dropped_handlers:()=>{this.activeTargetEl=null;},change_current_options_containers_listeners:(currentOptionsContainers)=>{this.state.currentOptionsContainers=currentOptionsContainers;if(!currentOptionsContainers.length){this.setTab(this.noSelectionTab);return;}
this.activeTargetEl=null;this.setTab("customize");},lower_panel_entries:withSequence(20,{Component:InvisibleElementsPanel,props:this.invisibleElementsPanelState,}),unsplittable_node_predicates:(node)=>node.querySelector?.("[data-oe-translation-source-sha]"),are_inlines_allowed_at_root_predicates:(el)=>ONLY_ALLOW_INLINE_TAGS.has(el.tagName.toLowerCase())||undefined,},localOverlayContainers:{key:this.env.localOverlayContainerKey,ref:this.props.overlayRef,},saveSnippet:(snippetEl,cleanForSaveHandlers,wrapWithSaveSnippetHandlers)=>this.snippetModel.saveSnippet(snippetEl,cleanForSaveHandlers,wrapWithSaveSnippetHandlers),snippetModel:this.snippetModel,updateInvisibleElementsPanel:()=>this.updateInvisibleEls(),allowCustomStyle:true,allowTargetBlank:true,dropImageAsAttachment:true,getAnimateTextConfig:()=>({editor:this.editor,editorBus:this.editorBus}),baseContainers:["P"],cleanEmptyStructuralContainers:false,isEditableRTL:false,publicAttachments:true,direction:"ltr",},this.env.services);this.props.onEditorLoad?.(this.editor);onWillStart(async()=>{await this.snippetModel.load();const iframeEl=await this.props.iframeLoaded;if(status(this)==="destroyed"){return;}
this.editableEl=iframeEl.contentDocument.body.querySelector(this.props.editableSelector);if(this.editableEl.matches(".o_rtl")){this.editor.config.isEditableRTL=true;this.editor.config.direction="rtl";}
this.onDragStart=(ev)=>{if(ev.target.nodeName==="IMG"){ev.preventDefault();ev.stopPropagation();}};this.editor.attachTo(this.editableEl);});useSubEnv({editor:this.editor,editorBus:this.editorBus,triggerDomUpdated:this.triggerDomUpdated.bind(this),editColorCombination:this.editColorCombination.bind(this),});onWillDestroy(()=>{this.editor.destroy();});onMounted(()=>{this.editor.document.body.classList.add("editor_enable");setBuilderCSSVariables(getHtmlStyle(this.editor.document));this.updateInvisibleEls();this.editableEl.addEventListener("dragstart",this.onDragStart);});onWillUnmount(()=>{this.editableEl.removeEventListener("dragstart",this.onDragStart);});onWillUpdateProps((nextProps)=>{if(nextProps.isMobile!==this.props.isMobile){this.updateInvisibleEls(nextProps.isMobile);this.invisibleElementsPanelState.invisibleSelector=this.getInvisibleSelector(nextProps.isMobile);}});this.noSelectionTab="blocks";}
async triggerDomUpdated(){this.lastTrigerUpdateId++;const currentTriggerId=this.lastTrigerUpdateId;const getStatePromises=[];const{promise:updatePromise,resolve}=Promise.withResolvers();this.editorBus.trigger("DOM_UPDATED",{getStatePromises,updatePromise});await Promise.allSettled(getStatePromises);const isLastTriggerId=this.lastTrigerUpdateId===currentTriggerId;resolve(isLastTriggerId);}
get displayOnlyCustomizeTab(){return this.props.config.isTranslationMode;}
getInvisibleSelector(isMobile=this.props.isMobile){return`.o_snippet_invisible, ${
            isMobile ? ".o_snippet_mobile_invisible" : ".o_snippet_desktop_invisible"
        }`;}
onTabClick(tab,presetId=null){if(this.state.activeTab===tab){return;}
this.setTab(tab);if(tab==="theme"||tab==="blocks"){this.colorPresetToShow=presetId;this.activeTargetEl=this.activeTargetEl||this.getActiveTarget();this.editor.shared.builderOptions.deactivateContainers();}else if(this.activeTargetEl){if(isVisible(this.activeTargetEl)){this.editor.shared.builderOptions.updateContainers(this.activeTargetEl);}
this.activeTargetEl=null;}}
setTab(tab){this.state.activeTab=tab;this.noSelectionTab=tab==="theme"?"theme":"blocks";}
undo(){this.editor.shared.operation.next(()=>this.editor.shared.history.undo());}
redo(){this.editor.shared.operation.next(()=>this.editor.shared.history.redo());}
onMobilePreviewClick(){this.props.toggleMobile();this.editor.resources["on_mobile_preview_clicked"].forEach((handler)=>handler());}
updateInvisibleEls(isMobile=this.props.isMobile){this.invisibleElementsPanelState.invisibleEls=[...this.editor.editable.querySelectorAll(this.getInvisibleSelector(isMobile)),];}
lowerPanelEntries(){return this.editor.resources["lower_panel_entries"]??[];}
editColorCombination(presetId){this.onTabClick("theme",presetId);}
getActiveTarget(){return this.editor.shared["builderOptions"].getContainers().at(-1)?.element;}}
return __exports;});;

/* /html_builder/static/src/core/anchor/anchor_dialog.js */
odoo.define('@html_builder/core/anchor/anchor_dialog',['@odoo/owl','@web/core/l10n/translation','@web/core/dialog/dialog'],function(require){'use strict';let __exports={};const{Component,useRef,useState}=require("@odoo/owl");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{Dialog}=require("@web/core/dialog/dialog");const AnchorDialog=__exports.AnchorDialog=class AnchorDialog extends Component{static template="html_builder.AnchorDialog";static components={Dialog};static props={currentAnchorName:{type:String},renameAnchor:{type:Function},deleteAnchor:{type:Function},formatAnchor:{type:Function},close:{type:Function},};setup(){this.title=_t("Link Anchor");this.inputRef=useRef("anchor-input");this.state=useState({isValid:true});}
async onConfirmClick(){const newAnchorName=this.props.formatAnchor(this.inputRef.el.value);if(newAnchorName===this.props.currentAnchorName){this.props.close();}
this.state.isValid=await this.props.renameAnchor(newAnchorName);if(this.state.isValid){this.props.close();}}
onRemoveClick(){this.props.deleteAnchor();this.props.close();}}
return __exports;});;

/* /html_builder/static/src/core/anchor/anchor_plugin.js */
odoo.define('@html_builder/core/anchor/anchor_plugin',['@html_editor/plugin','@html_editor/utils/resource','@web/core/browser/browser','@web/core/l10n/translation','@odoo/owl','@html_builder/core/anchor/anchor_dialog','@html_builder/utils/utils'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{browser}=require("@web/core/browser/browser");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{markup}=require("@odoo/owl");const{AnchorDialog}=require("@html_builder/core/anchor/anchor_dialog");const{getElementsWithOption}=require("@html_builder/utils/utils");const anchorSelector=":not(p).oe_structure > *, :not(p)[data-oe-type=html] > *, .accordion-item";const anchorExclude=".modal *, .oe_structure .oe_structure *, [data-oe-type=html] .oe_structure *, .s_popup";const TITLE_SELECTOR="h1, h2, h3, h4, h5, h6, .h1-fs, .h2-fs, .h3-fs, .h4-fs, .h5-fs, .h6-fs, .display-1-fs, .display-2-fs, .display-3-fs, display-4-fs, .base-fs, .o_small-fs";__exports.canHaveAnchor=canHaveAnchor;function canHaveAnchor(element){return element.matches(anchorSelector)&&!element.matches(anchorExclude);}
const AnchorPlugin=__exports.AnchorPlugin=class AnchorPlugin extends Plugin{static id="anchor";static dependencies=["history"];static shared=["createOrEditAnchorLink"];resources={on_cloned_handlers:this.onCloned.bind(this),get_options_container_top_buttons:withSequence(0,this.getOptionsContainerTopButtons.bind(this)),};onCloned({cloneEl}){const anchorEls=getElementsWithOption(cloneEl,anchorSelector,anchorExclude);anchorEls.forEach((anchorEl)=>this.deleteAnchor(anchorEl));}
getOptionsContainerTopButtons(el){if(!canHaveAnchor(el)){return[];}
return[{class:"fa fa-fw fa-link oe_snippet_anchor btn o-hb-btn btn-accent-color-hover",title:_t("Create and copy a link targeting this block or edit it"),handler:this.createOrEditAnchorLink.bind(this),},];}
isModal(element){return element.classList.contains("modal");}
setAnchorName(element,value){if(value){element.id=value;if(!this.isModal(element)){element.dataset.anchor=true;}}else{this.deleteAnchor(element);}
this.dependencies.history.addStep();}
createAnchor(element){const titleEls=element.querySelectorAll(TITLE_SELECTOR);const title=titleEls.length>0?titleEls[0].innerText:element.dataset.name;const anchorName=this.formatAnchor(title);let n="";while(this.document.getElementById(anchorName+n)){n=(n||1)+1;}
this.setAnchorName(element,anchorName+n);}
deleteAnchor(element){element.removeAttribute("data-anchor");element.removeAttribute("id");}
getAnchorLink(element){const pathName=this.isModal(element)?"":this.document.location.pathname;return`${pathName}#${element.id}`;}
async createOrEditAnchorLink(element){if(!element.id){this.createAnchor(element);}
const anchorLink=this.getAnchorLink(element);await browser.navigator.clipboard.writeText(anchorLink);const message=_t("Anchor copied to clipboard%(br)s%(open_span)sLink: %(anchor_link)s%(close_span)s",{open_span:markup`<span style=" display: -webkit-box; -webkit-line-clamp: 1;
                    -webkit-box-orient: vertical; overflow: hidden;">`,anchor_link:anchorLink,br:markup`<br>`,close_span:markup`</span>`,});const closeNotification=this.services.notification.add(message,{type:"success",buttons:[{name:_t("Edit"),primary:true,onClick:()=>{closeNotification();this.services.dialog.add(AnchorDialog,{currentAnchorName:decodeURIComponent(element.id),renameAnchor:async(anchorName)=>{const alreadyExists=!!this.document.getElementById(anchorName);if(alreadyExists){return false;}
this.setAnchorName(element,anchorName);await this.createOrEditAnchorLink(element);return true;},deleteAnchor:()=>{this.deleteAnchor(element);this.dependencies.history.addStep();},formatAnchor:this.formatAnchor,});},},],});}
formatAnchor(text){return encodeURIComponent(text.trim().replace(/\s+/g,"-"));}}
return __exports;});;

/* /html_builder/static/src/core/builder_action.js */
odoo.define('@html_builder/core/builder_action',[],function(require){'use strict';let __exports={};const BuilderAction=__exports.BuilderAction=class BuilderAction{static dependencies=[];static cancelReload=Symbol("cancel reload");constructor(context){this.document=context.document;this.window=context.document.defaultView;this.editable=context.editable;this.config=context.config;this.services=context.services;this.dependencies=context.dependencies;this.getResource=context.getResource;this.dispatchTo=context.dispatchTo;this.delegateTo=context.delegateTo;this.checkPredicates=context.checkPredicates;this.setup();this.preview??=this.reload?false:true;this.withLoadingEffect??=true;this.loadOnClean??=false;this.canTimeout??=!this.has("load");}
setup(){}
async prepare(context){}
getPriority(context){}
async apply(context){}
getValue(context){}
isApplied(context){}
async clean(context){}
async load(context){}
has(method){const baseMethod=BuilderAction.prototype[method];const actualMethod=this.constructor.prototype[method];return baseMethod!==actualMethod;}}
return __exports;});;

/* /html_builder/static/src/core/builder_actions_plugin.js */
odoo.define('@html_builder/core/builder_actions_plugin',['@html_editor/plugin'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const BuilderActionsPlugin=__exports.BuilderActionsPlugin=class BuilderActionsPlugin extends Plugin{static id="builderActions";static shared=["getAction","applyAction"];static dependencies=["operation","history"];setup(){this.actions={};for(const actions of this.getResource("builder_actions")){for(const Action of Object.values(actions)){if(Action.id in this.actions){throw new Error(`Duplicate builder action id: ${Action.id}`);}
this.actions[Action.id]=new Action(this.__editor.getEditorContext(Action.dependencies));}}
Object.freeze(this.actions);}
getAction(actionId){const action=this.actions[actionId];if(!action){throw new Error(`Unknown builder action id: ${actionId}`);}
return action;}
applyAction(actionId,spec){const action=this.getAction(actionId);this.dependencies.operation.next(async()=>{await action.apply(spec);this.dependencies.history.addStep();},{...action,load:async()=>{if(action.load){const loadResult=await action.load(spec);spec.loadResult=loadResult;}},});}}
return __exports;});;

/* /html_builder/static/src/core/builder_component_plugin.js */
odoo.define('@html_builder/core/builder_component_plugin',['@html_builder/core/building_blocks/builder_list','@web/core/dropdown/dropdown_item','@html_builder/core/building_blocks/builder_button_group','@web/core/dropdown/dropdown','@html_builder/core/building_blocks/builder_datetimepicker','@html_builder/core/building_blocks/builder_row','@html_builder/core/building_blocks/builder_button','@html_builder/core/building_blocks/builder_number_input','@html_builder/core/building_blocks/builder_select','@html_builder/core/building_blocks/builder_select_item','@html_builder/core/building_blocks/builder_colorpicker','@html_builder/core/building_blocks/builder_text_input','@html_builder/core/building_blocks/builder_checkbox','@html_builder/core/building_blocks/builder_range','@html_builder/core/building_blocks/builder_context','@html_builder/core/building_blocks/basic_many2many','@html_builder/core/building_blocks/builder_many2many','@html_builder/core/building_blocks/builder_many2one','@html_builder/core/building_blocks/model_many2many','@html_editor/plugin','@html_builder/core/img','@html_builder/core/building_blocks/builder_urlpicker','@html_builder/core/building_blocks/builder_fontfamilypicker'],function(require){'use strict';let __exports={};const{BuilderList}=require("@html_builder/core/building_blocks/builder_list");const{DropdownItem}=require("@web/core/dropdown/dropdown_item");const{BuilderButtonGroup}=require("@html_builder/core/building_blocks/builder_button_group");const{Dropdown}=require("@web/core/dropdown/dropdown");const{BuilderDateTimePicker}=require("@html_builder/core/building_blocks/builder_datetimepicker");const{BuilderRow}=require("@html_builder/core/building_blocks/builder_row");const{BuilderButton}=require("@html_builder/core/building_blocks/builder_button");const{BuilderNumberInput}=require("@html_builder/core/building_blocks/builder_number_input");const{BuilderSelect}=require("@html_builder/core/building_blocks/builder_select");const{BuilderSelectItem}=require("@html_builder/core/building_blocks/builder_select_item");const{BuilderColorPicker}=require("@html_builder/core/building_blocks/builder_colorpicker");const{BuilderTextInput}=require("@html_builder/core/building_blocks/builder_text_input");const{BuilderCheckbox}=require("@html_builder/core/building_blocks/builder_checkbox");const{BuilderRange}=require("@html_builder/core/building_blocks/builder_range");const{BuilderContext}=require("@html_builder/core/building_blocks/builder_context");const{BasicMany2Many}=require("@html_builder/core/building_blocks/basic_many2many");const{BuilderMany2Many}=require("@html_builder/core/building_blocks/builder_many2many");const{BuilderMany2One}=require("@html_builder/core/building_blocks/builder_many2one");const{ModelMany2Many}=require("@html_builder/core/building_blocks/model_many2many");const{Plugin}=require("@html_editor/plugin");const{Img}=require("@html_builder/core/img");const{BuilderUrlPicker}=require("@html_builder/core/building_blocks/builder_urlpicker");const{BuilderFontFamilyPicker}=require("@html_builder/core/building_blocks/builder_fontfamilypicker");const BuilderComponentPlugin=__exports.BuilderComponentPlugin=class BuilderComponentPlugin extends Plugin{static id="builderComponents";static shared=["getComponents"];resources={builder_components:{BuilderContext,BuilderFontFamilyPicker,BuilderRow,BuilderUrlPicker,Dropdown,DropdownItem,BuilderButtonGroup,BuilderButton,BuilderTextInput,BuilderNumberInput,BuilderRange,BuilderColorPicker,BuilderSelect,BuilderSelectItem,BuilderCheckbox,BasicMany2Many,BuilderMany2Many,BuilderMany2One,ModelMany2Many,BuilderDateTimePicker,BuilderList,Img,},};setup(){this.Components={};for(const r of this.getResource("builder_components")){for(const C in r){if(C in this.Components){throw new Error(`Duplicated builder component: ${C}`);}
this.Components[C]=r[C];}}}
getComponents(){return this.Components;}}
return __exports;});;

/* /html_builder/static/src/core/builder_content_editable_plugin.js */
odoo.define('@html_builder/core/builder_content_editable_plugin',['@html_editor/plugin','@html_editor/utils/dom_traversal','@web/core/registry'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{selectElements}=require("@html_editor/utils/dom_traversal");const{registry}=require("@web/core/registry");const BuilderContentEditablePlugin=__exports.BuilderContentEditablePlugin=class BuilderContentEditablePlugin extends Plugin{static id="builderContentEditablePlugin";resources={content_not_editable_selectors:["section:has(> .o_container_small, > .container, > .container-fluid)",".o_not_editable","[data-oe-field='arch']:empty",],content_editable_selectors:["section > .o_container_small","section > .container","section > .container-fluid",".o_editable",],valid_contenteditable_predicates:this.isValidContentEditable.bind(this),content_editable_providers:this.getContentEditableEls.bind(this),content_not_editable_providers:this.getContentNotEditableEls.bind(this),contenteditable_to_remove_selector:"[contenteditable]",};setup(){this.editable.setAttribute("contenteditable",false);}
getContentEditableEls(rootEl){const editableSelector=this.getResource("content_editable_selectors").join(",");return[...selectElements(rootEl,editableSelector)];}
getContentNotEditableEls(rootEl){const notEditableSelector=this.getResource("content_not_editable_selectors").join(",");return[...selectElements(rootEl,notEditableSelector)];}
isValidContentEditable(contentEditableEl){const isDescendantOfNotEditableNotSnippet=(el)=>{let notEditableEl=el.closest(".o_not_editable");if(!notEditableEl){return false;}
while(notEditableEl.parentElement.closest(".o_not_editable")){notEditableEl=notEditableEl.parentElement.closest(".o_not_editable");}
return!notEditableEl.closest("[data-snippet]");};return(!contentEditableEl.matches("input, [data-oe-readonly]")&&contentEditableEl.closest(".o_editable")&&!isDescendantOfNotEditableNotSnippet(contentEditableEl));}}
registry.category("builder-plugins").add(BuilderContentEditablePlugin.id,BuilderContentEditablePlugin);return __exports;});;

/* /html_builder/static/src/core/builder_options_plugin.js */
odoo.define('@html_builder/core/builder_options_plugin',['@html_editor/plugin','@web/core/utils/functions','@html_builder/core/remove_plugin','@html_builder/core/clone_plugin','@html_builder/utils/utils','@html_builder/utils/utils_css','@html_builder/sidebar/option_container'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{uniqueId}=require("@web/core/utils/functions");const{isRemovable}=require("@html_builder/core/remove_plugin");const{isClonable}=require("@html_builder/core/clone_plugin");const{getElementsWithOption,isElementInViewport}=require("@html_builder/utils/utils");const{shouldEditableMediaBeEditable}=require("@html_builder/utils/utils_css");const{OptionsContainer}=require("@html_builder/sidebar/option_container");const BuilderOptionsPlugin=__exports.BuilderOptionsPlugin=class BuilderOptionsPlugin extends Plugin{static id="builderOptions";static dependencies=["selection","overlay","operation","history","builderOverlay","overlayButtons",];static shared=["computeContainers","findOption","getContainers","updateContainers","deactivateContainers","getTarget","getPageContainers","getRemoveDisabledReason","getCloneDisabledReason","getReloadSelector","setNextTarget","getBuilderOptionContext",];resources={before_add_step_handlers:this.onWillAddStep.bind(this),step_added_handlers:this.onStepAdded.bind(this),post_undo_handlers:(revertedStep)=>this.restoreContainers(revertedStep,"undo"),post_redo_handlers:(revertedStep)=>this.restoreContainers(revertedStep,"redo"),clean_for_save_handlers:this.cleanForSave.bind(this),start_edition_handlers:()=>{if(this.config.initialTarget){const el=this.editable.querySelector(this.config.initialTarget);this.updateContainers(el);}},};setup(){this.builderOptions=this.getResource("builder_options");this.builderOptionsContext=new Map();this.builderOptionsDependencies=new Map();const options=this.builderOptions.concat([OptionsContainer]);for(const Option of options){if(isLegacyOption(Option)){continue;}
this.getBuilderDependencies(Option);this.getBuilderOptionContext(Option);}
this.elementsToOptionsTitleComponents=withIds(this.getResource("elements_to_options_title_components"));this.getResource("patch_builder_options").forEach((option)=>{this.patchBuilderOptions(option);});this.builderHeaderMiddleButtons=withIds(this.getResource("builder_header_middle_buttons"));this.builderContainerTitle=withIds(this.getResource("container_title"));this.onClick=this.onClick.bind(this);this.editable.addEventListener("click",this.onClick,{capture:true});this.lastContainers=[];this.notActivableElementsSelector=["#web_editor-top-edit","#oe_manipulators",".oe_drop_zone",".o_notification_manager",".o_we_no_overlay",".ui-autocomplete",".modal .btn-close",".transfo-container",".o_datetime_picker",].join(", ");}
destroy(){this.editable.removeEventListener("click",this.onClick,{capture:true});}
onClick(ev){this.dependencies.operation.next(()=>{this.updateContainers(ev.target);});}
getReloadSelector(editingElement){for(const container of[...this.lastContainers].reverse()){for(const option of container.options){if(option.reloadTarget){return option.selector;}}}
if(editingElement.closest("header")){return"header";}
if(editingElement.closest("main")){return"main";}
if(editingElement.closest("footer")){return"footer";}
return null;}
updateContainers(target,{forceUpdate=false}={}){if(this.dependencies.history.getIsCurrentStepModified()){console.warn("Should not have any mutations in the current step when you update the container selection");}
if(this.dependencies.history.getIsPreviewing()){return;}
if(target){if(target.closest(this.notActivableElementsSelector)){return;}
this.target=target;}
if(!this.target||!this.target.isConnected){const connectedContainers=this.lastContainers.filter((c)=>c.element.isConnected);this.target=connectedContainers.at(-1)?.element;}
const newContainers=this.computeContainers(this.target);if(newContainers.length===0&&this.lastContainers.length===0){return;}
if(!forceUpdate&&this.target?.isConnected&&newContainers.length===this.lastContainers.length){const previousIds=this.lastContainers.map((c)=>c.id);const newIds=newContainers.map((c)=>c.id);const areSameElements=newIds.every((id,i)=>id===previousIds[i]);const previousOverlays=this.lastContainers.map((c)=>c.hasOverlayOptions);const newOverlays=newContainers.map((c)=>c.hasOverlayOptions);const areSameOverlays=previousOverlays.every((check,i)=>check===newOverlays[i]);if(areSameElements&&areSameOverlays){const previousOptions=this.lastContainers.flatMap((c)=>[...c.options,...c.headerMiddleButtons,c.containerTitle,]);const newOptions=newContainers.flatMap((c)=>[...c.options,...c.headerMiddleButtons,c.containerTitle,]);const areSameOptions=newOptions.length===previousOptions.length&&newOptions.every((option,i)=>option.id===previousOptions[i].id);if(areSameOptions){return;}}}
this.lastContainers=newContainers;this.dispatchTo("change_current_options_containers_listeners",this.lastContainers);}
getTarget(){return this.target;}
deactivateContainers(){this.target=null;this.lastContainers=[];this.dispatchTo("change_current_options_containers_listeners",this.lastContainers);}
computeContainers(target){const mapElementsToOptions=(Options)=>{const map=new Map();for(const Option of Options){const{selector,exclude,editableOnly}=Option;let elements=getClosestElements(target,selector);if(!elements.length){continue;}
elements=elements.filter((el)=>checkElement(el,{exclude,editableOnly}));for(const element of elements){if(map.has(element)){map.get(element).push(Option);}else{map.set(element,[Option]);}}}
return map;};const elementToOptions=mapElementsToOptions(this.builderOptions);const elementToHeaderMiddleButtons=mapElementsToOptions(this.builderHeaderMiddleButtons);const elementToContainerTitle=mapElementsToOptions(this.builderContainerTitle);const elementToOptionTitleComponents=mapElementsToOptions(this.elementsToOptionsTitleComponents);let element=target;while(element&&!elementToOptions.has(element)){if(this.hasOverlayOptions(element)){elementToOptions.set(element,[]);break;}
element=element.parentElement;}
const previousElementToIdMap=new Map(this.lastContainers.map((c)=>[c.element,c.id]));let containers=[...elementToOptions].sort(([a],[b])=>(b.contains(a)?1:-1)).map(([element,options])=>({id:previousElementToIdMap.get(element)||uniqueId(),element,options,optionTitleComponents:elementToOptionTitleComponents.get(element)||[],headerMiddleButtons:elementToHeaderMiddleButtons.get(element)||[],containerTitle:elementToContainerTitle.get(element)?elementToContainerTitle.get(element)[0]:{},hasOverlayOptions:this.hasOverlayOptions(element),isRemovable:isRemovable(element),removeDisabledReason:this.getRemoveDisabledReason(element),isClonable:isClonable(element),cloneDisabledReason:this.getCloneDisabledReason(element),optionsContainerTopButtons:this.getOptionsContainerTopButtons(element),}));const lastValidContainerIdx=containers.findLastIndex((c)=>this.getResource("no_parent_containers").some((selector)=>c.element.matches(selector)));if(lastValidContainerIdx>0){containers=containers.slice(lastValidContainerIdx);}
return containers;}
getPageContainers(){return this.computeContainers(this.editable.querySelector("main"));}
getContainers(){return this.lastContainers;}
hasOverlayOptions(el){const parentEl=el.parentElement;const isAloneInColumn=parentEl?.children.length===1&&parentEl.matches(".row > div");const isInnerSnippet=this.config.snippetModel.isInnerContent(el);const keepOptions=this.delegateTo("keep_overlay_options",el);if(isInnerSnippet&&isAloneInColumn&&!keepOptions){return false;}
for(const{hasOption,editableOnly}of this.getResource("has_overlay_options")){if(checkElement(el,{editableOnly})&&hasOption(el)){return true;}}
return false;}
getOptionsContainerTopButtons(el){const buttons=[];for(const getContainerButtons of this.getResource("get_options_container_top_buttons")){buttons.push(...getContainerButtons(el));for(const button of buttons){const handler=button.handler;button.handler=(...args)=>{this.dependencies.operation.next(async()=>{await handler(...args);this.dependencies.history.addStep();});};}}
return buttons;}
cleanForSave({root}){for(const Option of this.builderOptions){const{selector,exclude,cleanForSave}=Option;if(!cleanForSave){continue;}
for(const el of getElementsWithOption(root,selector,exclude)){const context=isLegacyOption(Option)?undefined:this.getBuilderOptionContext(Option);cleanForSave(el,context);}}}
setNextTarget(targetEl){if(this.dependencies.history.getIsPreviewing()){return;}
this.dependencies.history.setStepExtra("nextTarget",targetEl);}
onWillAddStep(){this.dependencies.history.setStepExtra("currentTarget",this.target);}
onStepAdded({step}){const nextTargetEl=step.extraStepInfos.nextTarget;if(nextTargetEl){this.updateContainers(nextTargetEl,{forceUpdate:true});}else if(nextTargetEl===false){this.deactivateContainers();}else{this.updateContainers();}}
restoreContainers(revertedStep,mode){if(revertedStep&&revertedStep.extraStepInfos.currentTarget){let targetEl=revertedStep.extraStepInfos.currentTarget;const nextTarget=revertedStep.extraStepInfos.nextTarget;if(mode==="redo"&&(nextTarget||nextTarget===false)){targetEl=nextTarget;}
if(targetEl){this.dispatchTo("on_restore_containers_handlers",targetEl);this.updateContainers(targetEl,{forceUpdate:true});if(!isElementInViewport(targetEl)){targetEl.scrollIntoView({behavior:"smooth",block:"start"});}}else{this.deactivateContainers();}}}
getRemoveDisabledReason(el){const reasons=[];this.dispatchTo("remove_disabled_reason_providers",{el,reasons});return reasons.length?reasons.join(" "):undefined;}
getCloneDisabledReason(el){const reasons=[];this.dispatchTo("clone_disabled_reason_providers",{el,reasons});return reasons.length?reasons.join(" "):undefined;}
patchBuilderOptions({target_name,target_element,method,value}){if(!target_name||!target_element||!method||(!value&&method!=="remove")){throw new Error(`Missing patch_builder_options required parameters: target_name, target_element, method, value`);}
const builderOption=this.builderOptions.find((option)=>option.name===target_name);if(!builderOption){throw new Error(`Builder option ${target_name} not found`);}
switch(method){case"replace":builderOption[target_element]=value;break;case"remove":delete builderOption[target_element];break;case"add":if(!builderOption[target_element]){throw new Error(`Builder option ${target_name} does not have ${target_element}`);}
builderOption[target_element]+=`, ${value}`;break;default:throw new Error(`Unknown method ${method}`);}}
findOption(el,optionName,allowParent=false){let containers=this.getContainers().filter((container)=>container.element.contains(el));containers.reverse();if(!allowParent){containers=[containers[0]];}
let targetEl,requestedOption;for(const{element,options}of containers){requestedOption=options.find((option)=>{if(option.OptionComponent){return option.OptionComponent.name===optionName;}else{return option.template.split(".").at(-1)===optionName;}});if(requestedOption){const{applyTo}=requestedOption;targetEl=applyTo?element.querySelector(applyTo):element;break;}}
return{option:requestedOption,targetEl};}
getBuilderDependencies(OptionComponent){const cachedDeps=this.builderOptionsDependencies.get(OptionComponent);if(cachedDeps){return cachedDeps;}
const deps=OptionComponent.dependencies||[];this.builderOptionsDependencies.set(OptionComponent,deps);const childDeps=Object.values(OptionComponent.components||{}).flatMap(this.getBuilderDependencies.bind(this));deps.push(...childDeps);return deps;}
getBuilderOptionContext(OptionComponent){const context=this.builderOptionsContext.get(OptionComponent);if(!context){const deps=this.getBuilderDependencies(OptionComponent);const context=this.__editor.getEditorContext(deps);this.builderOptionsContext.set(OptionComponent,context);return context;}
return context;}}
function getClosestElements(element,selector){if(!element){return[];}
const parent=element.closest(selector);return parent?[parent,...getClosestElements(parent.parentElement,selector)]:[];}
__exports.checkElement=checkElement;function checkElement(el,{editableOnly=true,exclude=""}){if(editableOnly&&!el.closest(".o_editable")){return false;}
exclude+=`${exclude && ", "}.o_snippet_not_selectable`;if(el.matches(exclude)){return false;}
if(!editableOnly){return true;}
if(el.matches(".o_editable_media")){return shouldEditableMediaBeEditable(el);}
return!el.matches('.o_not_editable:not(.s_social_media) :not([contenteditable="true"])');}
function withIds(arr){return arr.map((el)=>({...el,id:uniqueId()}));}
__exports.isLegacyOption=isLegacyOption;function isLegacyOption(option){return typeof option==="object";}
return __exports;});;

/* /html_builder/static/src/core/builder_options_plugin_translate.js */
odoo.define('@html_builder/core/builder_options_plugin_translate',['@html_builder/sidebar/option_container','@html_editor/plugin','@html_builder/core/builder_options_plugin'],function(require){'use strict';let __exports={};const{OptionsContainer}=require("@html_builder/sidebar/option_container");const{Plugin}=require("@html_editor/plugin");const{BuilderOptionsPlugin}=require("@html_builder/core/builder_options_plugin");const BuilderOptionsTranslationPlugin=__exports.BuilderOptionsTranslationPlugin=class BuilderOptionsTranslationPlugin extends Plugin{static id="builderOptions";static shared=["deactivateContainers","getTarget","updateContainers","setNextTarget","getBuilderOptionContext","getRemoveDisabledReason","getCloneDisabledReason",];static dependencies=["history"];setup(){this.builderOptions=this.getResource("translate_options");this.builderOptionsContext=new Map();this.builderOptionsDependencies=new Map();const options=this.builderOptions.concat([OptionsContainer]);for(const Option of options){this.getBuilderDependencies(Option);this.getBuilderOptionContext(Option);}}
deactivateContainers(){}
getTarget(){}
getRemoveDisabledReason(){}
getCloneDisabledReason(){}
updateContainers(){}
setNextTarget(targetEl){this.dependencies.history.setStepExtra("nextTarget",targetEl);}}
BuilderOptionsTranslationPlugin.prototype.getBuilderDependencies=BuilderOptionsPlugin.prototype.getBuilderDependencies;BuilderOptionsTranslationPlugin.prototype.getBuilderOptionContext=BuilderOptionsPlugin.prototype.getBuilderOptionContext;return __exports;});;

/* /html_builder/static/src/core/builder_overlay/builder_overlay.js */
odoo.define('@html_builder/core/builder_overlay/builder_overlay',['@web/core/utils/render','@html_builder/utils/grid_layout_utils'],function(require){'use strict';let __exports={};const{renderToElement}=require("@web/core/utils/render");const{addBackgroundGrid,getGridProperties,getGridItemProperties,resizeGrid,setElementToMaxZindex,}=require("@html_builder/utils/grid_layout_utils");const sizingY=__exports.sizingY={selector:"section, .row > div, .parallax, .s_hr, .carousel-item, .s_rating",exclude:"section:has(> .carousel), .s_image_gallery .carousel-item, .s_col_no_resize.row > div, .s_col_no_resize",};const sizingX=__exports.sizingX={selector:".row > div",exclude:".s_col_no_resize.row > div, .s_col_no_resize",};const sizingGrid=__exports.sizingGrid={selector:".row > div",exclude:".s_col_no_resize.row > div, .s_col_no_resize",};const BuilderOverlay=__exports.BuilderOverlay=class BuilderOverlay{constructor(overlayTarget,{iframe,overlayContainer,history,hasOverlayOptions,next,isMobileView,mobileBreakpoint,isRtl,}){this.history=history;this.next=next;this.hasOverlayOptions=hasOverlayOptions;this.iframe=iframe;this.overlayContainer=overlayContainer;this.overlayElement=renderToElement("html_builder.BuilderOverlay");this.overlayTarget=overlayTarget;this.hasSizingHandles=this.hasSizingHandles();this.handlesWrapperEl=this.overlayElement.querySelector(".o_handles");this.handleEls=this.overlayElement.querySelectorAll(".o_handle");this.yHandles=this.handlesWrapperEl.querySelectorAll(`.n:not(.o_grid_handle), .s:not(.o_grid_handle)`);this.xHandles=this.handlesWrapperEl.querySelectorAll(`.e:not(.o_grid_handle), .w:not(.o_grid_handle)`);this.gridHandles=this.handlesWrapperEl.querySelectorAll(".o_grid_handle");this.isMobileView=isMobileView;this.mobileBreakpoint=mobileBreakpoint;this.isRtl=isRtl;this.initHandles();this.initSizing();this.refreshHandles();}
hasSizingHandles(){if(!this.hasOverlayOptions){return false;}
return this.isResizableY()||this.isResizableX()||this.isResizableGrid();}
isActive(){return this.overlayElement.matches(".oe_active, .o_we_overlay_preview");}
refreshPosition(){if(!this.isActive()){return;}
const openModalEl=this.overlayTarget.querySelector(".modal.show");const overlayTarget=openModalEl?openModalEl:this.overlayTarget;const iframeRect=this.iframe.getBoundingClientRect();const overlayContainerRect=this.overlayContainer.getBoundingClientRect();const targetRect=overlayTarget.getBoundingClientRect();const isMobile=this.isMobileView(overlayTarget);const iframeScaleX=isMobile?iframeRect.width/this.iframe.offsetWidth:1;const iframeScaleY=isMobile?iframeRect.height/this.iframe.offsetHeight:1;Object.assign(this.overlayElement.style,{width:`${targetRect.width * iframeScaleX}px`,height:`${targetRect.height * iframeScaleY}px`,top:`${
                iframeRect.y - overlayContainerRect.y + window.scrollY + targetRect.y * iframeScaleY
            }px`,left:`${
                iframeRect.x - overlayContainerRect.x + window.scrollX + targetRect.x * iframeScaleX
            }px`,});this.handlesWrapperEl.style.height=`${targetRect.height * iframeScaleY}px`;}
refreshHandles(){if(!this.hasSizingHandles||!this.isActive()){return;}
if(this.overlayTarget.parentNode?.classList.contains("row")){const isMobile=this.isMobileView(this.overlayTarget);const isGridOn=this.overlayTarget.classList.contains("o_grid_item");const isGrid=!isMobile&&isGridOn;this.handleEls.forEach((handleEl)=>{const isGridHandle=handleEl.classList.contains("o_grid_handle");handleEl.classList.toggle("d-none",isGrid^isGridHandle);const isVerticalSizing=handleEl.matches(".n, .s");handleEl.classList.toggle("readonly",isMobile&&isVerticalSizing&&isGridOn);});}
this.updateHandleY();}
toggleOverlay(show){this.overlayElement.classList.toggle("oe_active",show);this.refreshPosition();this.refreshHandles();}
toggleOverlayPreview(show){this.overlayElement.classList.toggle("o_we_overlay_preview",show);this.refreshPosition();this.refreshHandles();}
toggleOverlayVisibility(show){if(!this.isActive()){return;}
this.overlayElement.classList.toggle("o_overlay_hidden",!show);}
destroy(){if(!this.hasSizingHandles){return;}
this.handleEls.forEach((handleEl)=>handleEl.removeEventListener("pointerdown",this._onSizingStart));}
isResizableY(){return(this.overlayTarget.matches(sizingY.selector)&&!this.overlayTarget.matches(sizingY.exclude));}
isResizableX(){return(this.overlayTarget.matches(sizingX.selector)&&!this.overlayTarget.matches(sizingX.exclude));}
isResizableGrid(){return(this.overlayTarget.matches(sizingGrid.selector)&&!this.overlayTarget.matches(sizingGrid.exclude));}
initHandles(){if(!this.hasSizingHandles){return;}
if(this.isResizableY()){this.yHandles.forEach((handleEl)=>handleEl.classList.remove("readonly"));}
if(this.isResizableX()){this.xHandles.forEach((handleEl)=>handleEl.classList.remove("readonly"));}
if(this.isResizableGrid()){this.gridHandles.forEach((handleEl)=>handleEl.classList.remove("readonly"));}}
initSizing(){if(!this.hasSizingHandles){return;}
this._onSizingStart=this.onSizingStart.bind(this);this.handleEls.forEach((handleEl)=>handleEl.addEventListener("pointerdown",this._onSizingStart));}
replaceSizingClass(classRegex,newClass){const newClassName=(this.overlayTarget.className||"").replace(classRegex,"");this.overlayTarget.className=newClassName;this.overlayTarget.classList.add(newClass);}
getSizingYConfig(){const isTargetHR=this.overlayTarget.matches("hr");const nClass=isTargetHR?"mt":"pt";const nProperty=isTargetHR?"margin-top":"padding-top";const sClass=isTargetHR?"mb":"pb";const sProperty=isTargetHR?"margin-bottom":"padding-bottom";const values=[0,4];for(let i=1;i<=256/8;i++){values.push(i*8);}
return{n:{classes:values.map((v)=>nClass+v),values:values,cssProperty:nProperty},s:{classes:values.map((v)=>sClass+v),values:values,cssProperty:sProperty},};}
onResizeY(compass,initialClasses,currentIndex){this.updateHandleY();}
updateHandleY(){this.yHandles.forEach((handleEl)=>{const topOrBottom=handleEl.matches(".n")?"top":"bottom";const padding=window.getComputedStyle(this.overlayTarget)[`padding-${topOrBottom}`];handleEl.style.height=padding;});}
getSizingXConfig(){const resolutionModifier=this.isMobile?"":`${this.mobileBreakpoint}-`;const rowWidth=this.overlayTarget.closest(".row").getBoundingClientRect().width;const valuesE=[1,2,3,4,5,6,7,8,9,10,11,12];const valuesW=[0,1,2,3,4,5,6,7,8,9,10,11];return{e:{classes:valuesE.map((v)=>`col-${resolutionModifier}${v}`),values:valuesE.map((v)=>(rowWidth/12)*v),cssProperty:"width",},w:{classes:valuesW.map((v)=>`offset-${resolutionModifier}${v}`),values:valuesW.map((v)=>(rowWidth/12)*v),cssProperty:"margin-left",},};}
onResizeX(compass,initialClasses,currentIndex){const resolutionModifier=this.isMobile?"":`${this.mobileBreakpoint}-`;const offsetRegex=new RegExp(`(?:^|\\s+)offset-${resolutionModifier}(\\d{1,2})(?!\\S)`);const colRegex=new RegExp(`(?:^|\\s+)col-${resolutionModifier}(\\d{1,2})(?!\\S)`);const initialOffset=Number(initialClasses.match(offsetRegex)?.[1]||0);if(compass==="w"){const initialCol=Number(initialClasses.match(colRegex)?.[1]||12);let offset=Number(this.overlayTarget.className.match(offsetRegex)?.[1]||0);const offsetClass=`offset-${resolutionModifier}${offset}`;let colSize=initialCol-(offset-initialOffset);if(colSize<=0){colSize=1;offset=initialOffset+initialCol-1;}
this.overlayTarget.classList.remove(offsetClass);this.replaceSizingClass(colRegex,`col-${resolutionModifier}${colSize}`);if(offset>0){this.overlayTarget.classList.add(`offset-${resolutionModifier}${offset}`);}
if(this.isMobile&&offset===0){this.overlayTarget.classList.remove(`offset-${this.mobileBreakpoint}-0`);}else{const className=this.overlayTarget.className;const hasDesktopClass=!!className.match(new RegExp(`(^|\\s+)offset-${this.mobileBreakpoint}-\\d{1,2}(?!\\S)`));const hasMobileClass=!!className.match(/(^|\s+)offset-\d{1,2}(?!\S)/);if((this.isMobile&&offset>0&&!hasDesktopClass)||(!this.isMobile&&offset===0&&hasMobileClass)){this.overlayTarget.classList.add(`offset-${this.mobileBreakpoint}-0`);}}}else if(initialOffset>0){const col=Number(this.overlayTarget.className.match(colRegex)?.[1]||0);if(col+initialOffset>12){this.replaceSizingClass(colRegex,`col-${resolutionModifier}${12 - initialOffset}`);}}}
getSizingGridConfig(){const rowEl=this.overlayTarget.closest(".row");const gridProp=getGridProperties(rowEl);const{rowStart,rowEnd,columnStart,columnEnd}=getGridItemProperties(this.overlayTarget);const valuesN=[];const valuesS=[];for(let i=1;i<parseInt(rowEnd)+12;i++){valuesN.push(i);valuesS.push(i+1);}
const valuesW=[1,2,3,4,5,6,7,8,9,10,11,12];const valuesE=[2,3,4,5,6,7,8,9,10,11,12,13];return{n:{classes:valuesN.map((v)=>"g-height-"+(rowEnd-v)),values:valuesN.map((v)=>(gridProp.rowSize+gridProp.rowGap)*(v-1)),cssProperty:"grid-row-start",},s:{classes:valuesS.map((v)=>"g-height-"+(v-rowStart)),values:valuesS.map((v)=>(gridProp.rowSize+gridProp.rowGap)*(v-1)),cssProperty:"grid-row-end",},w:{classes:valuesW.map((v)=>`g-col-${this.mobileBreakpoint}-`+(columnEnd-v)),values:valuesW.map((v)=>(gridProp.columnSize+gridProp.columnGap)*(v-1)),cssProperty:"grid-column-start",},e:{classes:valuesE.map((v)=>`g-col-${this.mobileBreakpoint}-`+(v-columnStart)),values:valuesE.map((v)=>(gridProp.columnSize+gridProp.columnGap)*(v-1)),cssProperty:"grid-column-end",},};}
onResizeGrid(compass,initialClasses,currentIndex){const style=this.overlayTarget.style;if(compass==="n"){const rowEnd=parseInt(style.gridRowEnd);if(currentIndex<0){style.gridRowStart=1;}else if(currentIndex+1>=rowEnd){style.gridRowStart=rowEnd-1;}else{style.gridRowStart=currentIndex+1;}}else if(compass==="s"){const rowStart=parseInt(style.gridRowStart);const rowEnd=parseInt(style.gridRowEnd);if(currentIndex+2<=rowStart){style.gridRowEnd=rowStart+1;}else{style.gridRowEnd=currentIndex+2;}
const rowEl=this.overlayTarget.parentNode;const rowCount=parseInt(rowEl.dataset.rowCount);const backgroundGridEl=rowEl.querySelector(".o_we_background_grid");const backgroundGridRowEnd=parseInt(backgroundGridEl.style.gridRowEnd);let rowMove=0;if(style.gridRowEnd>rowEnd&&style.gridRowEnd>rowCount+1){rowMove=style.gridRowEnd-rowEnd;}else if(style.gridRowEnd<rowEnd&&style.gridRowEnd>=rowCount+1){rowMove=style.gridRowEnd-rowEnd;}
backgroundGridEl.style.gridRowEnd=backgroundGridRowEnd+rowMove;}else if(compass==="w"){const columnEnd=parseInt(style.gridColumnEnd);if(currentIndex<0){style.gridColumnStart=1;}else if(currentIndex+1>=columnEnd){style.gridColumnStart=columnEnd-1;}else{style.gridColumnStart=currentIndex+1;}}else if(compass==="e"){const columnStart=parseInt(style.gridColumnStart);if(currentIndex+2>13){style.gridColumnEnd=13;}else if(currentIndex+2<=columnStart){style.gridColumnEnd=columnStart+1;}else{style.gridColumnEnd=currentIndex+2;}}
if(compass==="n"||compass==="s"){const numberRows=style.gridRowEnd-style.gridRowStart;this.replaceSizingClass(/\s*(g-height-)([0-9-]+)/g,`g-height-${numberRows}`);}
if(compass==="w"||compass==="e"){const numberColumns=style.gridColumnEnd-style.gridColumnStart;this.replaceSizingClass(new RegExp(`\\s*(g-col-${this.mobileBreakpoint}-)([0-9-]+)`,"g"),`g-col-${this.mobileBreakpoint}-${numberColumns}`);}}
getDirections(ev,handleEl,sizingConfig){let compass=false;let XY=false;if(handleEl.matches(".n")){compass="n";XY="Y";}else if(handleEl.matches(".s")){compass="s";XY="Y";}else if(handleEl.matches(".e")){compass="e";XY="X";}else if(handleEl.matches(".w")){compass="w";XY="X";}else if(handleEl.matches(".nw")){compass="nw";XY="YX";}else if(handleEl.matches(".ne")){compass="ne";XY="YX";}else if(handleEl.matches(".sw")){compass="sw";XY="YX";}else if(handleEl.matches(".se")){compass="se";XY="YX";}
if(this.isRtl){if(compass.includes("e")){compass=compass.replace("e","w");}else if(compass.includes("w")){compass=compass.replace("w","e");}}
const currentConfig=[];for(let i=0;i<compass.length;i++){currentConfig.push(sizingConfig[compass[i]]);}
const directions=[];for(const[i,config]of currentConfig.entries()){let currentIndex=0;const cssProperty=config.cssProperty;const cssPropertyValue=parseInt(window.getComputedStyle(this.overlayTarget)[cssProperty]);config.classes.forEach((c,index)=>{if(this.overlayTarget.classList.contains(c)){currentIndex=index;}else if(config.values[index]===cssPropertyValue){currentIndex=index;}});directions.push({config,currentIndex,initialIndex:currentIndex,initialClasses:this.overlayTarget.className,classRegex:new RegExp("\\s*"+config.classes[currentIndex].replace(/[-]*[0-9]+/,"[-]*[0-9]+"),"g"),initialPageXY:ev["page"+XY[i]],XY:XY[i],compass:compass[i],});}
return directions;}
onSizingStart(ev){ev.preventDefault();const pointerDownTime=ev.timeStamp;let sizingResolve;const sizingProm=new Promise((resolve)=>(sizingResolve=()=>resolve()));this.next(async()=>await sizingProm,{withLoadingEffect:false,canTimeout:false});const cancelSizing=this.history.makeSavePoint();const handleEl=ev.currentTarget;const isGridHandle=handleEl.classList.contains("o_grid_handle");this.isMobile=this.isMobileView(this.overlayTarget);let rowEl,backgroundGridEl;if(isGridHandle){rowEl=this.overlayTarget.parentNode;backgroundGridEl=addBackgroundGrid(rowEl,0);setElementToMaxZindex(backgroundGridEl,rowEl);}
let sizingConfig,onResize;if(isGridHandle){sizingConfig=this.getSizingGridConfig();onResize=this.onResizeGrid.bind(this);}else if(handleEl.matches(".n, .s")){sizingConfig=this.getSizingYConfig();onResize=this.onResizeY.bind(this);}else{sizingConfig=this.getSizingXConfig();onResize=this.onResizeX.bind(this);}
const directions=this.getDirections(ev,handleEl,sizingConfig);const cursorClass=`${window.getComputedStyle(handleEl)["cursor"]}-important`;window.document.body.classList.add(cursorClass);const iframeEl=this.overlayTarget.ownerDocument.defaultView.frameElement;iframeEl.classList.add("o_resizing");this.overlayElement.classList.remove("o_handlers_idle");const onSizingMove=(ev)=>{for(const dir of directions){const configValues=dir.config.values;const currentIndex=dir.currentIndex;const currentValue=configValues[currentIndex];let deltaRaw=ev[`page${dir.XY}`]-dir.initialPageXY;if(dir.XY==="X"&&this.isRtl){deltaRaw=-deltaRaw;}
const delta=deltaRaw+configValues[dir.initialIndex];let nextIndex,beforeIndex;if(delta>currentValue){const nextValue=configValues.find((v)=>v>delta);nextIndex=nextValue?configValues.indexOf(nextValue):configValues.length-1;beforeIndex=nextIndex>0?nextIndex-1:currentIndex;}else if(delta<currentValue){const nextValue=configValues.findLast((v)=>v<delta);nextIndex=nextValue?configValues.indexOf(nextValue):0;beforeIndex=nextIndex<configValues.length-1?nextIndex+1:currentIndex;}
let change=false;if(delta!==currentValue){if(beforeIndex!==currentIndex){this.replaceSizingClass(dir.classRegex,dir.config.classes[beforeIndex]);dir.currentIndex=beforeIndex;change=true;}
const threshold=(2*configValues[nextIndex]+configValues[dir.currentIndex])/3;if((delta>currentValue&&delta>threshold)||(delta<currentValue&&delta<threshold)){this.replaceSizingClass(dir.classRegex,dir.config.classes[nextIndex]);dir.currentIndex=nextIndex;change=true;}}
if(change){onResize(dir.compass,dir.initialClasses,dir.currentIndex);}}};const onSizingStop=(ev)=>{ev.preventDefault();window.removeEventListener("pointermove",onSizingMove);window.removeEventListener("pointerup",onSizingStop);window.document.body.classList.remove(cursorClass);iframeEl.classList.remove("o_resizing");this.overlayElement.classList.add("o_handlers_idle");if(isGridHandle){backgroundGridEl.remove();resizeGrid(rowEl);const colClass=[...this.overlayTarget.classList].find((c)=>/^col-/.test(c));const gColClass=[...this.overlayTarget.classList].find((c)=>/^g-col-/.test(c));this.overlayTarget.classList.remove(colClass);this.overlayTarget.classList.add(gColClass.substring(2));}
const wasResized=!directions.every((dir)=>dir.initialIndex===dir.currentIndex);if(wasResized){this.history.addStep();}else{cancelSizing();}
sizingResolve();if(!wasResized){const pointerUpTime=ev.timeStamp;const pointerDownDuration=pointerUpTime-pointerDownTime;if(pointerDownDuration<500){const sameCoordinatesEls=this.overlayTarget.ownerDocument.elementsFromPoint(ev.pageX,ev.pageY);const toBeClickedEl=sameCoordinatesEls.find((el)=>!this.overlayContainer.contains(el)&&!el.matches(".o_loading_screen")&&typeof el.click==="function");if(toBeClickedEl){toBeClickedEl.click();}}}};window.addEventListener("pointermove",onSizingMove);window.addEventListener("pointerup",onSizingStop);}}
return __exports;});;

/* /html_builder/static/src/core/builder_overlay/builder_overlay_plugin.js */
odoo.define('@html_builder/core/builder_overlay/builder_overlay_plugin',['@html_editor/plugin','@web/core/utils/timing','@web/core/utils/scrolling','@html_builder/core/builder_options_plugin','@html_builder/core/builder_overlay/builder_overlay','@html_editor/utils/resource'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{throttleForAnimation}=require("@web/core/utils/timing");const{getScrollingElement,getScrollingTarget}=require("@web/core/utils/scrolling");const{checkElement}=require("@html_builder/core/builder_options_plugin");const{BuilderOverlay,sizingY,sizingX,sizingGrid}=require("@html_builder/core/builder_overlay/builder_overlay");const{withSequence}=require("@html_editor/utils/resource");function isResizable(el){const isResizableY=el.matches(sizingY.selector)&&!el.matches(sizingY.exclude);const isResizableX=el.matches(sizingX.selector)&&!el.matches(sizingX.exclude);const isResizableGrid=el.matches(sizingGrid.selector)&&!el.matches(sizingGrid.exclude);return isResizableY||isResizableX||isResizableGrid;}
const BuilderOverlayPlugin=__exports.BuilderOverlayPlugin=class BuilderOverlayPlugin extends Plugin{static id="builderOverlay";static dependencies=["localOverlay","history","operation"];static shared=["showOverlayPreview","hideOverlayPreview","refreshOverlays"];resources={step_added_handlers:this.refreshOverlays.bind(this),change_current_options_containers_listeners:this.openBuilderOverlays.bind(this),on_mobile_preview_clicked:withSequence(20,this.refreshOverlays.bind(this)),has_overlay_options:{hasOption:(el)=>isResizable(el)},};setup(){this.iframe=this.editable.ownerDocument.defaultView.frameElement;this.overlayContainer=this.dependencies.localOverlay.makeLocalOverlay("builder-overlay-container");this.overlayContainer.addEventListener("wheel",(ev)=>(this.document.documentElement.scrollTop+=ev.deltaY));this.overlays=[];this.resizeObserver=new ResizeObserver(()=>this.refreshPositions());this._refreshOverlays=throttleForAnimation(this.refreshOverlays.bind(this));this.addDomListener(window,"resize",this._refreshOverlays);const onMouseMoveOrDown=throttleForAnimation(()=>{this.toggleOverlaysVisibility(true);this.refreshPositions();this.editable.removeEventListener("mousemove",onMouseMoveOrDown);this.editable.removeEventListener("mousedown",onMouseMoveOrDown);});this.addDomListener(this.editable,"keydown",()=>{this.toggleOverlaysVisibility(false);this.editable.addEventListener("mousemove",onMouseMoveOrDown);this.editable.addEventListener("mousedown",onMouseMoveOrDown);});const scrollingElement=getScrollingElement(this.document);const scrollingTarget=getScrollingTarget(scrollingElement);this.addDomListener(scrollingTarget,"scroll",throttleForAnimation(()=>{this.toggleOverlaysVisibility(false);clearTimeout(this.scrollingTimeout);this.scrollingTimeout=setTimeout(()=>{this.toggleOverlaysVisibility(true);this.refreshPositions();},250);}),{capture:true});this._cleanups.push(()=>{this.removeBuilderOverlays();this.resizeObserver.disconnect();});}
openBuilderOverlays(optionsContainer){this.removeBuilderOverlays();if(!optionsContainer.length){return;}
optionsContainer.forEach((option)=>{const overlay=new BuilderOverlay(option.element,{iframe:this.iframe,overlayContainer:this.overlayContainer,history:this.dependencies.history,hasOverlayOptions:checkElement(option.element,{})&&option.hasOverlayOptions,next:this.dependencies.operation.next,isMobileView:this.config.isMobileView,mobileBreakpoint:this.config.mobileBreakpoint,isRtl:this.config.isEditableRTL,});this.overlays.push(overlay);this.overlayContainer.append(overlay.overlayElement);this.resizeObserver.observe(overlay.overlayTarget,{box:"border-box"});});const innermostOverlay=this.overlays.at(-1);innermostOverlay.toggleOverlay(true);if(!innermostOverlay.hasOverlayOptions){for(let i=this.overlays.length-2;i>=0;i--){const parentOverlay=this.overlays[i];if(parentOverlay.hasOverlayOptions){parentOverlay.toggleOverlay(true);break;}}}}
removeBuilderOverlays(){this.overlays.forEach((overlay)=>{overlay.destroy();overlay.overlayElement.remove();this.resizeObserver.unobserve(overlay.overlayTarget);});this.overlays=[];}
refreshOverlays(){this.overlays.forEach((overlay)=>{overlay.refreshPosition();overlay.refreshHandles();});}
refreshPositions(){this.overlays.forEach((overlay)=>{overlay.refreshPosition();});}
toggleOverlaysVisibility(show){this.overlays.forEach((overlay)=>{overlay.toggleOverlayVisibility(show);});}
showOverlayPreview(el){this.toggleOverlaysVisibility(false);const overlayToShow=this.overlays.find((overlay)=>overlay.overlayTarget===el);if(!overlayToShow){return;}
overlayToShow.toggleOverlayPreview(true);overlayToShow.toggleOverlayVisibility(true);}
hideOverlayPreview(el){const overlayToHide=this.overlays.find((overlay)=>overlay.overlayTarget===el);if(!overlayToHide){return;}
overlayToHide.toggleOverlayPreview(false);this.toggleOverlaysVisibility(true);}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/basic_many2many.js */
odoo.define('@html_builder/core/building_blocks/basic_many2many',['@odoo/owl','@html_builder/core/utils','@html_builder/core/building_blocks/select_many2x'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const{basicContainerBuilderComponentProps}=require("@html_builder/core/utils");const{SelectMany2X}=require("@html_builder/core/building_blocks/select_many2x");const BasicMany2Many=__exports.BasicMany2Many=class BasicMany2Many extends Component{static template="html_builder.BasicMany2Many";static props={...basicContainerBuilderComponentProps,model:String,fields:{type:Array,element:String,optional:true},domain:{type:Array,optional:true},limit:{type:Number,optional:true},selection:{type:Array,element:Object},setSelection:Function,create:{type:Function,optional:true},};static components={SelectMany2X};select(entry){this.props.setSelection([...this.props.selection,entry]);}
unselect(id){this.props.setSelection([...this.props.selection.filter((item)=>item.id!==id)]);}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_button.js */
odoo.define('@html_builder/core/building_blocks/builder_button',['@odoo/owl','@html_builder/core/utils','@html_builder/core/building_blocks/builder_component','@html_builder/core/img'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const{clickableBuilderComponentProps,useActionInfo,useSelectableItemComponent,}=require("@html_builder/core/utils");const{BuilderComponent}=require("@html_builder/core/building_blocks/builder_component");const{Img}=require("@html_builder/core/img");const BuilderButton=__exports.BuilderButton=class BuilderButton extends Component{static template="html_builder.BuilderButton";static components={BuilderComponent,Img};static props={...clickableBuilderComponentProps,title:{type:String,optional:true},label:{type:String,optional:true},iconImg:{type:String,optional:true},iconImgAlt:{type:String,optional:true},icon:{type:String,optional:true},className:{type:String,optional:true},classActive:{type:String,optional:true},style:{type:String,optional:true},type:{type:String,optional:true},slots:{type:Object,optional:true},};static defaultProps={type:"secondary",};setup(){this.info=useActionInfo();const{state,operation}=useSelectableItemComponent(this.props.id);this.state=state;this.onClick=operation.commit;this.onPointerEnter=operation.preview;this.onPointerLeave=operation.revert;}
get className(){let className=this.props.className||"";if(this.props.type){className+=` btn-${this.props.type}`;}
if(this.state.isActive){className=`active ${className}`;if(this.props.classActive){className+=` ${this.props.classActive}`;}}
if(this.props.icon){className+=` o-hb-btn-has-icon`;}
if(this.props.iconImg){className+=` o-hb-btn-has-img-icon`;}
return className;}
get iconClassName(){if(this.props.icon.startsWith("fa-")){return`fa ${this.props.icon}`;}else if(this.props.icon.startsWith("oi-")){return`oi ${this.props.icon}`;}
return"";}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_button_group.js */
odoo.define('@html_builder/core/building_blocks/builder_button_group',['@odoo/owl','@html_builder/core/utils','@html_builder/core/building_blocks/builder_component'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const{basicContainerBuilderComponentProps,useVisibilityObserver,useApplyVisibility,useSelectableComponent,}=require("@html_builder/core/utils");const{BuilderComponent}=require("@html_builder/core/building_blocks/builder_component");const BuilderButtonGroup=__exports.BuilderButtonGroup=class BuilderButtonGroup extends Component{static template="html_builder.BuilderButtonGroup";static props={...basicContainerBuilderComponentProps,slots:{type:Object,optional:true},};static components={BuilderComponent};setup(){useVisibilityObserver("root",useApplyVisibility("root"));useSelectableComponent(this.props.id);}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_checkbox.js */
odoo.define('@html_builder/core/building_blocks/builder_checkbox',['@odoo/owl','@web/core/checkbox/checkbox','@html_builder/core/utils','@html_builder/core/building_blocks/builder_component'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const{CheckBox}=require("@web/core/checkbox/checkbox");const{clickableBuilderComponentProps,useActionInfo,useClickableBuilderComponent,useDependencyDefinition,useDomState,}=require("@html_builder/core/utils");const{BuilderComponent}=require("@html_builder/core/building_blocks/builder_component");const BuilderCheckbox=__exports.BuilderCheckbox=class BuilderCheckbox extends Component{static template="html_builder.BuilderCheckbox";static components={BuilderComponent,CheckBox};static props={...clickableBuilderComponentProps,};setup(){this.info=useActionInfo();const{operation,isApplied,onReady}=useClickableBuilderComponent();if(this.props.id){useDependencyDefinition(this.props.id,{isActive:isApplied},{onReady});}
this.state=useDomState(async()=>{await onReady;return{isActive:isApplied(),};});this.onPointerEnter=operation.preview;this.onPointerLeave=operation.revert;this.onChange=operation.commit;}
getClassName(){return"o-hb-checkbox o_field_boolean o_boolean_toggle form-switch";}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_colorpicker.js */
odoo.define('@html_builder/core/building_blocks/builder_colorpicker',['@html_editor/main/font/color_selector','@odoo/owl','@web/core/color_picker/color_picker','@html_builder/core/building_blocks/builder_component','@html_builder/core/utils','@web/core/utils/colors','@html_builder/utils/utils_css'],function(require){'use strict';let __exports={};const{ColorSelector}=require("@html_editor/main/font/color_selector");const{Component,useComponent,useRef}=require("@odoo/owl");const{useColorPicker,DEFAULT_COLORS,DEFAULT_THEME_COLOR_VARS,}=require("@web/core/color_picker/color_picker");const{BuilderComponent}=require("@html_builder/core/building_blocks/builder_component");const{basicContainerBuilderComponentProps,getAllActionsAndOperations,revertPreview,useBuilderComponent,useDomState,useHasPreview,}=require("@html_builder/core/utils");const{isCSSColor,isColorGradient}=require("@web/core/utils/colors");const{getAllUsedColors}=require("@html_builder/utils/utils_css");__exports.useColorPickerBuilderComponent=useColorPickerBuilderComponent;function useColorPickerBuilderComponent(){const comp=useComponent();const{getAllActions,callOperation}=getAllActionsAndOperations(comp);const getAction=comp.env.editor.shared.builderActions.getAction;let selectedTab;const state=useDomState(getState);const applyOperation=comp.env.editor.shared.history.makePreviewableAsyncOperation((applySpecs,isPreviewing)=>{const proms=[];for(const applySpec of applySpecs){proms.push(applySpec.action.apply({isPreviewing,editingElement:applySpec.editingElement,params:applySpec.actionParam,value:applySpec.actionValue,loadResult:applySpec.loadResult,dependencyManager:comp.env.dependencyManager,}));}
return Promise.all(proms);});function getState(editingElement){const actionWithGetValue=getAllActions().find(({actionId})=>getAction(actionId).getValue);const{actionId,actionParam}=actionWithGetValue;const actionValue=getAction(actionId).getValue({editingElement,params:actionParam});return{defaultTab:comp.props.selectedTab,mode:actionParam.mainParam||actionId,selectedColor:actionValue||comp.props.defaultColor,selectedColorCombination:comp.env.editor.shared.color.getColorCombination(editingElement,actionParam),getTargetedElements:()=>[editingElement],selectedTab,};}
function getColor(colorValue){return colorValue.startsWith("color-prefix-")?`var(${colorValue.replace("color-prefix-", "--")})`:colorValue;}
let previewValue=null;function onApply(colorValue){previewValue=null;selectedTab=comp.getCorrespondingColorPickerTab(colorValue);callOperation(applyOperation.commit,{userInputValue:getColor(colorValue)});}
let onPreview=(colorValue)=>{if(previewValue===colorValue){return;}
previewValue=colorValue;callOperation(applyOperation.preview,{preview:true,userInputValue:getColor(colorValue),operationParams:{cancellable:true,cancelPrevious:()=>applyOperation.revert(),},});};const hasPreview=useHasPreview(getAllActions);if(!hasPreview){onPreview=()=>{};}
return{state,onApply,onPreview,onPreviewRevert:()=>{previewValue=null;revertPreview(comp.env.editor);},};}
const BuilderColorPicker=__exports.BuilderColorPicker=class BuilderColorPicker extends Component{static template="html_builder.BuilderColorPicker";static props={...basicContainerBuilderComponentProps,noTransparency:{type:Boolean,optional:true},enabledTabs:{type:Array,optional:true},grayscales:{type:Object,optional:true},unit:{type:String,optional:true},title:{type:String,optional:true},getUsedCustomColors:{type:Function,optional:true},selectedTab:{type:String,optional:true},defaultColor:{type:String,optional:true},defaultOpacity:{type:Number,optional:true},};static defaultProps={enabledTabs:["theme","gradient","custom"],defaultColor:"#FFFFFF00",selectedTab:"theme",};static components={ColorSelector:ColorSelector,BuilderComponent,};setup(){useBuilderComponent();const{state,onApply,onPreview,onPreviewRevert}=useColorPickerBuilderComponent();this.colorButton=useRef("colorButton");this.state=state;useColorPicker("colorButton",{state,applyColor:onApply,applyColorPreview:onPreview,applyColorResetPreview:onPreviewRevert,getUsedCustomColors:this.props.getUsedCustomColors||this.getUsedCustomColors.bind(this),colorPrefix:"color-prefix-",cssVarColorPrefix:"hb-cp-",noTransparency:this.props.noTransparency,enabledTabs:this.props.enabledTabs,grayscales:this.props.grayscales,defaultOpacity:this.props.defaultOpacity,className:"o-hb-colorpicker",editColorCombination:this.env.editColorCombination,},{onClose:onPreviewRevert,popoverClass:"o-hb-colorpicker-popover",});}
getSelectedColorStyle(){if(this.state.selectedColor){if(isColorGradient(this.state.selectedColor)){return`background-image: ${this.state.selectedColor}`;}
if(isCSSColor(this.state.selectedColor)){return`background-color: ${this.state.selectedColor}`;}
return`background-color: var(--${this.state.selectedColor})`;}
if(this.state.selectedColorCombination){const colorCombination=this.state.selectedColorCombination.replace("_","-");return`background-color: var(--hb-cp-${colorCombination}-bg); background-image: var(--hb-cp-${colorCombination}-bg-gradient);`;}
return"";}
getUsedCustomColors(){return getAllUsedColors(this.env.editor.editable);}
getCorrespondingColorPickerTab(selectedColor){if(!selectedColor){return;}
selectedColor=selectedColor.replace(/color-prefix-/g,"");const isTabEnabled=(tab)=>this.props.enabledTabs.includes(tab);if(isTabEnabled("gradient")&&isColorGradient(selectedColor)){return"gradient";}
const solidTabColors=[...DEFAULT_COLORS.flat(),...DEFAULT_THEME_COLOR_VARS.map((color)=>color.toUpperCase()),];if(isTabEnabled("solid")&&solidTabColors.includes(selectedColor.toUpperCase())){return"solid";}
if(isTabEnabled("theme")&&/^o_cc\d+$/.test(selectedColor)){return"theme";}
if(isTabEnabled("custom")){return"custom";}}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_component.js */
odoo.define('@html_builder/core/building_blocks/builder_component',['@odoo/owl','@html_builder/core/utils'],function(require){'use strict';let __exports={};const{Component,xml}=require("@odoo/owl");const{useDomState}=require("@html_builder/core/utils");const BuilderComponent=__exports.BuilderComponent=class BuilderComponent extends Component{static template=xml`<t t-if="this.state.isVisible"><t t-slot="default"/></t>`;static props={slots:{type:Object},};setup(){this.state=useDomState((editingElement)=>({isVisible:!!editingElement,}),{checkEditingElement:false});}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_context.js */
odoo.define('@html_builder/core/building_blocks/builder_context',['@odoo/owl','@html_builder/core/utils','@html_builder/core/building_blocks/builder_component'],function(require){'use strict';let __exports={};const{Component,xml}=require("@odoo/owl");const{basicContainerBuilderComponentProps,useBuilderComponent}=require("@html_builder/core/utils");const{BuilderComponent}=require("@html_builder/core/building_blocks/builder_component");const BuilderContext=__exports.BuilderContext=class BuilderContext extends Component{static template=xml`
        <BuilderComponent>
            <t t-slot="default"/>
        </BuilderComponent>
    `;static props={...basicContainerBuilderComponentProps,slots:{type:Object},};static components={BuilderComponent,};setup(){useBuilderComponent();}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_datetimepicker.js */
odoo.define('@html_builder/core/building_blocks/builder_datetimepicker',['@web/core/datetime/datetime_picker_hook','@odoo/owl','@web/core/utils/reactive','@web/core/l10n/dates','@web/core/utils/objects','@html_builder/core/utils','@html_builder/core/building_blocks/builder_component','@html_builder/core/building_blocks/builder_text_input_base'],function(require){'use strict';let __exports={};const{useDateTimePicker}=require("@web/core/datetime/datetime_picker_hook");const{Component,useState}=require("@odoo/owl");const{effect}=require("@web/core/utils/reactive");const{ConversionError,formatDate,formatDateTime,parseDateTime}=require("@web/core/l10n/dates");const{pick}=require("@web/core/utils/objects");const{basicContainerBuilderComponentProps,useBuilderComponent,useInputBuilderComponent,}=require("@html_builder/core/utils");const{BuilderComponent}=require("@html_builder/core/building_blocks/builder_component");const{BuilderTextInputBase,textInputBasePassthroughProps}=require("@html_builder/core/building_blocks/builder_text_input_base");const{DateTime}=luxon;const BuilderDateTimePicker=__exports.BuilderDateTimePicker=class BuilderDateTimePicker extends Component{static template="html_builder.BuilderDateTimePicker";static props={...basicContainerBuilderComponentProps,...textInputBasePassthroughProps,type:{type:[{value:"date"},{value:"datetime"}],optional:true},format:{type:String,optional:true},acceptEmptyDate:{type:Boolean,optional:true},};static defaultProps={type:"datetime",acceptEmptyDate:true,};static components={BuilderComponent,BuilderTextInputBase,};setup(){useBuilderComponent();this.defaultValue=DateTime.now().toUnixInteger().toString();const{state,commit,preview}=useInputBuilderComponent({id:this.props.id,defaultValue:this.props.acceptEmptyDate?undefined:this.defaultValue,formatRawValue:this.formatRawValue.bind(this),parseDisplayValue:this.parseDisplayValue.bind(this),});this.domState=state;this.state=useState({});effect(({value})=>{this.state.value=value;},[state]);this.commit=(userInputValue)=>{this.isPreviewing=false;const result=commit(userInputValue);return result;};this.preview=(userInputValue)=>{this.isPreviewing=true;preview(userInputValue);};const minDate=DateTime.fromObject({year:1000});const maxDate=DateTime.now().plus({year:200});const getPickerProps=()=>({type:this.props.type,minDate,maxDate,value:this.getCurrentValueDateTime(),rounding:0,});this.formatDateTime=this.props.type==="date"?formatDate:formatDateTime;this.dateTimePicker=useDateTimePicker({target:"root",format:this.props.format,get pickerProps(){return getPickerProps();},onApply:(value)=>{this.commit(this.formatDateTime(value));},onChange:(value)=>{const dateString=this.formatDateTime(value);this.preview(dateString);this.state.value=this.parseDisplayValue(dateString);},});}
getCurrentValueDateTime(){return this.domState.value?DateTime.fromSeconds(parseInt(this.domState.value)):false;}
formatRawValue(rawValue){return rawValue?this.formatDateTime(DateTime.fromSeconds(parseInt(rawValue))):"";}
parseDisplayValue(displayValue){if(displayValue===""&&this.props.acceptEmptyDate){return undefined;}
try{const parsedDateTime=parseDateTime(displayValue);if(parsedDateTime){return parsedDateTime.toUnixInteger().toString();}}catch(e){if(!(e instanceof ConversionError)){throw e;}
if(!this.isPreviewing&&displayValue!==""){return this.domState.value;}}
return this.defaultValue;}
get displayValue(){return this.state.value!==undefined?this.formatRawValue(this.state.value):undefined;}
get textInputBaseProps(){return pick(this.props,...Object.keys(textInputBasePassthroughProps));}
onFocus(){this.dateTimePicker.open();}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_fontfamilypicker.js */
odoo.define('@html_builder/core/building_blocks/builder_fontfamilypicker',['@odoo/owl','@web/core/l10n/translation','@web/core/utils/hooks','@html_builder/core/utils','@web/core/confirmation_dialog/confirmation_dialog','@html_builder/core/building_blocks/builder_select','@html_builder/core/building_blocks/builder_select_item'],function(require){'use strict';let __exports={};const{Component,onWillStart}=require("@odoo/owl");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{useService}=require("@web/core/utils/hooks");const{basicContainerBuilderComponentProps,useVisibilityObserver,useApplyVisibility,}=require("@html_builder/core/utils");const{ConfirmationDialog}=require("@web/core/confirmation_dialog/confirmation_dialog");const{BuilderSelect}=require("@html_builder/core/building_blocks/builder_select");const{BuilderSelectItem}=require("@html_builder/core/building_blocks/builder_select_item");const BuilderFontFamilyPicker=__exports.BuilderFontFamilyPicker=class BuilderFontFamilyPicker extends Component{static template="html_builder.BuilderFontFamilyPicker";static props={...basicContainerBuilderComponentProps,valueParamName:String,};static components={BuilderSelect,BuilderSelectItem,};setup(){this.dialog=useService("dialog");this.orm=useService("orm");useVisibilityObserver("content",useApplyVisibility("root"));this.fonts=[];onWillStart(async()=>{const fontsData=await this.env.editor.shared.builderFont.getFontsData();this.fonts=fontsData._fonts.slice().sort((a,b)=>a.string.localeCompare(b.string));});}
forwardProps(fontValue){const result=Object.assign({},this.props,{[this.props.valueParamName]:fontValue.fontFamilyValue,});delete result.selectMethod;delete result.valueParamName;return result;}
async onAddFontClick(){await this.env.editor.shared.websiteFont.addFont(this.props.actionParam);}
async onDeleteFontClick(font){const save=await new Promise((resolve)=>{this.env.services.dialog.add(ConfirmationDialog,{body:_t("Deleting a font requires a reload of the page. This will save all your changes and reload the page, are you sure you want to proceed?"),confirm:()=>resolve(true),cancel:()=>resolve(false),});});if(!save){return;}
await this.env.editor.shared.websiteFont.deleteFont(font);}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_list.js */
odoo.define('@html_builder/core/building_blocks/builder_list',['@html_builder/core/building_blocks/builder_component','@html_builder/core/utils','@html_builder/utils/utils','@odoo/owl','@web/core/dropdown/dropdown','@web/core/dropdown/dropdown_hooks','@web/core/l10n/translation','@web/core/utils/sortable_owl'],function(require){'use strict';let __exports={};const{BuilderComponent}=require("@html_builder/core/building_blocks/builder_component");const{basicContainerBuilderComponentProps,useBuilderComponent,useInputBuilderComponent,}=require("@html_builder/core/utils");const{isSmallInteger}=require("@html_builder/utils/utils");const{Component,onWillUpdateProps,useRef}=require("@odoo/owl");const{Dropdown}=require("@web/core/dropdown/dropdown");const{useDropdownState}=require("@web/core/dropdown/dropdown_hooks");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{useSortable}=require("@web/core/utils/sortable_owl");const BuilderList=__exports.BuilderList=class BuilderList extends Component{static template="html_builder.BuilderList";static props={...basicContainerBuilderComponentProps,id:{type:String,optional:true},addItemTitle:{type:String,optional:true},itemShape:{type:Object,values:[{value:"number"},{value:"text"},{value:"boolean"},{value:"exclusive_boolean"},],validate:(value)=>Object.keys(value).length>0&&!Object.keys(value).includes("_id"),optional:true,},default:{optional:true},sortable:{optional:true},hiddenProperties:{type:Array,optional:true},records:{type:String,optional:true},defaultNewValue:{type:Object,optional:true},columnWidth:{optional:true},forbidLastItemRemoval:{type:Boolean,optional:true},isInputDisabled:{type:Boolean,optional:true},};static defaultProps={addItemTitle:_t("Add"),itemShape:{value:"text"},default:{value:_t("Item")},sortable:true,hiddenProperties:[],mode:"button",defaultNewValue:{},columnWidth:{},forbidLastItemRemoval:false,isInputDisabled:false,};static components={BuilderComponent,Dropdown};setup(){this.validateProps();this.dropdown=useDropdownState();useBuilderComponent();const{state,commit,preview}=useInputBuilderComponent({id:this.props.id,defaultValue:this.parseDisplayValue([]),parseDisplayValue:this.parseDisplayValue,formatRawValue:this.formatRawValue.bind(this),});this.state=state;this.commit=commit;this.preview=preview;this.allRecords=this.formatRawValue(this.props.records);onWillUpdateProps((props)=>{this.allRecords=this.formatRawValue(props.records);});if(this.props.sortable){useSortable({enable:()=>this.props.sortable,ref:useRef("table"),elements:".o_row_draggable",handle:".o_handle_cell",cursor:"grabbing",placeholderClasses:["d-table-row"],onDrop:(params)=>{const{element,previous}=params;this.reorderItem(element.dataset.id,previous?.dataset.id);},});}}
validateProps(){const itemShapeKeys=Object.keys(this.props.itemShape);const defaultKeys=Object.keys(this.props.default);const allKeys=new Set([...itemShapeKeys,...defaultKeys]);if(allKeys.size!==itemShapeKeys.length){throw new Error("default properties don't match itemShape");}}
getAvailableRecords(){const itemIds=new Set(this.formatRawValue(this.state.value).map((i)=>i.id));return this.allRecords.filter((record)=>!itemIds.has(record.id));}
parseDisplayValue(displayValue){return JSON.stringify(displayValue);}
formatRawValue(rawValue){const items=rawValue?JSON.parse(rawValue):[];let nextAvailableId=items?this.getNextAvailableItemId(items):0;for(const item of items){if(!("_id"in item)){item._id=nextAvailableId.toString();nextAvailableId+=1;}}
return items;}
addItem(ev){const items=this.formatRawValue(this.state.value);if(!ev.currentTarget.dataset.id){items.push(this.makeDefaultItem());}else{const matchId=(el)=>el.id.toString()===ev.currentTarget.dataset.id.toString();const elementToAdd=this.allRecords.find(matchId);if(!items.some(matchId)){items.push(elementToAdd);}
this.dropdown.close();}
this.commit(items);}
deleteItem(itemId){const items=this.formatRawValue(this.state.value);this.commit(items.filter((item)=>item._id!==itemId));}
reorderItem(itemId,previousId){let items=this.formatRawValue(this.state.value);const itemToReorder=items.find((item)=>item._id===itemId);items=items.filter((item)=>item._id!==itemId);const previousItem=items.find((item)=>item._id===previousId);const previousItems=items.slice(0,items.indexOf(previousItem)+1);const nextItems=items.slice(items.indexOf(previousItem)+1,items.length);const newItems=[...previousItems,itemToReorder,...nextItems];this.commit(newItems);}
makeDefaultItem(){return{...this.props.defaultNewValue,...this.props.default,_id:this.getNextAvailableItemId().toString(),};}
getNextAvailableItemId(items){items=items||this.formatRawValue(this.state?.value);const biggestId=items.map((item)=>parseInt(item._id)).reduce((acc,id)=>(id>acc?id:acc),-1);const nextAvailableId=biggestId+1;return nextAvailableId;}
onInput(e){this.handleValueChange(e.target,false);}
onChange(e){this.handleValueChange(e.target,true);}
handleValueChange(targetInputEl,commitToHistory){const id=targetInputEl.dataset.id;const propertyName=targetInputEl.name;const isCheckbox=targetInputEl.type==="checkbox";const value=isCheckbox?targetInputEl.checked:targetInputEl.value;const items=this.formatRawValue(this.state.value);if(value===true&&this.props.itemShape[propertyName]==="exclusive_boolean"){for(const item of items){item[propertyName]=false;}}
const item=items.find((item)=>item._id===id);item[propertyName]=value;if(!isCheckbox){item.id=isSmallInteger(value)?parseInt(value):value;}
if(commitToHistory){this.commit(items);}else{this.preview(items);}}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_many2many.js */
odoo.define('@html_builder/core/building_blocks/builder_many2many',['@odoo/owl','@web/core/utils/hooks','@html_builder/core/utils','@html_builder/core/building_blocks/builder_component','@html_builder/core/building_blocks/basic_many2many'],function(require){'use strict';let __exports={};const{Component,onWillStart,onWillUpdateProps,useState}=require("@odoo/owl");const{useService}=require("@web/core/utils/hooks");const{basicContainerBuilderComponentProps,getAllActionsAndOperations,useBuilderComponent,useDomState,}=require("@html_builder/core/utils");const{BuilderComponent}=require("@html_builder/core/building_blocks/builder_component");const{BasicMany2Many}=require("@html_builder/core/building_blocks/basic_many2many");const BuilderMany2Many=__exports.BuilderMany2Many=class BuilderMany2Many extends Component{static template="html_builder.BuilderMany2Many";static props={...basicContainerBuilderComponentProps,model:String,m2oField:{type:String,optional:true},fields:{type:Array,element:String,optional:true},domain:{type:Array,optional:true},limit:{type:Number,optional:true},};static defaultProps=BuilderComponent.defaultProps;static components={BuilderComponent,BasicMany2Many};setup(){useBuilderComponent();this.fields=useService("field");const{getAllActions,callOperation}=getAllActionsAndOperations(this);this.callOperation=callOperation;this.applyOperation=this.env.editor.shared.history.makePreviewableAsyncOperation(this.callApply.bind(this));this.state=useState({searchModel:undefined,});this.domState=useDomState((el)=>{const getAction=this.env.editor.shared.builderActions.getAction;const actionWithGetValue=getAllActions().find(({actionId})=>getAction(actionId).getValue);const{actionId,actionParam}=actionWithGetValue;const actionValue=getAction(actionId).getValue({editingElement:el,params:actionParam,});return{selection:JSON.parse(actionValue||"[]"),};});onWillStart(async()=>{await this.handleProps(this.props);});onWillUpdateProps(async(newProps)=>{await this.handleProps(newProps);});}
async handleProps(props){if(props.m2oField){const modelData=await this.fields.loadFields(props.model,{fieldNames:[props.m2oField],});this.state.searchModel=modelData[props.m2oField].relation;if(!this.state.searchModel){throw new Error(`m2oField ${props.m2oField} is not a relation field`);}}else{this.state.searchModel=props.model;}}
callApply(applySpecs){const proms=[];for(const applySpec of applySpecs){proms.push(applySpec.action.apply({editingElement:applySpec.editingElement,params:applySpec.actionParam,value:applySpec.actionValue,loadResult:applySpec.loadResult,dependencyManager:this.env.dependencyManager,}));}
return proms;}
setSelection(newSelection){this.callOperation(this.applyOperation.commit,{userInputValue:JSON.stringify(newSelection),});}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_many2one.js */
odoo.define('@html_builder/core/building_blocks/builder_many2one',['@odoo/owl','@html_builder/core/utils','@html_builder/core/building_blocks/builder_component','@html_builder/core/building_blocks/select_many2x','@html_builder/core/cached_model_utils'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const{basicContainerBuilderComponentProps,getAllActionsAndOperations,revertPreview,useBuilderComponent,useDependencyDefinition,useDomState,useHasPreview,}=require("@html_builder/core/utils");const{BuilderComponent}=require("@html_builder/core/building_blocks/builder_component");const{SelectMany2X}=require("@html_builder/core/building_blocks/select_many2x");const{useCachedModel}=require("@html_builder/core/cached_model_utils");const BuilderMany2One=__exports.BuilderMany2One=class BuilderMany2One extends Component{static template="html_builder.BuilderMany2One";static props={...basicContainerBuilderComponentProps,model:String,fields:{type:Array,element:String,optional:true},domain:{type:Array,optional:true},limit:{type:Number,optional:true},id:{type:String,optional:true},allowUnselect:{type:Boolean,optional:true},defaultMessage:{type:String,optional:true},createAction:{type:String,optional:true},nullText:{type:String,optional:true},};static defaultProps={...BuilderComponent.defaultProps,allowUnselect:true,};static components={BuilderComponent,SelectMany2X};setup(){useBuilderComponent();const{getAllActions,callOperation}=getAllActionsAndOperations(this);this.cachedModel=useCachedModel();this.callOperation=callOperation;this.hasPreview=useHasPreview(getAllActions);this.applyOperation=this.env.editor.shared.history.makePreviewableAsyncOperation(this.callApply.bind(this));const getAction=this.env.editor.shared.builderActions.getAction;const actionWithGetValue=getAllActions().find(({actionId})=>getAction(actionId).getValue);const{actionId,actionParam}=actionWithGetValue;const getValue=(el)=>getAction(actionId).getValue({editingElement:el,params:actionParam});this.domState=useDomState(async(el)=>{const selectedString=getValue(el);const selected=selectedString&&JSON.parse(selectedString);if(selected&&!("display_name"in selected&&"name"in selected)){let value;if(!selected.id){value={display_name:this.props.nullText,name:this.props.nullText,};}else{value=(await this.cachedModel.ormRead(this.props.model,[selected.id],["display_name","name"]))[0];}
Object.assign(selected,value);}
return{selected};});if(this.props.id){useDependencyDefinition(this.props.id,{getValue:()=>getValue(this.env.getEditingElement()),});}
if(this.props.createAction){this.createAction=this.env.editor.shared.builderActions.getAction(this.props.createAction);this.createOperation=this.env.editor.shared.history.makePreviewableOperation(this.createAction.apply);}}
callApply(applySpecs,isPreviewing){const proms=[];for(const applySpec of applySpecs){if(applySpec.actionValue===undefined){applySpec.action.clean({isPreviewing,editingElement:applySpec.editingElement,params:applySpec.actionParam,dependencyManager:this.env.dependencyManager,});}else{proms.push(applySpec.action.apply({isPreviewing,editingElement:applySpec.editingElement,params:applySpec.actionParam,value:applySpec.actionValue,loadResult:applySpec.loadResult,dependencyManager:this.env.dependencyManager,}));}}
return Promise.all(proms);}
select(newSelected){this.callOperation(this.applyOperation.commit,{userInputValue:newSelected&&JSON.stringify(newSelected),});}
preview(newSelected){this.callOperation(this.applyOperation.preview,{preview:true,userInputValue:newSelected&&JSON.stringify(newSelected),operationParams:{cancellable:true,cancelPrevious:()=>this.applyOperation.revert(),},});}
revert(){revertPreview(this.env.editor);}
create(name){const args={editingElement:this.env.getEditingElement(),value:name};this.env.editor.shared.operation.next(()=>this.createOperation.commit(args),{load:()=>this.createAction.load?.(args).then((loadResult)=>(args.loadResult=loadResult)),});}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_number_input.js */
odoo.define('@html_builder/core/building_blocks/builder_number_input',['@html_editor/utils/formatting','@odoo/owl','@html_builder/core/utils','@html_builder/core/building_blocks/builder_component','@html_builder/core/building_blocks/builder_text_input_base','@web/core/utils/hooks','@web/core/utils/objects'],function(require){'use strict';let __exports={};const{convertNumericToUnit,getHtmlStyle}=require("@html_editor/utils/formatting");const{Component}=require("@odoo/owl");const{basicContainerBuilderComponentProps,useInputBuilderComponent,useBuilderComponent,useInputDebouncedCommit,}=require("@html_builder/core/utils");const{BuilderComponent}=require("@html_builder/core/building_blocks/builder_component");const{BuilderTextInputBase,textInputBasePassthroughProps,}=require("@html_builder/core/building_blocks/builder_text_input_base");const{useChildRef}=require("@web/core/utils/hooks");const{pick}=require("@web/core/utils/objects");const BuilderNumberInput=__exports.BuilderNumberInput=class BuilderNumberInput extends Component{static template="html_builder.BuilderNumberInput";static props={...basicContainerBuilderComponentProps,...textInputBasePassthroughProps,default:{type:[Number,{value:null}],optional:true},unit:{type:String,optional:true},saveUnit:{type:String,optional:true},step:{type:Number,optional:true},min:{type:Number,optional:true},max:{type:Number,optional:true},composable:{type:Boolean,optional:true},applyWithUnit:{type:Boolean,optional:true},};static components={BuilderComponent,BuilderTextInputBase};static defaultProps={composable:false,applyWithUnit:true,default:0,};setup(){if(this.props.saveUnit&&!this.props.unit){throw new Error("'unit' must be defined to use the 'saveUnit' props");}
useBuilderComponent();const{state,commit,preview}=useInputBuilderComponent({id:this.props.id,defaultValue:this.props.default===null?null:this.props.default?.toString(),formatRawValue:this.formatRawValue.bind(this),parseDisplayValue:this.parseDisplayValue.bind(this),});this.commit=commit;this.preview=preview;this.state=state;this.inputRef=useChildRef();this.debouncedCommitValue=useInputDebouncedCommit(this.inputRef);}
convertSpaceSplitValues(values,convertSingleValueFn){if(typeof values==="number"){return convertSingleValueFn(values.toString());}
if(values===null){return values;}
if(!values){return"";}
return values.trim().split(/\s+/g).map(convertSingleValueFn).join(" ");}
formatRawValue(rawValue){return this.convertSpaceSplitValues(rawValue,(value)=>{const unit=this.props.unit;const{savedValue,savedUnit}=value.match(/(?<savedValue>[\d.e+-]+)(?<savedUnit>\w*)/).groups;if(savedUnit||this.props.saveUnit){value=convertNumericToUnit(parseFloat(savedValue),savedUnit||this.props.saveUnit,unit,getHtmlStyle(this.env.getEditingElement().ownerDocument));}
return parseFloat(parseFloat(value).toFixed(3)).toString();});}
clampValue(value){if(!value&&value!==0){return value;}
value=parseFloat(value);if(value<this.props.min){return`${this.props.min}`;}
if(value>this.props.max){return`${this.props.max}`;}
return+value.toFixed(3);}
parseDisplayValue(displayValue){if(!displayValue){return displayValue;}
displayValue=displayValue.replace(/,/g,".");if(this.props.composable){displayValue=displayValue.trim().replace(/[^0-9.-\s]/g,"").replace(/(?<!^|\s)-/g,"");}else{displayValue=displayValue.trim().replace(/-\s*/g,"-").split(" ")[0].replace(/[^0-9.-]/g,"").replace(/(?<!^)-/g,"").replace(/^([^.]*)\.?(.*)/,(_,a,b)=>a+(b?"."+b.replace(/\./g,""):""));}
displayValue=displayValue.split(" ").map(this.clampValue.bind(this)).join(" ")||this.props.default;return this.convertSpaceSplitValues(displayValue,(value)=>{if(value===""){return value;}
const unit=this.props.unit;const saveUnit=this.props.saveUnit;const applyWithUnit=this.props.applyWithUnit;if(unit&&saveUnit){value=convertNumericToUnit(value,unit,saveUnit,getHtmlStyle(this.env.getEditingElement().ownerDocument));}
if(unit&&applyWithUnit){if(saveUnit||saveUnit===""){value=value+saveUnit;}else{value=value+unit;}}
return value;});}
get displayValue(){return this.formatRawValue(this.state.value);}
onKeydown(e){if(!["ArrowUp","ArrowDown"].includes(e.key)){return;}
const values=e.target.value.split(" ").map((number)=>parseFloat(number)||0);if(e.key==="ArrowUp"){values.forEach((value,i)=>{values[i]=this.clampValue(value+(this.props.step||1));});}else if(e.key==="ArrowDown"){values.forEach((value,i)=>{values[i]=this.clampValue(value-(this.props.step||1));});}
e.target.value=values.join(" ");this.preview(e.target.value);this.debouncedCommitValue();}
get textInputBaseProps(){return pick(this.props,...Object.keys(textInputBasePassthroughProps));}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_range.js */
odoo.define('@html_builder/core/building_blocks/builder_range',['@odoo/owl','@html_builder/core/utils','@html_builder/core/building_blocks/builder_component'],function(require){'use strict';let __exports={};const{Component,useRef}=require("@odoo/owl");const{basicContainerBuilderComponentProps,useActionInfo,useBuilderComponent,useInputBuilderComponent,useInputDebouncedCommit,}=require("@html_builder/core/utils");const{BuilderComponent}=require("@html_builder/core/building_blocks/builder_component");const BuilderRange=__exports.BuilderRange=class BuilderRange extends Component{static template="html_builder.BuilderRange";static props={...basicContainerBuilderComponentProps,min:{type:Number,optional:true},max:{type:Number,optional:true},step:{type:Number,optional:true},displayRangeValue:{type:Boolean,optional:true},computedOutput:{type:Function,optional:true},unit:{type:String,optional:true},};static defaultProps={...BuilderComponent.defaultProps,min:0,max:100,step:1,displayRangeValue:false,};static components={BuilderComponent};setup(){this.info=useActionInfo();useBuilderComponent();const{state,commit,preview}=useInputBuilderComponent({id:this.props.id,formatRawValue:this.formatRawValue.bind(this),parseDisplayValue:this.parseDisplayValue.bind(this),});this.inputRef=useRef("inputRef");this.debouncedCommitValue=useInputDebouncedCommit(this.inputRef);this.commit=commit;this.preview=preview;this.state=state;}
formatRawValue(value){if(this.props.unit){value=value.slice(0,-this.props.unit.length);}
return value;}
parseDisplayValue(value){if(this.props.unit){value=`${value}${this.props.unit}`;}
return value;}
onChange(e){const normalizedDisplayValue=this.commit(e.target.value);e.target.value=normalizedDisplayValue;}
onInput(e){this.preview(e.target.value);if(this.props.displayRangeValue){this.state.value=this.parseDisplayValue(e.target.value);}}
onKeydown(e){if(!["ArrowLeft","ArrowUp","ArrowDown","ArrowRight"].includes(e.key)){return;}
e.preventDefault();let value=parseFloat(e.target.value);if(e.key==="ArrowLeft"||e.key==="ArrowDown"){value=Math.max(this.min,value-this.props.step);}else{value=Math.min(this.max,value+this.props.step);}
e.target.value=value;this.onInput(e);this.debouncedCommitValue();}
get rangeInputValue(){return this.state.value?this.formatRawValue(this.state.value):"0";}
get displayValue(){let value=this.rangeInputValue;if(this.props.computedOutput){value=this.props.computedOutput(value);}else if(this.props.unit){value=`${value}${this.props.unit}`;}
return value;}
get className(){const baseClasses="p-0 border-0";return this.props.min>this.props.max?`${baseClasses} o_we_inverted_range`:baseClasses;}
get min(){return this.props.min>this.props.max?this.props.max:this.props.min;}
get max(){return this.props.min>this.props.max?this.props.min:this.props.max;}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_row.js */
odoo.define('@html_builder/core/building_blocks/builder_row',['@odoo/owl','@web/core/l10n/localization','@web/core/transition','@web/core/utils/functions','@web/core/utils/hooks','@html_builder/core/utils','@html_builder/core/building_blocks/builder_component'],function(require){'use strict';let __exports={};const{Component,onMounted,useEffect,useRef,useState}=require("@odoo/owl");const{localization}=require("@web/core/l10n/localization");const{useTransition}=require("@web/core/transition");const{uniqueId}=require("@web/core/utils/functions");const{useService}=require("@web/core/utils/hooks");const{basicContainerBuilderComponentProps,useApplyVisibility,useBuilderComponent,useVisibilityObserver,}=require("@html_builder/core/utils");const{BuilderComponent}=require("@html_builder/core/building_blocks/builder_component");const BuilderRow=__exports.BuilderRow=class BuilderRow extends Component{static template="html_builder.BuilderRow";static components={BuilderComponent};static props={...basicContainerBuilderComponentProps,label:{type:String,optional:true},tooltip:{type:String,optional:true},slots:{type:Object,optional:true},level:{type:Number,optional:true},expand:{type:Boolean,optional:true},initialExpandAnim:{type:Boolean,optional:true},extraLabelClass:{type:String,optional:true},observeCollapseContent:{type:Boolean,optional:true},disabled:{type:Boolean,optional:true},fullRowToggler:{type:Boolean,optional:true},};static defaultProps={expand:false,observeCollapseContent:false,fullRowToggler:false};setup(){useBuilderComponent();useVisibilityObserver("content",useApplyVisibility("root"));this.state=useState({expanded:this.props.expand,});this.tooltipText=undefined;this.isBackendRTL=localization.direction==="rtl";if(this.props.slots.collapse){useVisibilityObserver("collapse-content",useApplyVisibility("collapse"));this.collapseContentId=uniqueId("builder_collapse_content_");}
this.labelRef=useRef("label");this.rootRef=useRef("root");this.collapseContentRef=useRef("collapse-content");let isMounted=false;onMounted(()=>{if(this.props.initialExpandAnim){setTimeout(()=>{this.toggleCollapseContent();},150);}});this.transition=useTransition({initialVisibility:this.props.expand,leaveDuration:350,name:"hb-collapse-content",});useEffect((stage)=>{const isFirstMount=!isMounted;isMounted=true;const contentEl=this.collapseContentRef.el;if(!contentEl){return;}
const setHeightAuto=()=>{contentEl.style.height="auto";};if(isFirstMount&&this.props.expand){setHeightAuto();return;}
switch(stage){case"enter-active":{contentEl.style.height=contentEl.scrollHeight+"px";contentEl.addEventListener("transitionend",setHeightAuto,{once:true});break;}
case"leave":{contentEl.style.height=contentEl.scrollHeight+"px";void contentEl.offsetHeight;contentEl.style.height="0px";break;}}},()=>[this.transition.stage]);this.tooltip=useService("tooltip");useEffect(()=>refreshSublevelLines(this.rootRef.el));}
getLevelClass(){return this.props.level?`hb-row-sublevel hb-row-sublevel-${this.props.level}`:"";}
onRowContentClick(){if(this.props.fullRowToggler){this.toggleCollapseContent();}}
toggleCollapseContent(){this.state.expanded=!this.state.expanded;this.transition.shouldMount=this.state.expanded;}
get displayCollapseContent(){return this.transition.shouldMount||this.props.observeCollapseContent;}
get collapseContentClass(){const isNotVisible=this.props.observeCollapseContent&&!this.transition.shouldMount;return`${this.transition.className} ${isNotVisible ? "d-none" : ""}`;}
openTooltip(){const labelEl=this.labelRef.el;if(this.tooltipText===undefined){const isLabelTooLong=labelEl.offsetWidth<labelEl.scrollWidth;if(isLabelTooLong){this.tooltipText=this.props.tooltip?`${this.props.label}\u00A0: ${this.props.tooltip}`:this.props.label;}else if(this.props.tooltip){this.tooltipText=this.props.tooltip;}else{this.tooltipText="";}}
if(this.tooltipText){this.removeTooltip=this.tooltip.add(labelEl,{tooltip:this.tooltipText,});}}
closeTooltip(){if(this.removeTooltip){this.removeTooltip();}}}
function refreshSublevelLines(rowEl){const optionsContainerEl=rowEl?.closest(".options-container");if(!optionsContainerEl){return;}
alignSublevelLines(optionsContainerEl);}
function alignSublevelLines(optionsContainerEl){const rowEls=[...optionsContainerEl.querySelectorAll(".hb-row")];if(!rowEls.length){return;}
const visibleRowEls=[];for(const rowEl of rowEls){const labelEl=rowEl.querySelector(":scope > .hb-row-label");if(labelEl){labelEl.style.removeProperty("--o-hb-row-sublevel-top");}
if(getComputedStyle(rowEl).display!=="none"){visibleRowEls.push(rowEl);}}
for(let index=0;index<visibleRowEls.length;index++){const rowEl=visibleRowEls[index];const level=getRowLevel(rowEl);if(!level){continue;}
const previousRowEl=visibleRowEls[index-1];if(!previousRowEl||getRowLevel(previousRowEl)<=level){continue;}
for(let previousIndex=index-1;previousIndex>=0;previousIndex--){if(getRowLevel(visibleRowEls[previousIndex])===level){applyLineOffset(rowEl,visibleRowEls[previousIndex]);break;}}}}
function applyLineOffset(rowEl,previousRowEl){const labelEl=rowEl.querySelector(":scope > .hb-row-label");const previousLabelEl=previousRowEl.querySelector(":scope > .hb-row-label");if(!labelEl||!previousLabelEl){return;}
const offset=previousLabelEl.getBoundingClientRect().bottom-labelEl.getBoundingClientRect().top;if(offset<0){labelEl.style.setProperty("--o-hb-row-sublevel-top",`${offset}px`);}}
function getRowLevel(rowEl){const sublevelClass=[...rowEl.classList].find((className)=>className.startsWith("hb-row-sublevel-"));if(!sublevelClass){return 0;}
return parseInt(sublevelClass.replace("hb-row-sublevel-",""),10)||0;}
Object.assign(__exports,{refreshSublevelLines});return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_select.js */
odoo.define('@html_builder/core/building_blocks/builder_select',['@odoo/owl','@web/core/l10n/translation','@web/core/dropdown/dropdown','@html_builder/core/utils','@html_builder/core/building_blocks/builder_component','@web/core/dropdown/dropdown_hooks','@web/core/utils/html'],function(require){'use strict';let __exports={};const{Component,onMounted,useRef,useSubEnv,xml}=require("@odoo/owl");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{Dropdown}=require("@web/core/dropdown/dropdown");const{basicContainerBuilderComponentProps,useVisibilityObserver,useApplyVisibility,useSelectableComponent,}=require("@html_builder/core/utils");const{BuilderComponent}=require("@html_builder/core/building_blocks/builder_component");const{useDropdownState}=require("@web/core/dropdown/dropdown_hooks");const{setElementContent}=require("@web/core/utils/html");const WithIgnoreItem=__exports.WithIgnoreItem=class WithIgnoreItem extends Component{static template=xml`<t t-slot="default"/>`;static props={slots:{type:Object},};setup(){useSubEnv({ignoreBuilderItem:true,});}}
const BuilderSelect=__exports.BuilderSelect=class BuilderSelect extends Component{static template="html_builder.BuilderSelect";static props={...basicContainerBuilderComponentProps,className:{type:String,optional:true},dropdownContainerClass:{type:String,optional:true},disabled:{type:Boolean,optional:true},slots:{type:Object,shape:{default:Object,fixedButton:{type:Object,optional:true},},},dropdownClass:{type:String,optional:true},};static defaultProps={dropdownClass:"o-hb-select-dropdown"};static components={Dropdown,BuilderComponent,WithIgnoreItem,};setup(){useVisibilityObserver("content",useApplyVisibility("root"));this.dropdown=useDropdownState();const buttonRef=useRef("button");let currentLabel;const updateCurrentLabel=()=>{if(!this.props.slots.fixedButton){const newHtml=currentLabel||_t("None");if(buttonRef.el&&buttonRef.el.innerHTML!==newHtml){setElementContent(buttonRef.el,newHtml);}}};useSelectableComponent(this.props.id,{onItemChange(item){currentLabel=item.getLabel();updateCurrentLabel();},});onMounted(updateCurrentLabel);useSubEnv({onSelectItem:()=>{this.dropdown.close();},});}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_select_item.js */
odoo.define('@html_builder/core/building_blocks/builder_select_item',['@odoo/owl','@web/core/hotkeys/hotkey_service','@html_builder/core/utils','@html_builder/core/building_blocks/builder_component'],function(require){'use strict';let __exports={};const{Component,markup,onMounted,useRef}=require("@odoo/owl");const{getActiveHotkey}=require("@web/core/hotkeys/hotkey_service");const{clickableBuilderComponentProps,useActionInfo,useSelectableItemComponent,}=require("@html_builder/core/utils");const{BuilderComponent}=require("@html_builder/core/building_blocks/builder_component");const BuilderSelectItem=__exports.BuilderSelectItem=class BuilderSelectItem extends Component{static template="html_builder.BuilderSelectItem";static props={...clickableBuilderComponentProps,title:{type:String,optional:true},label:{type:String,optional:true},className:{type:String,optional:true},slots:{type:Object,optional:true},};static defaultProps={className:"",};static components={BuilderComponent};setup(){if(!this.env.selectableContext){throw new Error("BuilderSelectItem must be used inside a BuilderSelect component.");}
this.info=useActionInfo();const item=useRef("item");let label="";const getLabel=()=>{label=this.props.label||(item.el?markup(item.el.innerHTML):"")||label||"";return label;};onMounted(getLabel);const{state,operation}=useSelectableItemComponent(this.props.id,{getLabel,});this.state=state;this.operation=operation;this.onFocusin=this.operation.preview;this.onFocusout=this.operation.revert;}
onClick(){this.env.onSelectItem();this.operation.commit();this.removeKeydown?.();}
onKeydown(ev){const hotkey=getActiveHotkey(ev);if(hotkey==="escape"){this.operation.revert();this.removeKeydown?.();}}
onPointerEnter(){this.operation.preview();const _onKeydown=this.onKeydown.bind(this);document.addEventListener("keydown",_onKeydown);this.removeKeydown=()=>document.removeEventListener("keydown",_onKeydown);}
onPointerLeave(){this.operation.revert();this.removeKeydown();}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_text_input.js */
odoo.define('@html_builder/core/building_blocks/builder_text_input',['@odoo/owl','@web/core/utils/objects','@html_builder/core/building_blocks/builder_text_input_base','@html_builder/core/utils','@html_builder/core/building_blocks/builder_component'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const{pick}=require("@web/core/utils/objects");const{BuilderTextInputBase,textInputBasePassthroughProps}=require("@html_builder/core/building_blocks/builder_text_input_base");const{basicContainerBuilderComponentProps,useInputBuilderComponent,useBuilderComponent,}=require("@html_builder/core/utils");const{BuilderComponent}=require("@html_builder/core/building_blocks/builder_component");const BuilderTextInput=__exports.BuilderTextInput=class BuilderTextInput extends Component{static template="html_builder.BuilderTextInput";static props={...basicContainerBuilderComponentProps,...textInputBasePassthroughProps,prefix:{type:String,optional:true},default:{type:String,optional:true},};static components={BuilderComponent,BuilderTextInputBase,};setup(){useBuilderComponent();const{state,commit,preview}=useInputBuilderComponent({id:this.props.id,defaultValue:this.props.default,});this.commit=commit;this.preview=preview;this.state=state;}
get textInputBaseProps(){return pick(this.props,...Object.keys(textInputBasePassthroughProps));}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_text_input_base.js */
odoo.define('@html_builder/core/building_blocks/builder_text_input_base',['@odoo/owl','@web/core/utils/hooks','@html_builder/core/utils'],function(require){'use strict';let __exports={};const{Component,onWillUpdateProps,useState}=require("@odoo/owl");const{useForwardRefToParent}=require("@web/core/utils/hooks");const{useActionInfo}=require("@html_builder/core/utils");const textInputBasePassthroughProps=__exports.textInputBasePassthroughProps={action:{type:String,optional:true},placeholder:{type:String,optional:true},title:{type:String,optional:true},style:{type:String,optional:true},tooltip:{type:String,optional:true},classes:{type:String,optional:true},inputClasses:{type:String,optional:true},prefix:{type:String,optional:true},};const BuilderTextInputBase=__exports.BuilderTextInputBase=class BuilderTextInputBase extends Component{static template="html_builder.BuilderTextInputBase";static props={slots:{type:Object,optional:true},inputRef:{type:Function,optional:true},...textInputBasePassthroughProps,commit:{type:Function},preview:{type:Function},onFocus:{type:Function,optional:true},onKeydown:{type:Function,optional:true},value:{type:[String,{value:null}],optional:true},};setup(){this.isEditing=false;this.info=useActionInfo();this.inputRef=useForwardRefToParent("inputRef");this.state=useState({value:this.props.value});onWillUpdateProps((nextProps)=>{if("value"in nextProps){this.state.value=this.isEditing?this.inputRef.el.value:nextProps.value;}});}
onChange(ev){this.isEditing=false;const normalizedDisplayValue=this.props.commit(ev.target.value);ev.target.value=normalizedDisplayValue;}
onInput(ev){this.isEditing=true;this.props.preview(ev.target.value);}
onFocus(ev){this.props.onFocus?.(ev);}
onKeydown(ev){this.props.onKeydown?.(ev);}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/builder_urlpicker.js */
odoo.define('@html_builder/core/building_blocks/builder_urlpicker',['@html_builder/core/building_blocks/builder_component','@html_builder/core/building_blocks/builder_text_input_base','@html_builder/core/utils','@odoo/owl','@web/core/utils/hooks','@web/core/utils/objects'],function(require){'use strict';let __exports={};const{BuilderComponent}=require("@html_builder/core/building_blocks/builder_component");const{BuilderTextInputBase,textInputBasePassthroughProps,}=require("@html_builder/core/building_blocks/builder_text_input_base");const{basicContainerBuilderComponentProps,useBuilderComponent,useInputBuilderComponent,}=require("@html_builder/core/utils");const{Component}=require("@odoo/owl");const{useChildRef}=require("@web/core/utils/hooks");const{pick}=require("@web/core/utils/objects");const BuilderUrlPicker=__exports.BuilderUrlPicker=class BuilderUrlPicker extends Component{static template="html_builder.BuilderUrlPicker";static props={...basicContainerBuilderComponentProps,...textInputBasePassthroughProps,default:{type:String,optional:true},};static components={BuilderComponent,BuilderTextInputBase,};setup(){this.inputRef=useChildRef();useBuilderComponent();const{state,commit,preview}=useInputBuilderComponent({id:this.props.id,defaultValue:this.props.default,});this.commit=commit;this.preview=preview;this.state=state;}
get textInputBaseProps(){return pick(this.props,...Object.keys(textInputBasePassthroughProps));}
openPreviewUrl(){if(this.inputRef.el.value){window.open(this.inputRef.el.value,"_blank");}}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/color_picker_theme_tab.js */
odoo.define('@html_builder/core/building_blocks/color_picker_theme_tab',['@odoo/owl','@web/core/l10n/translation','@web/core/registry'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{registry}=require("@web/core/registry");const ColorPickerThemeTab=__exports.ColorPickerThemeTab=class ColorPickerThemeTab extends Component{static template="html_builder.ColorPickerThemeTab";static props={onColorClick:Function,onColorPointerOver:Function,onColorPointerOut:Function,onColorPointerLeave:Function,onFocusin:Function,onFocusout:Function,selectedColorCombination:{type:String,optional:true},"*":{optional:true},};}
registry.category("color_picker_tabs").add("html_builder.theme",{id:"theme",name:_t("Theme"),component:ColorPickerThemeTab,},{sequence:10});return __exports;});;

/* /html_builder/static/src/core/building_blocks/model_many2many.js */
odoo.define('@html_builder/core/building_blocks/model_many2many',['@odoo/owl','@web/core/utils/functions','@web/core/utils/hooks','@html_builder/core/utils','@html_builder/core/cached_model_utils','@html_builder/core/building_blocks/builder_component','@html_builder/core/building_blocks/basic_many2many'],function(require){'use strict';let __exports={};const{Component,useState,onWillStart,onWillUpdateProps}=require("@odoo/owl");const{uniqueId}=require("@web/core/utils/functions");const{useService}=require("@web/core/utils/hooks");const{useDomState}=require("@html_builder/core/utils");const{useCachedModel}=require("@html_builder/core/cached_model_utils");const{BuilderComponent}=require("@html_builder/core/building_blocks/builder_component");const{BasicMany2Many}=require("@html_builder/core/building_blocks/basic_many2many");const ModelMany2Many=__exports.ModelMany2Many=class ModelMany2Many extends Component{static template="html_builder.ModelMany2Many";static props={baseModel:String,recordId:Number,m2oField:String,fields:{type:Array,element:String,optional:true},domain:{type:Array,optional:true},limit:{type:Number,optional:true},createAction:{type:String,optional:true},id:{type:String,optional:true},applyTo:{type:String,optional:true},};static defaultProps={fields:[],domain:[],limit:10,};static components={BuilderComponent,BasicMany2Many};setup(){this.fields=useService("field");this.cachedModel=useCachedModel();this.state=useState({searchModel:undefined,});this.modelEdit=undefined;this.domState=useDomState((el)=>{if(!this.modelEdit){return{selection:[]};}
return{selection:this.modelEdit.get(this.props.m2oField),};});onWillStart(async()=>{await this.handleProps(this.props);});onWillUpdateProps(async(newProps)=>{await this.handleProps(newProps);});}
async handleProps(props){const[record]=await this.cachedModel.ormRead(props.baseModel,[props.recordId],[props.m2oField]);const selectedRecordIds=record[props.m2oField];const modelData=await this.fields.loadFields(props.baseModel,{fieldNames:[props.m2oField],});this.state.searchModel=modelData[props.m2oField].relation;this.modelEdit=this.cachedModel.useModelEdit({model:this.props.baseModel,recordId:props.recordId,});if(!this.modelEdit.has(props.m2oField)){const storedSelection=await this.cachedModel.ormRead(this.state.searchModel,selectedRecordIds,["display_name"]);for(const item of storedSelection){item.name=item.display_name;}
this.modelEdit.init(props.m2oField,[...storedSelection]);}
this.domState.selection=this.modelEdit.get(props.m2oField);}
setSelection(newSelection){this.modelEdit.set(this.props.m2oField,newSelection);this.env.editor.shared.history.addStep();}
create(name){this.setSelection([...this.domState.selection,{id:`new-${uniqueId()}`,name:name,display_name:name,model:this.state.searchModel,},]);}}
return __exports;});;

/* /html_builder/static/src/core/building_blocks/select_many2x.js */
odoo.define('@html_builder/core/building_blocks/select_many2x',['@odoo/owl','@web/core/utils/hooks','@html_builder/core/cached_model_utils','@web/core/l10n/translation','@web/core/select_menu/select_menu','@web/core/dropdown/dropdown_hooks','@web/core/utils/arrays'],function(require){'use strict';let __exports={};const{Component,useState,onWillUpdateProps,onWillDestroy}=require("@odoo/owl");const{useChildRef,useService}=require("@web/core/utils/hooks");const{useCachedModel}=require("@html_builder/core/cached_model_utils");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{SelectMenu}=require("@web/core/select_menu/select_menu");const{useDropdownCloser}=require("@web/core/dropdown/dropdown_hooks");const{shallowEqual}=require("@web/core/utils/arrays");class SelectMany2XCreate extends Component{static template="html_builder.SelectMany2XCreate";static props={name:String,create:Function,};setup(){this.dropdown=useDropdownCloser();this.create=this.create.bind(this);}
create(){this.dropdown.close();this.props.create(this.props.name);}}
const SelectMany2X=__exports.SelectMany2X=class SelectMany2X extends Component{static template="html_builder.SelectMany2X";static props={model:String,fields:{type:Array,element:String,optional:true},domain:{type:Array,optional:true},limit:{type:Number,optional:true},selected:{type:Array,element:{type:Object,shape:{id:[Number,String],"*":true}},},select:Function,preview:{type:Function,optional:true},revert:{type:Function,optional:true},closeOnEnterKey:{type:Boolean,optional:true},message:{type:String,optional:true},create:{type:Function,optional:true},nullText:{type:String,optional:true},};static defaultProps={fields:[],domain:[],limit:5,closeOnEnterKey:true,message:_t("Choose a record..."),};static components={SelectMenu,SelectMany2XCreate};setup(){this.orm=useService("orm");this.cachedModel=useCachedModel();this.prevSelectedIds=undefined;this.prevSearchValue=undefined;this.state=useState({nameToCreate:"",searchResults:[],limit:this.props.limit,});onWillUpdateProps(async(newProps)=>{if(this.searchInvalidationKey(this.props)!==this.searchInvalidationKey(newProps)){this.prevSelectedIds=undefined;this.prevSearchValue=undefined;this.state.searchResults=[];}});this.menuRef=useChildRef();onWillDestroy(()=>this.removeListeners?.());}
onOpened(){const menuEl=this.menuRef.el;if(menuEl){this.removeListeners?.();const onNavigatedAway=this.onNavigatedAway.bind(this);const onNavigatedBack=this.onNavigatedBack.bind(this);menuEl.addEventListener("pointerleave",onNavigatedAway);menuEl.addEventListener("pointerenter",onNavigatedBack);this.removeListeners=()=>{delete this.removeListeners;menuEl.removeEventListener("pointerleave",onNavigatedAway);menuEl.removeEventListener("pointerenter",onNavigatedBack);};}}
onClosed(){this.removeListeners?.();this.onNavigatedAway();}
searchInvalidationKey(props){return JSON.stringify([props.model,props.fields,props.domain]);}
searchMore(searchValue){this.state.limit+=this.props.limit;this.search(searchValue);}
async search(searchValue){const domain=Object.values(this.props.domain).filter((item)=>item!==null);const selectedIds=this.props.selected.map((e)=>e.id).filter((value)=>typeof value==="number");if(selectedIds.length){domain.push(["id","not in",selectedIds]);}
const tuples=await this.orm.call(this.props.model,"name_search",[],{name:searchValue,domain:domain,operator:"ilike",limit:this.state.limit+1,});this.state.hasMore=tuples.length>this.state.limit;const results=await this.cachedModel.ormRead(this.props.model,tuples.map(([id,_name])=>id),[...new Set(this.props.fields).add("display_name").add("name")]);if(this.props.nullText&&(!results.length||results[0].id)){results.unshift({id:0,name:this.props.nullText,display_name:this.props.nullText,});}
this.state.searchResults=results;}
filteredSearchResult(){const selectedIds=new Set(this.props.selected.map((e)=>e.id));return this.state.searchResults.filter((entry)=>!selectedIds.has(entry.id)).slice(0,this.state.limit);}
async canCreate(name){if(!this.props.create||!name.length){return false;}
const allRecords=await this.cachedModel.ormSearchRead(this.props.model,[],["id","name"]);const usedNames=[...allRecords.map((item)=>item.name),...this.props.selected.map((item)=>item.name),];return!usedNames.includes(name);}
async onInput(searchValue){const selectedIds=this.props.selected.map((e)=>e.id);if(searchValue===this.prevSearchValue&&shallowEqual(selectedIds,this.prevSelectedIds)){return;}
this.prevSearchValue=searchValue;this.prevSelectedIds=selectedIds;await this.search(searchValue);this.state.nameToCreate=(await this.canCreate(searchValue))?searchValue:"";}
preview(value){if(this.previewed!==value){this.previewed=value;this.props.preview?.(value);}}
revert(){delete this.previewed;this.props.revert?.();}
onNavigated(choice){choice?this.preview(choice.value):this.revert();delete this.lastPreviewed;}
onNavigatedAway(){if("previewed"in this){this.lastPreviewed=this.previewed;this.revert();}}
onNavigatedBack(){if("lastPreviewed"in this){this.preview(this.lastPreviewed);}}}
return __exports;});;

/* /html_builder/static/src/core/cached_model_plugin.js */
odoo.define('@html_builder/core/cached_model_plugin',['@html_editor/plugin','@web/core/utils/cache','@html_builder/core/cached_model_utils'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{Cache}=require("@web/core/utils/cache");const{ModelEdit}=require("@html_builder/core/cached_model_utils");const CachedModelPlugin=__exports.CachedModelPlugin=class CachedModelPlugin extends Plugin{static id="cachedModel";static shared=["ormRead","ormSearchRead","useModelEdit"];static dependencies=["history"];resources={save_handlers:this.savePendingRecords.bind(this),};setup(){this.ormReadCache=new Cache(({model,ids,fields})=>this.services.orm.read(model,ids,fields),JSON.stringify);this.ormSearchReadCache=new Cache(({model,domain,fields})=>this.services.orm.searchRead(model,domain,fields),JSON.stringify);this.modelEditCache=new Cache(({model,recordId})=>new ModelEdit(this.dependencies.history,model,recordId),JSON.stringify);}
destroy(){this.ormReadCache.invalidate();this.ormSearchReadCache.invalidate();this.modelEditCache.invalidate();}
ormRead(model,ids,fields){const SAFE_NULL=-1;const newIds=ids.map((id)=>(id===null?SAFE_NULL:id));return this.ormReadCache.read({model,ids:newIds,fields});}
ormSearchRead(model,domain,fields){return this.ormSearchReadCache.read({model,domain,fields});}
useModelEdit({model,recordId,field}){const modelEdit=this.modelEditCache.read({model,recordId,field});return modelEdit;}
async savePendingRecords(){const inventory={};for(const modelEdit of Object.values(this.modelEditCache.cache)){modelEdit.collect(inventory);}
for(const[model,records]of Object.entries(inventory)){for(const[recordId,record]of Object.entries(records)){for(const[field,value]of Object.entries(record)){const proms=value.filter((value)=>typeof value.id==="string").map((value)=>this.services.orm.create(value.model,[{name:value.name}]));const createdIDs=(await Promise.all(proms)).flat();const ids=value.filter((value)=>typeof value.id==="number").map((value)=>value.id).concat(createdIDs);await this.services.orm.write(model,[parseInt(recordId)],{[field]:[[6,0,ids]],});}}}
return!!inventory.length;}}
return __exports;});;

/* /html_builder/static/src/core/cached_model_utils.js */
odoo.define('@html_builder/core/cached_model_utils',['@odoo/owl'],function(require){'use strict';let __exports={};const{useEnv}=require("@odoo/owl");__exports.useCachedModel=useCachedModel;function useCachedModel(){return useEnv().editor.shared.cachedModel;}
const ModelEdit=__exports.ModelEdit=class ModelEdit{constructor(history,model,recordId){this.values={};this.history=history;this.model=model;this.recordId=recordId;}
has(field){return field in this.values;}
get(field){return JSON.parse(this.values[field].current);}
init(field,value){value=JSON.stringify(value);this.values[field]={initial:value,current:value};}
set(field,value){const previous=this.values[field].current;value=JSON.stringify(value);this.history.applyCustomMutation({apply:()=>{this.values[field].current=value;},revert:()=>{this.values[field].current=previous;},});}
collect(inventory){const records=inventory[this.model]||{};const record=records[this.recordId]||{};for(const field of Object.keys(this.values)){if(this.values[field].initial!==this.values[field].current){inventory[this.model]=records;records[this.recordId]=record;record[field]=JSON.parse(this.values[field].current);}}}}
return __exports;});;

/* /html_builder/static/src/core/clone_plugin.js */
odoo.define('@html_builder/core/clone_plugin',['@html_editor/plugin','@html_editor/utils/resource','@web/core/l10n/translation','@html_builder/utils/utils','@html_builder/core/remove_plugin','@html_builder/core/builder_action'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{isElementInViewport}=require("@html_builder/utils/utils");const{isRemovable}=require("@html_builder/core/remove_plugin");const{BuilderAction}=require("@html_builder/core/builder_action");const clonableSelector="a.btn:not(.oe_unremovable, .js_subscribe_btn, .s_website_form_send, .s_website_form_submit)";__exports.isClonable=isClonable;function isClonable(el){return el.matches(clonableSelector)||isRemovable(el);}
const ClonePlugin=__exports.ClonePlugin=class ClonePlugin extends Plugin{static id="clone";static dependencies=["history","builderOptions","dom"];static shared=["cloneElement"];resources={builder_actions:{CloneItemAction,},get_overlay_buttons:withSequence(2,{getButtons:this.getActiveOverlayButtons.bind(this),}),};setup(){this.overlayTarget=null;}
getActiveOverlayButtons(target){if(!isClonable(target)){this.overlayTarget=null;return[];}
const buttons=[];this.overlayTarget=target;const disabledReason=this.dependencies.builderOptions.getCloneDisabledReason(target);buttons.push({class:"o_snippet_clone fa fa-clone",title:_t("Duplicate"),disabledReason,handler:async()=>{await this.cloneElement(this.overlayTarget,{activateClone:false});this.dependencies.history.addStep();},});return buttons;}
async cloneElement(el,{position="afterend",scrollToClone=false,activateClone=true}={}){this.dispatchTo("on_will_clone_handlers",{originalEl:el});const cloneEl=el.cloneNode(true);this.dependencies.dom.removeSystemProperties(cloneEl);el.insertAdjacentElement(position,cloneEl);if(activateClone){this.dependencies.builderOptions.setNextTarget(cloneEl);}
if(scrollToClone&&!isElementInViewport(cloneEl)){cloneEl.scrollIntoView({behavior:"smooth",block:"start"});}
for(const onCloned of this.getResource("on_cloned_handlers")){await onCloned({cloneEl,originalEl:el});}
return cloneEl;}}
const CloneItemAction=__exports.CloneItemAction=class CloneItemAction extends BuilderAction{static id="addItem";static dependencies=["clone","history"];async apply({editingElement,params:{mainParam:itemSelector},value:position}){const itemEl=editingElement.querySelector(itemSelector);if(itemEl){await this.dependencies.clone.cloneElement(itemEl,{position,scrollToClone:true});this.dependencies.history.addStep();}}}
return __exports;});;

/* /html_builder/static/src/core/color_style_plugin.js */
odoo.define('@html_builder/core/color_style_plugin',['@html_editor/plugin','@web/core/registry','@html_builder/utils/utils_css','@html_editor/utils/resource'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{applyNeededCss}=require("@html_builder/utils/utils_css");const{withSequence}=require("@html_editor/utils/resource");class ColorStylePlugin extends Plugin{static id="colorStyle";static dependencies=["color"];resources={apply_color_style_overrides:withSequence(5,(element,cssProp,color)=>{applyNeededCss(element,cssProp,color);return true;}),apply_custom_css_style:withSequence(20,this.applyColorStyle.bind(this)),};applyColorStyle({editingElement,params:{mainParam:styleName=""},value}){if(styleName==="background-color"){const match=value.match(/var\(--([a-zA-Z0-9-_]+)\)/);if(match){value=`bg-${match[1]}`;}
this.dependencies.color.colorElement(editingElement,value,"backgroundColor");return true;}else if(styleName==="color"){const match=value.match(/var\(--([a-zA-Z0-9-_]+)\)/);if(match){value=`text-${match[1]}`;}
this.dependencies.color.colorElement(editingElement,value,"color");return true;}
return false;}}
registry.category("builder-plugins").add(ColorStylePlugin.id,ColorStylePlugin);return __exports;});;

/* /html_builder/static/src/core/color_ui_plugin.js */
odoo.define('@html_builder/core/color_ui_plugin',['@html_editor/main/font/color_ui_plugin','@html_builder/utils/utils_css'],function(require){'use strict';let __exports={};const{ColorUIPlugin:EditorColorUIPlugin}=require("@html_editor/main/font/color_ui_plugin");const{getAllUsedColors}=require("@html_builder/utils/utils_css");const ColorUIPlugin=__exports.ColorUIPlugin=class ColorUIPlugin extends EditorColorUIPlugin{getUsedCustomColors(mode){return getAllUsedColors(this.editable);}
getPropsForColorSelector(type){const props={...super.getPropsForColorSelector(type)};props.cssVarColorPrefix="hb-cp-";return props;}}
return __exports;});;

/* /html_builder/static/src/core/compatibility_inline_border_removal_plugin.js */
odoo.define('@html_builder/core/compatibility_inline_border_removal_plugin',['@html_editor/plugin','@web/core/registry','@html_editor/utils/resource','@html_builder/utils/utils_css'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{withSequence}=require("@html_editor/utils/resource");const{CSS_SHORTHANDS}=require("@html_builder/utils/utils_css");const NEW_STYLES=["--box-border-width","--box-border-radius"];const OLD_STYLES=["border-width","border-radius"];const CompatibilityInlineBorderRemovalPlugin=__exports.CompatibilityInlineBorderRemovalPlugin=class CompatibilityInlineBorderRemovalPlugin extends Plugin{static id="compatibilityInlineBorderRemoval";resources={apply_custom_css_style:withSequence(20,this.removeInlineBorderIfNecessary.bind(this)),};removeInlineBorderIfNecessary({editingElement,params}){const newStyleBeingEdited=NEW_STYLES.find((style)=>params.mainParam===style||CSS_SHORTHANDS[style].includes(params.mainParam));if(newStyleBeingEdited&&OLD_STYLES.some((style)=>editingElement.style[style])){for(const oldStyle of OLD_STYLES){editingElement.style.setProperty(oldStyle,"");}
const compatLayerSelectors=[".o_we_bg_filter",".o_bg_video_container",".s_parallax_bg",];const selector=`:scope > ${compatLayerSelectors.join(", :scope > ")}`;for(const childNode of editingElement.querySelectorAll(selector)){childNode.style.setProperty("border-radius","");}}
return false;}}
registry.category("builder-plugins").add(CompatibilityInlineBorderRemovalPlugin.id,CompatibilityInlineBorderRemovalPlugin);return __exports;});;

/* /html_builder/static/src/core/composite_action_plugin.js */
odoo.define('@html_builder/core/composite_action_plugin',['@html_builder/core/utils','@html_editor/plugin','@html_builder/core/builder_action'],function(require){'use strict';let __exports={};const{convertParamToObject}=require("@html_builder/core/utils");const{Plugin}=require("@html_editor/plugin");const{BuilderAction}=require("@html_builder/core/builder_action");const CompositeActionPlugin=__exports.CompositeActionPlugin=class CompositeActionPlugin extends Plugin{static id="compositeAction";static dependencies=["builderActions"];resources={builder_actions:{CompositeAction,ReloadCompositeAction,},};}
const CompositeAction=__exports.CompositeAction=class CompositeAction extends BuilderAction{static id="composite";static dependencies=["builderActions"];loadOnClean=true;async prepare({actionParam:{mainParam:actions},actionValue}){const proms=[];for(const actionDef of actions){const action=this.dependencies.builderActions.getAction(actionDef.action);if(action.has("prepare")){const actionDescr={actionId:actionDef.action};if(actionDef.actionParam){actionDescr.actionParam=convertParamToObject(actionDef.actionParam);}
if(actionDef.actionValue||actionValue){actionDescr.actionValue=actionDef.actionValue||actionValue;}
proms.push(action.prepare(actionDescr));}}
await Promise.all(proms);}
getPriority({params:{mainParam:actions},value}){const results=[];for(const actionDef of actions){const action=this.dependencies.builderActions.getAction(actionDef.action);if(action.has("getPriority")){const actionDescr=this._getActionDescription({...actionDef,value});results.push(action.getPriority(actionDescr));}}
return Math.max(...results);}
getValue({editingElement,params:{mainParam:actions}}){let actionGetValue;const actionDef=actions.find((actionDef)=>{const action=this.dependencies.builderActions.getAction(actionDef.action);if(action.has("getValue")){actionGetValue=action.getValue;}
return!!action.getValue;});if(actionDef){const actionDescr=this._getActionDescription({editingElement,actionParam:actionDef.actionParam,});return actionGetValue(actionDescr);}}
isApplied({editingElement,params:{mainParam:actions},value}){const results=[];for(const actionDef of actions){const action=this.dependencies.builderActions.getAction(actionDef.action);if(action.has("isApplied")){const actionDescr=this._getActionDescription({editingElement,...actionDef,value,});results.push(action.isApplied(actionDescr));}}
return!!results.length&&results.every((result)=>result);}
async load({editingElement,params:{mainParam:actions},value}){const loadActions=[];const loadResults=[];for(const actionDef of actions){const action=this.dependencies.builderActions.getAction(actionDef.action);if(action.has("load")){const actionDescr=this._getActionDescription({editingElement,...actionDef,value,});loadActions.push(actionDef.action);loadResults.push(await action.load(actionDescr));}}
return loadActions.reduce((acc,actionId,idx)=>{acc[actionId]=loadResults[idx];return acc;},{});}
async apply({editingElement,params:{mainParam:actions},value,loadResult,dependencyManager,selectableContext,}){for(const actionDef of actions){const action=this.dependencies.builderActions.getAction(actionDef.action);if(action.has("apply")){const actionDescr=this._getActionDescription({editingElement,value,...actionDef,loadResult,dependencyManager,selectableContext,});await action.apply(actionDescr);}}}
clean({editingElement,params:{mainParam:actions},value,loadResult,dependencyManager,selectableContext,nextAction,}){for(const actionDef of actions){const action=this.dependencies.builderActions.getAction(actionDef.action);const actionDescr=this._getActionDescription({editingElement,...actionDef,value,loadResult,dependencyManager,selectableContext,nextAction,});if(action.has("clean")){action.clean(actionDescr);}else if(action.has("apply")){if(loadResult&&loadResult[actionDef.action]){actionDescr.loadResult=loadResult[actionDef.action];}
action.apply(actionDescr);}}}
_getActionDescription(action){const{action:actionId,actionParam,actionValue,value,loadResult}=action;const actionDescr={};const forwardedSpecs=["editingElement","dependencyManager","selectableContext","nextAction",];for(const spec of forwardedSpecs){if(action[spec]){actionDescr[spec]=action[spec];}}
if(actionParam){actionDescr.params=convertParamToObject(actionParam);}
if(actionValue||value){actionDescr.value=actionValue||value;}
if(loadResult&&loadResult[actionId]){actionDescr.loadResult=loadResult[actionId];}
return actionDescr;}}
const ReloadCompositeAction=__exports.ReloadCompositeAction=class ReloadCompositeAction extends CompositeAction{static id="reloadComposite";setup(){this.reload={};}}
return __exports;});;

/* /html_builder/static/src/core/core_builder_action_plugin.js */
odoo.define('@html_builder/core/core_builder_action_plugin',['@html_editor/plugin','@html_editor/utils/formatting','@html_builder/utils/utils_css','@html_builder/core/builder_action','@html_builder/utils/utils'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{getHtmlStyle}=require("@html_editor/utils/formatting");const{CSS_SHORTHANDS,applyNeededCss,areCssValuesEqual,normalizeColor,}=require("@html_builder/utils/utils_css");const{BuilderAction}=require("@html_builder/core/builder_action");const{getValueFromVar}=require("@html_builder/utils/utils");__exports.withoutTransition=withoutTransition;function withoutTransition(editingElement,callback){if(editingElement.classList.contains("o_we_force_no_transition")){return callback();}
editingElement.classList.add("o_we_force_no_transition");try{return callback();}finally{editingElement.classList.remove("o_we_force_no_transition");}}
const CoreBuilderActionPlugin=__exports.CoreBuilderActionPlugin=class CoreBuilderActionPlugin extends Plugin{static id="coreBuilderAction";resources={builder_actions:{ClassAction,AttributeAction,StyleAction,DataAttributeAction,SetClassRangeAction,},system_classes:["o_we_force_no_transition"],};}
function getStyleValue(el,styleName){const computedStyle=window.getComputedStyle(el);const cssProps=CSS_SHORTHANDS[styleName]||[styleName];const cssValues=cssProps.map((cssProp)=>computedStyle.getPropertyValue(cssProp).trim());if(cssValues.length===4&&areCssValuesEqual(cssValues[3],cssValues[1],styleName,computedStyle)){cssValues.pop();}
if(cssValues.length===3&&areCssValuesEqual(cssValues[2],cssValues[0],styleName,computedStyle)){cssValues.pop();}
if(cssValues.length===2&&areCssValuesEqual(cssValues[1],cssValues[0],styleName,computedStyle)){cssValues.pop();}
return cssValues.join(" ");}
function setStyle(el,styleName,value,{extraClass,force=false,allowImportant=true}={}){const computedStyle=window.getComputedStyle(el);const cssProps=CSS_SHORTHANDS[styleName]||[styleName];for(const cssProp of cssProps){el.style.setProperty(cssProp,"");}
el.classList.remove(extraClass);const values=value.replace(/,\s/g,",").split(/\s+/g);while(values.length<cssProps.length){const len=values.length;const index=len==3?1:len==1||len==2?0:len-1;values.push(values[index]);}
let hasUserValue=false;const applyAllCSS=(values)=>{for(let i=cssProps.length-1;i>0;i--){hasUserValue=applyNeededCss(el,cssProps[i],values.pop(),computedStyle,{force,allowImportant,})||hasUserValue;}
hasUserValue=applyNeededCss(el,cssProps[0],values.join(" "),computedStyle,{force,allowImportant,})||hasUserValue;};applyAllCSS([...values]);if(extraClass){el.classList.toggle(extraClass,hasUserValue);if(hasUserValue){for(const cssProp of cssProps){el.style.removeProperty(cssProp);}
applyAllCSS(values);}}}
const ClassAction=__exports.ClassAction=class ClassAction extends BuilderAction{static id="classAction";getPriority({params:{mainParam:classNames}={}}){return(classNames||"")?.trim().split(/\s+/).filter(Boolean).length||0;}
isApplied({editingElement,params:{mainParam:classNames}={}}){if(classNames===undefined||classNames===""){return true;}
return classNames.split(" ").every((className)=>editingElement.classList.contains(className));}
apply({editingElement,params:{mainParam:classNames}={}}){for(const className of(classNames||"").split(" ")){if(className!==""){editingElement.classList.add(className);}}}
clean({editingElement,params:{mainParam:classNames}={}}){for(const className of(classNames||"").split(" ")){if(className!==""){editingElement.classList.remove(className);}}}}
class AttributeAction extends BuilderAction{static id="attributeAction";getValue({editingElement,params:{mainParam:attributeName}={}}){return editingElement.getAttribute(attributeName);}
isApplied({editingElement,params:{mainParam:attributeName}={},value}){if(value){return(editingElement.hasAttribute(attributeName)&&editingElement.getAttribute(attributeName)===value);}else{return!editingElement.hasAttribute(attributeName);}}
apply({editingElement,params:{mainParam:attributeName}={},value}){if(value){editingElement.setAttribute(attributeName,value);}else{editingElement.removeAttribute(attributeName);}}
clean({editingElement,params:{mainParam:attributeName}={}}){editingElement.removeAttribute(attributeName);}}
const DataAttributeAction=__exports.DataAttributeAction=class DataAttributeAction extends BuilderAction{static id="dataAttributeAction";getValue({editingElement,params:{mainParam:attributeName}={}}){if(!/(^color|Color)($|(?=[A-Z]))/.test(attributeName)){return editingElement.dataset[attributeName];}
const color=normalizeColor(editingElement.dataset[attributeName],getHtmlStyle(this.document));return color;}
isApplied({editingElement,params:{mainParam:attributeName}={},value}){if(value){value=getValueFromVar(value.toString());return editingElement.dataset[attributeName]===value;}else{return!(attributeName in editingElement.dataset);}}
apply({editingElement,params:{mainParam:attributeName}={},value}){if(value){value=getValueFromVar(value.toString());editingElement.dataset[attributeName]=value;}else{delete editingElement.dataset[attributeName];}}
clean({editingElement,params:{mainParam:attributeName}={}}){delete editingElement.dataset[attributeName];}}
class SetClassRangeAction extends BuilderAction{static id="setClassRange";getValue({editingElement,params:{mainParam:classNames}}){for(const index in classNames){const className=classNames[index];if(editingElement.classList.contains(className)){return index;}}}
apply({editingElement,params:{mainParam:classNames},value:index}){for(const className of classNames){if(editingElement.classList.contains(className)){editingElement.classList.remove(className);}}
editingElement.classList.add(classNames[index]);}}
const StyleAction=__exports.StyleAction=class StyleAction extends BuilderAction{static id="styleAction";static dependencies=["color"];getValue({editingElement:el,params:{mainParam:styleName}}){if(styleName==="--box-border-width"||CSS_SHORTHANDS["--box-border-width"].includes(styleName)||styleName==="--box-border-radius"||CSS_SHORTHANDS["--box-border-radius"].includes(styleName)){styleName=styleName.substring("--box-".length);}
if(styleName==="box-shadow"){const value=getStyleValue(el,styleName);const inset=value.includes("inset");let values=value.replace(/,\s/g,",").replace("inset","").trim().split(/\s+/g);const color=values.find((s)=>!s.match(/^\d/));values=values.join(" ").replace(color,"").trim();return`${color} ${values}${inset ? " inset" : ""}`;}else if(styleName==="border-width"||CSS_SHORTHANDS["border-width"].includes(styleName)){let value=getStyleValue(el,styleName);if(value.endsWith("px")){value=value.split(/\s+/g).map((singleValue)=>`${Math.ceil(parseFloat(singleValue))}px`).join(" ");}
return value;}else if(styleName==="row-gap"||styleName==="column-gap"){return parseInt(getStyleValue(el,styleName))||0;}else if(styleName==="width"){return el.style.width;}else if(styleName==="background-color"){return this.dependencies.color.getElementColors(el)["backgroundColor"];}else if(styleName==="color"){return this.dependencies.color.getElementColors(el)["color"];}
return this._getValueWithoutTransition(el,styleName);}
isApplied({editingElement:el,params:{mainParam:styleName},value}){const currentValue=this.getValue({editingElement:el,params:{mainParam:styleName},});return currentValue===value;}
apply({editingElement,params={},value}){if(!this.delegateTo("apply_custom_css_style",{editingElement,params,value})){this.applyCssStyle({editingElement,params,value});}}
applyCssStyle({editingElement,params={},value}){params={...params};const styleName=params.mainParam;delete params.mainParam;withoutTransition(editingElement,()=>{setStyle(editingElement,styleName,value,params);});}
_getValueWithoutTransition(el,styleName){return withoutTransition(el,()=>getStyleValue(el,styleName));}}
return __exports;});;

/* /html_builder/static/src/core/core_plugins.js */
odoo.define('@html_builder/core/core_plugins',['@html_editor/plugin_sets','@html_builder/utils/utils','@html_builder/core/anchor/anchor_plugin','@html_builder/core/builder_actions_plugin','@html_builder/core/builder_component_plugin','@html_builder/core/builder_options_plugin','@html_builder/core/builder_overlay/builder_overlay_plugin','@html_builder/core/cached_model_plugin','@html_builder/core/clone_plugin','@html_builder/core/color_ui_plugin','@html_builder/core/image_plugin','@html_builder/core/icon_plugin','@html_builder/core/core_builder_action_plugin','@html_builder/core/composite_action_plugin','@html_builder/core/customize_tab_plugin','@html_builder/core/disable_snippets_plugin','@html_builder/core/drag_and_drop_plugin','@html_builder/core/drop_zone_plugin','@html_builder/core/dropzone_selector_plugin','@html_builder/core/grid_layout/grid_layout_plugin','@html_builder/core/media_website_plugin','@html_builder/core/move_plugin','@html_builder/core/operation_plugin','@html_builder/core/overlay_buttons/overlay_buttons_plugin','@html_builder/core/remove_plugin','@html_builder/core/save_plugin','@html_builder/core/save_snippet_plugin','@html_builder/core/setup_editor_plugin','@html_builder/core/core_setup_editor_plugin','@html_builder/core/visibility_plugin','@html_builder/core/field_change_replication_plugin','@html_builder/core/builder_content_editable_plugin','@html_builder/plugins/image_field_plugin','@html_builder/plugins/monetary_field_plugin','@html_builder/plugins/many2one_option_plugin','@html_builder/core/version_error_plugin'],function(require){'use strict';let __exports={};const{MAIN_PLUGINS:MAIN_EDITOR_PLUGINS,NO_EMBEDDED_COMPONENTS_FALLBACK_PLUGINS,}=require("@html_editor/plugin_sets");const{removePlugins}=require("@html_builder/utils/utils");const{AnchorPlugin}=require("@html_builder/core/anchor/anchor_plugin");const{BuilderActionsPlugin}=require("@html_builder/core/builder_actions_plugin");const{BuilderComponentPlugin}=require("@html_builder/core/builder_component_plugin");const{BuilderOptionsPlugin}=require("@html_builder/core/builder_options_plugin");const{BuilderOverlayPlugin}=require("@html_builder/core/builder_overlay/builder_overlay_plugin");const{CachedModelPlugin}=require("@html_builder/core/cached_model_plugin");const{ClonePlugin}=require("@html_builder/core/clone_plugin");const{ColorUIPlugin}=require("@html_builder/core/color_ui_plugin");const{ImagePlugin}=require("@html_builder/core/image_plugin");const{IconPlugin}=require("@html_builder/core/icon_plugin");const{CoreBuilderActionPlugin}=require("@html_builder/core/core_builder_action_plugin");const{CompositeActionPlugin}=require("@html_builder/core/composite_action_plugin");const{CustomizeTabPlugin}=require("@html_builder/core/customize_tab_plugin");const{DisableSnippetsPlugin}=require("@html_builder/core/disable_snippets_plugin");const{DragAndDropPlugin}=require("@html_builder/core/drag_and_drop_plugin");const{DropZonePlugin}=require("@html_builder/core/drop_zone_plugin");const{DropZoneSelectorPlugin}=require("@html_builder/core/dropzone_selector_plugin");const{GridLayoutPlugin}=require("@html_builder/core/grid_layout/grid_layout_plugin");const{MediaWebsitePlugin}=require("@html_builder/core/media_website_plugin");const{MovePlugin}=require("@html_builder/core/move_plugin");const{OperationPlugin}=require("@html_builder/core/operation_plugin");const{OverlayButtonsPlugin}=require("@html_builder/core/overlay_buttons/overlay_buttons_plugin");const{RemovePlugin}=require("@html_builder/core/remove_plugin");const{SavePlugin}=require("@html_builder/core/save_plugin");const{SaveSnippetPlugin}=require("@html_builder/core/save_snippet_plugin");const{SetupEditorPlugin}=require("@html_builder/core/setup_editor_plugin");const{CoreSetupEditorPlugin}=require("@html_builder/core/core_setup_editor_plugin");const{VisibilityPlugin}=require("@html_builder/core/visibility_plugin");const{FieldChangeReplicationPlugin}=require("@html_builder/core/field_change_replication_plugin");const{BuilderContentEditablePlugin}=require("@html_builder/core/builder_content_editable_plugin");const{ImageFieldPlugin}=require("@html_builder/plugins/image_field_plugin");const{MonetaryFieldPlugin}=require("@html_builder/plugins/monetary_field_plugin");const{Many2OneOptionPlugin}=require("@html_builder/plugins/many2one_option_plugin");const{VersionErrorPlugin}=require("@html_builder/core/version_error_plugin");const mainEditorPluginsToRemove=["PowerButtonsPlugin","DoubleClickImagePreviewPlugin","SeparatorPlugin","StarPlugin","BannerPlugin","MoveNodePlugin","FontFamilyPlugin","SelectionPlaceholderPlugin","ColorUIPlugin","ImagePlugin","IconPlugin",];const MAIN_PLUGINS=__exports.MAIN_PLUGINS=[...removePlugins([...MAIN_EDITOR_PLUGINS,...NO_EMBEDDED_COMPONENTS_FALLBACK_PLUGINS],mainEditorPluginsToRemove),ColorUIPlugin,ImagePlugin,IconPlugin,];const CORE_PLUGINS=__exports.CORE_PLUGINS=[...MAIN_PLUGINS,BuilderOptionsPlugin,BuilderActionsPlugin,BuilderComponentPlugin,OperationPlugin,BuilderOverlayPlugin,OverlayButtonsPlugin,MovePlugin,GridLayoutPlugin,DragAndDropPlugin,RemovePlugin,ClonePlugin,SaveSnippetPlugin,AnchorPlugin,DropZonePlugin,DisableSnippetsPlugin,MediaWebsitePlugin,SetupEditorPlugin,CoreSetupEditorPlugin,SavePlugin,VisibilityPlugin,DropZoneSelectorPlugin,CachedModelPlugin,CoreBuilderActionPlugin,CompositeActionPlugin,CustomizeTabPlugin,FieldChangeReplicationPlugin,BuilderContentEditablePlugin,ImageFieldPlugin,MonetaryFieldPlugin,Many2OneOptionPlugin,VersionErrorPlugin,];return __exports;});;

/* /html_builder/static/src/core/core_setup_editor_plugin.js */
odoo.define('@html_builder/core/core_setup_editor_plugin',['@html_editor/plugin'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const CoreSetupEditorPlugin=__exports.CoreSetupEditorPlugin=class CoreSetupEditorPlugin extends Plugin{static id="core_setup_editor_plugin";resources={o_editable_selectors:"[data-oe-model]",};}
return __exports;});;

/* /html_builder/static/src/core/customize_tab_plugin.js */
odoo.define('@html_builder/core/customize_tab_plugin',['@html_editor/plugin','@odoo/owl','@web/core/registry'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{reactive}=require("@odoo/owl");const{registry}=require("@web/core/registry");const CustomizeTabPlugin=__exports.CustomizeTabPlugin=class CustomizeTabPlugin extends Plugin{static id="customizeTab";static shared=["getCustomizeComponent","openCustomizeComponent","closeCustomizeComponent"];resources={post_redo_handlers:()=>this.closeCustomizeComponent(),post_undo_handlers:()=>this.closeCustomizeComponent(),change_current_options_containers_listeners:()=>this.closeCustomizeComponent(),};setup(){this.customizeComponent=reactive({component:null,props:{},editingEls:null,});this.closeCustomizeComponent=this.closeCustomizeComponent.bind(this);}
getCustomizeComponent(){return this.customizeComponent;}
openCustomizeComponent(component,editingEls,props={}){this.customizeComponent.component=component;this.customizeComponent.editingEls=editingEls;this.customizeComponent.props={...props,onClose:this.closeCustomizeComponent,};}
closeCustomizeComponent(){if(this.customizeComponent){this.customizeComponent.component=null;this.customizeComponent.editingEls=null;this.customizeComponent.props={};}}}
registry.category("builder-plugins").add(CustomizeTabPlugin.id,CustomizeTabPlugin);return __exports;});;

/* /html_builder/static/src/core/dependency_manager.js */
odoo.define('@html_builder/core/dependency_manager',['@odoo/owl','@web/core/utils/timing'],function(require){'use strict';let __exports={};const{EventBus}=require("@odoo/owl");const{batched}=require("@web/core/utils/timing");const DependencyManager=__exports.DependencyManager=class DependencyManager extends EventBus{constructor(){super();this.dependencies=[];this.dependenciesMap={};this.count=0;this.dirty=false;this.triggerDependencyUpdated=batched(()=>{this.trigger("dependency-updated");});}
update(){this.dependenciesMap={};for(const[id,value,ignored]of this.dependencies.slice().reverse()){if(ignored&&id in this.dependenciesMap){continue;}
this.dependenciesMap[id]=value;}
this.dirty=false;}
add(id,value,ignored=false){if(!ignored||!(id in this.dependenciesMap)){this.triggerDependencyUpdated();}
this.dependencies.push([id,value,ignored]);this.dirty=true;}
get(id){if(this.dirty){this.update();}
return this.dependenciesMap[id];}
removeByValue(value){this.dependencies=this.dependencies.filter(([,v])=>v!==value);this.dirty=true;this.triggerDependencyUpdated();}}
return __exports;});;

/* /html_builder/static/src/core/disable_snippets_plugin.js */
odoo.define('@html_builder/core/disable_snippets_plugin',['@web/core/utils/objects','@html_editor/plugin','@html_editor/utils/resource'],function(require){'use strict';let __exports={};const{omit}=require("@web/core/utils/objects");const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const DisableSnippetsPlugin=__exports.DisableSnippetsPlugin=class DisableSnippetsPlugin extends Plugin{static id="disableSnippets";static dependencies=["setup_editor_plugin","dropzone","dropzone_selector"];static shared=["disableUndroppableSnippets"];resources={on_removed_handlers:this.disableUndroppableSnippets.bind(this),post_undo_handlers:this.disableUndroppableSnippets.bind(this),post_redo_handlers:this.disableUndroppableSnippets.bind(this),on_mobile_preview_clicked:withSequence(20,this.disableUndroppableSnippets.bind(this)),};setup(){this.snippetModel=this.config.snippetModel;this._disableSnippets=this.disableUndroppableSnippets.bind(this);const editableDropdownEls=this.editable.querySelectorAll(".dropdown-menu.o_editable");editableDropdownEls.forEach((dropdownEl)=>{const dropdownToggleEl=dropdownEl.parentNode.querySelector(".dropdown-toggle");this.addDomListener(dropdownToggleEl,"shown.bs.dropdown",this._disableSnippets);this.addDomListener(dropdownToggleEl,"hidden.bs.dropdown",this._disableSnippets);});const offcanvasEls=this.editable.querySelectorAll(".offcanvas");offcanvasEls.forEach((offcanvasEl)=>{this.addDomListener(offcanvasEl,"shown.bs.offcanvas",this._disableSnippets);this.addDomListener(offcanvasEl,"hidden.bs.offcanvas",this._disableSnippets);});this.disableUndroppableSnippets();}
disableUndroppableSnippets(){const editableAreaEls=this.dependencies.setup_editor_plugin.getEditableAreas();const rootEl=this.dependencies.dropzone.getDropRootElement();const dropAreasBySelector=this.getDropAreas(editableAreaEls,rootEl);const checkSanitize=(el,snippetEl)=>{let forbidSanitize=false;for(const el of[snippetEl,...snippetEl.querySelectorAll("[data-snippet")]){const snippet=this.snippetModel.getOriginalSnippet(el.dataset.snippet);if(snippet&&snippet.forbidSanitize){forbidSanitize=snippet.forbidSanitize;if(forbidSanitize===true){break;}}}
if(forbidSanitize==="form"){return!el.closest('[data-oe-sanitize]:not([data-oe-sanitize="allow_form"])');}else{return forbidSanitize?!el.closest("[data-oe-sanitize]"):true;}};const canDrop=(snippet)=>{const snippetEl=snippet.content;return!!dropAreasBySelector.find(({selector,exclude,dropAreaEls})=>snippetEl.matches(selector)&&!snippetEl.matches(exclude)&&dropAreaEls.some((el)=>checkSanitize(el,snippetEl)));};const snippetGroups=this.snippetModel.snippetsByCategory["snippet_groups"];let areGroupsDisabled=false;if(snippetGroups.length&&!canDrop(snippetGroups[0])){snippetGroups.forEach((snippetGroup)=>(snippetGroup.isDisabled=true));areGroupsDisabled=true;}
const snippets=[];const ignoredCategories=["snippet_groups"];if(areGroupsDisabled){ignoredCategories.push(...["snippet_structure","snippet_custom"]);}
for(const category in omit(this.snippetModel.snippetsByCategory,...ignoredCategories)){snippets.push(...this.snippetModel.snippetsByCategory[category]);}
snippets.forEach((snippet)=>{snippet.isDisabled=!canDrop(snippet);});if(!areGroupsDisabled){snippetGroups.forEach((snippetGroup)=>{if(snippetGroup.groupName!=="custom"){snippetGroup.isDisabled=!snippets.find((snippet)=>snippet.groupName===snippetGroup.groupName&&!snippet.isDisabled);}else{const customSnippets=this.snippetModel.snippetsByCategory["snippet_custom"];snippetGroup.isDisabled=!customSnippets.find((snippet)=>!snippet.isDisabled);}});}}
getDropAreas(editableAreaEls,rootEl){const dropAreasBySelector=[];this.getResource("dropzone_selector").forEach((dropzoneSelector)=>{const{selector,exclude=false,dropIn,dropNear,excludeNearParent,}=dropzoneSelector;const dropAreaEls=[];if(dropNear){dropAreaEls.push(...this.dependencies.dropzone.getSelectorSiblings(editableAreaEls,rootEl,{selector:dropNear,excludeParent:excludeNearParent,}));}
if(dropIn){dropAreaEls.push(...this.dependencies.dropzone.getSelectorChildren(editableAreaEls,rootEl,{selector:dropIn,}));}
if(dropAreaEls.length){dropAreasBySelector.push({selector,exclude,dropAreaEls});}});return dropAreasBySelector;}}
return __exports;});;

/* /html_builder/static/src/core/disable_snippets_plugin_translation.js */
odoo.define('@html_builder/core/disable_snippets_plugin_translation',['@html_editor/plugin'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const DisableSnippetsPlugin=__exports.DisableSnippetsPlugin=class DisableSnippetsPlugin extends Plugin{static id="disableSnippets";static shared=["disableUndroppableSnippets"];disableUndroppableSnippets(){}}
return __exports;});;

/* /html_builder/static/src/core/drag_and_drop_move_handle.js */
odoo.define('@html_builder/core/drag_and_drop_move_handle',['@odoo/owl','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{Component,onMounted}=require("@odoo/owl");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const DragAndDropMoveHandle=__exports.DragAndDropMoveHandle=class DragAndDropMoveHandle extends Component{static template="html_builder.DragAndDropMoveHandle";static props={onRenderedCallback:{type:Function},};setup(){this.title=_t("Drag and move");onMounted(()=>{this.props.onRenderedCallback();});}}
return __exports;});;

/* /html_builder/static/src/core/drag_and_drop_plugin.js */
odoo.define('@html_builder/core/drag_and_drop_plugin',['@html_editor/plugin','@html_editor/utils/resource','@html_editor/utils/drag_and_drop','@web/core/utils/scrolling','@web/core/utils/ui','@web/core/utils/numbers','@html_builder/utils/grid_layout_utils','@html_builder/utils/utils','@html_builder/core/drag_and_drop_move_handle'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{useDragAndDrop}=require("@html_editor/utils/drag_and_drop");const{closestScrollableY,getScrollingElement,isScrollableY}=require("@web/core/utils/scrolling");const{closest,touching}=require("@web/core/utils/ui");const{clamp}=require("@web/core/utils/numbers");const{rowSize}=require("@html_builder/utils/grid_layout_utils");const{isEditable,isVisible}=require("@html_builder/utils/utils");const{DragAndDropMoveHandle}=require("@html_builder/core/drag_and_drop_move_handle");const DragAndDropPlugin=__exports.DragAndDropPlugin=class DragAndDropPlugin extends Plugin{static id="dragAndDrop";static dependencies=["dropzone","history","operation","builderOptions"];resources={has_overlay_options:{hasOption:(el)=>this.isDraggable(el)},get_overlay_buttons:withSequence(1,{getButtons:this.getActiveOverlayButtons.bind(this),}),system_classes:["o_draggable"],clean_for_save_handlers:this.cleanForSave.bind(this),};setup(){this.dropzoneSelectors=this.getResource("dropzone_selector");this.overlayTarget=null;this.iframe=this.document.defaultView.frameElement;this.isRtl=this.config.isEditableRTL;}
destroy(){this.draggableComponent?.destroy();this.draggableComponentImgs?.destroy();}
cleanForSave({root}){[root,...root.querySelectorAll(".o_draggable")].forEach((el)=>{el.classList.remove("o_draggable");});}
isDraggable(el){const isDraggable=isEditable(el.parentNode)&&!el.matches(".oe_unmovable")&&!!this.dropzoneSelectors.find(({selector,exclude=false})=>el.matches(selector)&&!el.matches(exclude));if(!isDraggable){return false;}
for(const isDraggable of this.getResource("is_draggable_handlers")){if(!isDraggable(el)){return false;}}
return true;}
getActiveOverlayButtons(target){if(!this.isDraggable(target)){this.overlayTarget=null;this.draggableComponent?.destroy();this.draggableComponentImgs?.destroy();return[];}
const buttons=[];this.overlayTarget=target;buttons.push({Component:DragAndDropMoveHandle,props:{onRenderedCallback:()=>{this.draggableComponent?.destroy();this.draggableComponentImgs?.destroy();this.draggableComponent=this.initDragAndDrop(".o_move_handle",".o_overlay_options",document.querySelector(".o_move_handle"));if(!this.overlayTarget.matches("section")){this.draggableComponentImgs=this.initDragAndDrop("img",".o_draggable",this.overlayTarget,true);}},},});return buttons;}
initDragAndDrop(handleSelector,elementsSelector,element,fromIframe=false){let dropzoneEls=[];let dragAndDropResolve;const iframeWindow=this.document.defaultView!==window?this.document.defaultView:false;const scrollingElement=()=>{let scrollingElement=this.dependencies.dropzone.getDropRootElement()||getScrollingElement(this.document);if(!isScrollableY(scrollingElement)){scrollingElement=closestScrollableY(this.iframe)??scrollingElement;}
return scrollingElement;};const dragAndDropOptions={ref:{el:element},iframeWindow,cursor:"move",elements:elementsSelector,scrollingElement,handle:handleSelector,allowDisconnected:true,enable:()=>!!document.querySelector(".o_move_handle")||this.dragStarted,dropzones:()=>dropzoneEls,helper:({helperOffset})=>{const draggedEl=document.createElement("div");draggedEl.classList.add("o_drag_move_helper");Object.assign(draggedEl.style,{width:"24px",height:"24px",});document.body.append(draggedEl);const iframeRect=this.document.defaultView.frameElement.getBoundingClientRect();helperOffset.x=12-(fromIframe?iframeRect.x:0);helperOffset.y=12;return draggedEl;},onDragStart:({x,y})=>{const dragAndDropProm=new Promise((resolve)=>(dragAndDropResolve=()=>resolve()));this.dependencies.operation.next(async()=>await dragAndDropProm,{withLoadingEffect:false,canTimeout:false,});const restoreDragSavePoint=this.dependencies.history.makeSavePoint();this.cancelDragAndDrop=()=>{this.dependencies.dropzone.removeDropzones();this.dragState.restoreCallbacks?.forEach((restore)=>restore());restoreDragSavePoint();dragAndDropResolve();this.dependencies.builderOptions.updateContainers(this.overlayTarget);};this.dragStarted=true;this.dragState={};dropzoneEls=[];let targetRect=this.overlayTarget.getBoundingClientRect();const gridRowSize=rowSize;const boundedYMousePosition=clamp(y,targetRect.top+12,targetRect.bottom-gridRowSize);this.dragState.mousePositionYOnElement=boundedYMousePosition-targetRect.y;this.dragState.mousePositionXOnElement=(x-targetRect.x)*(this.isRtl?-1:1);const restoreCallbacks=[];for(const prepareDrag of this.getResource("on_prepare_drag_handlers")){const restore=prepareDrag();restoreCallbacks.unshift(restore);}
this.dragState.restoreCallbacks=restoreCallbacks;this.dispatchTo("on_element_dragged_handlers",{draggedEl:this.overlayTarget,dragState:this.dragState,});targetRect=this.overlayTarget.getBoundingClientRect();this.dragState.startTop=targetRect.top;this.dragState.startMiddle=targetRect.left+targetRect.width/2;this.dragState.overFirstDropzone=true;const targetStyle=window.getComputedStyle(this.overlayTarget);const toInsertInline=targetStyle.display.includes("inline");const parentEl=this.overlayTarget.parentElement;this.dragState.startParentEl=parentEl;this.dragState.startPreviousEl=this.overlayTarget.previousElementSibling;this.dragState.startNextEl=this.overlayTarget.nextElementSibling;const visibleSiblingEl=[...parentEl.children].find((el)=>el!==this.overlayTarget&&isVisible(el));if(parentEl.children.length===1||!visibleSiblingEl){const dropCloneEl=this.overlayTarget.cloneNode();dropCloneEl.classList.add("oe_drop_clone");dropCloneEl.style.visibility="hidden";dropCloneEl.style.height=`${targetRect.height}px`;dropCloneEl.style.width=`${targetRect.width}px`;this.overlayTarget.after(dropCloneEl);this.dragState.dropCloneEl=dropCloneEl;}
const isColumn=parentEl.classList.contains("row");const withGrids=isColumn||"filterOnly";const selectors=this.dependencies.dropzone.getSelectors(this.overlayTarget,true,withGrids);this.overlayTarget.remove();this.dependencies.builderOptions.deactivateContainers();dropzoneEls=this.dependencies.dropzone.activateDropzones(selectors,{toInsertInline,});},dropzoneOver:({dropzone})=>{const dropzoneEl=dropzone.el;if(this.dragState.overFirstDropzone){this.dragState.overFirstDropzone=false;const{startTop,startMiddle}=this.dragState;const helperRect={x:startMiddle-12,y:startTop-24,width:24,height:24,};const dropzoneRect=dropzoneEl.getBoundingClientRect();const dropzoneBottom=dropzoneRect.bottom;const isGluedToDropzone=startTop>=dropzoneBottom&&!!touching([dropzoneEl],helperRect).length;if(isGluedToDropzone){return;}}
dropzoneEl.classList.add("invisible");dropzoneEl.after(this.overlayTarget);this.dragState.currentDropzoneEl=dropzoneEl;this.dispatchTo("on_element_over_dropzone_handlers",{draggedEl:this.overlayTarget,dragState:this.dragState,});},onDrag:({x,y})=>{if(!this.dragState.currentDropzoneEl){return;}
this.dispatchTo("on_element_move_handlers",{draggedEl:this.overlayTarget,dragState:this.dragState,x,y,});},dropzoneOut:()=>{const dropzoneEl=this.dragState.currentDropzoneEl;if(!dropzoneEl){return;}
this.dispatchTo("on_element_out_dropzone_handlers",{draggedEl:this.overlayTarget,dragState:this.dragState,});this.overlayTarget.remove();dropzoneEl.classList.remove("invisible");this.dragState.currentDropzoneEl=null;},onDragEnd:async({x,y})=>{this.dragStarted=false;let currentDropzoneEl=this.dragState.currentDropzoneEl;const isDroppedOver=!!currentDropzoneEl;if(!currentDropzoneEl){const closestDropzoneEl=closest(dropzoneEls,{x,y});if(!closestDropzoneEl){this.cancelDragAndDrop();return;}
currentDropzoneEl=closestDropzoneEl;}
if(isDroppedOver){this.dispatchTo("on_element_dropped_over_handlers",{droppedEl:this.overlayTarget,dragState:this.dragState,});}else{currentDropzoneEl.after(this.overlayTarget);this.dispatchTo("on_element_dropped_near_handlers",{droppedEl:this.overlayTarget,dropzoneEl:currentDropzoneEl,dragState:this.dragState,});}
const{startPreviousEl,startNextEl,startParentEl}=this.dragState;if(startPreviousEl){startPreviousEl.after(this.overlayTarget);}else if(startNextEl){startNextEl.before(this.overlayTarget);}else{startParentEl.prepend(this.overlayTarget);}
this.dragState.restoreCallbacks.forEach((restore)=>restore());this.dragState.restoreCallbacks=null;currentDropzoneEl.after(this.overlayTarget);this.dependencies.dropzone.removeDropzones();this.dragState.dropCloneEl?.remove();for(const onElementDropped of this.getResource("on_element_dropped_handlers")){const cancel=await onElementDropped({droppedEl:this.overlayTarget,dragState:this.dragState,});if(cancel){this.cancelDragAndDrop();return;}}
let hasSamePositionAsStart;if("hasSamePositionAsStart"in this.dragState){hasSamePositionAsStart=this.dragState.hasSamePositionAsStart();}else{const previousEl=this.overlayTarget.previousElementSibling;const nextEl=this.overlayTarget.nextElementSibling;const parentEl=this.overlayTarget.parentElement;hasSamePositionAsStart=startPreviousEl===previousEl&&startNextEl===nextEl&&startParentEl===parentEl;}
if(!hasSamePositionAsStart){this.dependencies.history.addStep();}else{this.cancelDragAndDrop();return;}
dragAndDropResolve();this.dependencies.builderOptions.updateContainers(this.overlayTarget);},};return useDragAndDrop(dragAndDropOptions);}}
return __exports;});;

/* /html_builder/static/src/core/drop_zone_plugin.js */
odoo.define('@html_builder/core/drop_zone_plugin',['@html_builder/utils/utils','@html_editor/plugin','@html_editor/utils/dom_info','@html_editor/utils/dom_traversal','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{isVisible}=require("@html_builder/utils/utils");const{Plugin}=require("@html_editor/plugin");const{isElement}=require("@html_editor/utils/dom_info");const{closestElement}=require("@html_editor/utils/dom_traversal");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const DropZonePlugin=__exports.DropZonePlugin=class DropZonePlugin extends Plugin{static id="dropzone";static dependencies=["history","setup_editor_plugin"];static shared=["activateDropzones","removeDropzones","getDropRootElement","getSelectorSiblings","getSelectorChildren","getSelectors",];resources={savable_mutation_record_predicates:(record)=>{if(record.type==="childList"){const addedOrRemovedNode=(record.addedTrees[0]||record.removedTrees[0]).node;if(isElement(addedOrRemovedNode)&&addedOrRemovedNode.matches(".oe_drop_zone")){return false;}}
return true;},selection_placeholder_container_predicates:(container)=>{if(container.classList.contains("oe_structure")){return false;}},};setup(){this.snippetModel=this.config.snippetModel;this.dropzoneSelectors=this.getResource("dropzone_selector");this.iframe=this.document.defaultView.frameElement;}
getDropRootElement(){const openModalEl=this.editable.querySelector(".modal.show");if(openModalEl&&isVisible(openModalEl)){return openModalEl;}
const openDropdownEl=this.editable.querySelector(".o_editable.dropdown-menu.show, .dropdown-menu.show .o_editable.dropdown-menu");if(openDropdownEl){return openDropdownEl;}
const openOffcanvasEl=this.editable.querySelector(".offcanvas.show");if(openOffcanvasEl){return openOffcanvasEl.querySelector(".offcanvas-body");}}
getSelectors(snippetEl,checkLockedWithin=false,withGrids=false){let selectorChildren=[];let selectorSiblings=[];const selectorExcludeAncestor=[];const selectorLockedWithin=[];const editableAreaEls=this.dependencies.setup_editor_plugin.getEditableAreas();const rootEl=this.getDropRootElement();this.dropzoneSelectors.forEach((dropzoneSelector)=>{const{selector,exclude=false,dropIn,dropNear,dropLockWithin,excludeAncestor,excludeNearParent,}=dropzoneSelector;if(snippetEl.matches(selector)&&!snippetEl.matches(exclude)){if(dropNear){selectorSiblings.push(...this.getSelectorSiblings(editableAreaEls,rootEl,{selector:dropNear,excludeParent:excludeNearParent,}));}
if(dropIn){selectorChildren.push(...this.getSelectorChildren(editableAreaEls,rootEl,{selector:dropIn}));}
if(dropLockWithin){selectorLockedWithin.push(dropLockWithin);}
if(excludeAncestor){selectorExcludeAncestor.push(excludeAncestor);}}});selectorSiblings=selectorSiblings.filter((el)=>!snippetEl.contains(el));selectorChildren=selectorChildren.filter((el)=>!snippetEl.contains(el));const hasForm=snippetEl.matches("form")||!!snippetEl.querySelector("form");if(hasForm&&!selectorExcludeAncestor.includes("form")){selectorExcludeAncestor.push("form");}
if(selectorExcludeAncestor.length){const excludeAncestor=selectorExcludeAncestor.join(",");selectorSiblings=selectorSiblings.filter((el)=>!el.closest(excludeAncestor));selectorChildren=selectorChildren.filter((el)=>!el.closest(excludeAncestor));}
if(checkLockedWithin&&selectorLockedWithin.length){const lockedAncestorsSelector=selectorLockedWithin.join(",");const closestLockedAncestorEl=snippetEl.closest(lockedAncestorsSelector);const filterFct=(el)=>el.closest(lockedAncestorsSelector)===closestLockedAncestorEl;selectorSiblings=selectorSiblings.filter(filterFct);selectorChildren=selectorChildren.filter(filterFct);}
let forbidSanitize=false;for(const el of[snippetEl,...snippetEl.querySelectorAll("[data-snippet")]){const snippet=this.snippetModel.getOriginalSnippet(el.dataset.snippet);if(snippet&&snippet.forbidSanitize){forbidSanitize=snippet.forbidSanitize;if(forbidSanitize===true){break;}}}
const selectorSanitized=new Set();const filterSanitized=(el)=>{if(el.closest('[data-oe-sanitize="no_block"]')){return false;}
let sanitizedZoneEl;if(forbidSanitize==="form"){sanitizedZoneEl=el.closest('[data-oe-sanitize]:not([data-oe-sanitize="allow_form"]):not([data-oe-sanitize="no_block"])');}else if(forbidSanitize){sanitizedZoneEl=el.closest('[data-oe-sanitize]:not([data-oe-sanitize="no_block"])');}
if(sanitizedZoneEl){selectorSanitized.add(sanitizedZoneEl);return false;}
return true;};selectorSiblings=selectorSiblings.filter((el)=>filterSanitized(el));selectorChildren=selectorChildren.filter((el)=>filterSanitized(el));let selectorGrids=new Set();if(withGrids){const filterGrids=(potentialGridEl)=>{if(potentialGridEl.matches(".o_grid_mode")){selectorGrids.add(potentialGridEl);return false;}
return true;};selectorSiblings=selectorSiblings.filter((el)=>filterGrids(el.parentElement));selectorChildren=selectorChildren.filter((el)=>filterGrids(el));if(withGrids==="filterOnly"){selectorGrids=new Set();}}
return{selectorSiblings:new Set(selectorSiblings),selectorChildren:new Set(selectorChildren),selectorSanitized,selectorGrids,};}
checkSelectors(el,rootEl){if(rootEl&&!rootEl.contains(el)){return false;}
if(!isVisible(el)){return false;}
if((el.closest(".dropdown-menu")&&!el.closest(".dropdown-menu.show"))||(el.closest(".offcanvas")&&!el.closest(".offcanvas.show"))){return false;}
return true;}
getSelectorSiblings(editableAreaEls,rootEl,{selector,excludeParent=false}){const filterFct=(el)=>this.checkSelectors(el,rootEl)&&!el.parentNode.closest("[data-oe-type=image]")&&!el.matches(".o_not_editable *")&&!el.matches(".o_we_no_overlay")&&!this.delegateTo("filter_for_sibling_dropzone_predicates",el)&&(excludeParent?!el.parentNode.matches(excludeParent):true);const dropAreaEls=[];editableAreaEls.forEach((el)=>{const areaEls=[...el.querySelectorAll(selector)].filter(filterFct);dropAreaEls.push(...areaEls);});return dropAreaEls;}
getSelectorChildren(editableAreaEls,rootEl,{selector}){const filterFct=(el)=>this.checkSelectors(el,rootEl)&&!el.closest("[data-oe-type=image]")&&!el.matches('.o_not_editable :not([contenteditable="true"]), .o_not_editable');const dropAreaEls=[];editableAreaEls.forEach((el)=>{const areaEls=el.matches(selector)?[el]:[];areaEls.push(...el.querySelectorAll(selector));dropAreaEls.push(...areaEls.filter(filterFct));});return dropAreaEls;}
createDropzone(parentEl,isVertical,style){const dropzoneEl=this.document.createElement("div");dropzoneEl.classList.add("oe_drop_zone","oe_insert");const editorMessagesAttributes=["data-editor-message-default","data-editor-message","data-editor-sub-message",];for(const messageAttribute of editorMessagesAttributes){const message=parentEl.getAttribute(messageAttribute);if(message){dropzoneEl.setAttribute(messageAttribute,message);}}
if(isVertical){dropzoneEl.classList.add("oe_vertical");}
Object.assign(dropzoneEl.style,style);return dropzoneEl;}
createSanitizedDropzone(){const dropzoneEl=this.document.createElement("div");dropzoneEl.classList.add("oe_drop_zone","oe_insert","oe_sanitized_drop_zone","text-center","text-uppercase");const messageEl=this.document.createElement("p");messageEl.textContent=_t("For technical reasons, this block cannot be dropped here");dropzoneEl.prepend(messageEl);return dropzoneEl;}
createGridDropzone(rowEl){const columnCount=12;const rowCount=parseInt(rowEl.dataset.rowCount);const dropzoneEl=this.document.createElement("div");dropzoneEl.classList.add("oe_drop_zone","oe_insert","oe_grid_zone");Object.assign(dropzoneEl.style,{gridArea:1+"/"+1+"/"+(rowCount+1)+"/"+(columnCount+1),minHeight:window.getComputedStyle(rowEl).height,width:window.getComputedStyle(rowEl).width,});return dropzoneEl;}
setDropzoneDirection(hookEl,parentEl,toInsertInline){let vertical=false;const style={};const hookStyle=window.getComputedStyle(hookEl);const parentStyle=window.getComputedStyle(parentEl);const float=hookStyle.float||hookStyle.cssFloat;const{display,flexDirection}=parentStyle;if(toInsertInline||float==="left"||float==="right"||(display==="flex"&&flexDirection==="row")){if(!toInsertInline){style.float=float;}
const parentPaddingX=parseFloat(parentStyle.paddingLeft)+parseFloat(parentStyle.paddingRight);const parentBorderX=parseFloat(parentStyle.borderLeft)+parseFloat(parentStyle.borderRight);const hookMarginX=parseFloat(hookStyle.marginLeft)+parseFloat(hookStyle.marginRight);const parentContentWidth=parentEl.getBoundingClientRect().width-parentPaddingX-parentBorderX;const hookOuterWidth=hookEl.getBoundingClientRect().width+hookMarginX;if(parseInt(parentContentWidth)!==parseInt(hookOuterWidth)){vertical=true;const hookOuterHeight=hookEl.getBoundingClientRect().height;style.height=Math.max(hookOuterHeight,30)+"px";if(toInsertInline){style.display="inline-block";style.verticalAlign="middle";style.float="none";}}}
return{vertical,style};}
activateDropzones({selectorSiblings,selectorChildren,selectorSanitized,selectorGrids},{toInsertInline,isContentInIframe=true}={}){const isIgnored=(el)=>el.matches(".o_we_no_overlay")||!isVisible(el);let hookEls=[];for(const parentEl of selectorChildren){const validChildrenEls=[...parentEl.children].filter((el)=>!isIgnored(el));hookEls.push(...validChildrenEls);parentEl.prepend(this.createDropzone(parentEl));}
hookEls.push(...selectorSiblings);const systemNodeSelectors=this.getResource("system_node_selectors").join(",");if(systemNodeSelectors){hookEls=hookEls.filter((el)=>!closestElement(el,systemNodeSelectors));}
for(const hookEl of hookEls){const parentEl=hookEl.parentElement;const{vertical,style}=this.setDropzoneDirection(hookEl,parentEl,toInsertInline);let previousEl=hookEl.previousElementSibling;while(previousEl&&isIgnored(previousEl)){previousEl=previousEl.previousElementSibling;}
if(!previousEl||!previousEl.classList.contains("oe_drop_zone")){hookEl.before(this.createDropzone(parentEl,vertical,style));}
if(hookEl.classList.contains("oe_drop_clone")){continue;}
let nextEl=hookEl.nextElementSibling;while(nextEl&&isIgnored(nextEl)){nextEl=nextEl.nextElementSibling;}
if(!nextEl||!nextEl.classList.contains("oe_drop_zone")){hookEl.after(this.createDropzone(parentEl,vertical,style));}}
for(const sanitizedZoneEl of selectorSanitized){sanitizedZoneEl.style.position="relative";sanitizedZoneEl.prepend(this.createSanitizedDropzone());}
this.sanitizedZoneEls=selectorSanitized;for(const rowEl of selectorGrids){rowEl.append(this.createGridDropzone(rowEl));}
if(isContentInIframe){const dropzoneEls=[...this.editable.querySelectorAll(".oe_drop_zone")];dropzoneEls.forEach((dropzoneEl)=>{dropzoneEl.oldGetBoundingRect=dropzoneEl.getBoundingClientRect;dropzoneEl.getBoundingClientRect=()=>{const iframeRect=this.iframe.getBoundingClientRect();const rect=dropzoneEl.oldGetBoundingRect();rect.x+=iframeRect.x;rect.y+=iframeRect.y;return rect;};});}
return[...this.editable.querySelectorAll(".oe_drop_zone:not(.oe_sanitized_drop_zone)")];}
removeDropzones(){this.editable.querySelectorAll(".oe_drop_zone").forEach((dropzoneEl)=>{dropzoneEl.remove();});this.sanitizedZoneEls.forEach((sanitizedZoneEl)=>sanitizedZoneEl.style.removeProperty("position"));this.sanitizedZoneEls=[];}}
return __exports;});;

/* /html_builder/static/src/core/dropzone_selector_plugin.js */
odoo.define('@html_builder/core/dropzone_selector_plugin',['@html_editor/plugin'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const card_parent_handlers=".s_three_columns .row > div, .s_comparisons .row > div, .s_cards_grid .row > div, .s_cards_soft .row > div, .s_product_list .row > div, .s_newsletter_centered .row > div, .s_company_team_spotlight .row > div, .s_comparisons_horizontal .row > div, .s_company_team_grid .row > div, .s_company_team_card .row > div, .s_carousel_cards_item";const special_cards_selector=`.s_card.s_timeline_card, div:is(${card_parent_handlers}) > .s_card`;const so_snippet_addition_drop_in=":not(p).oe_structure:not(.oe_structure_solo), :not(.o_mega_menu):not(p)[data-oe-type=html], :not(p).oe_structure.oe_structure_solo:not(:has(> section:not(.s_snippet_group), > div:not(.o_hook_drop_zone)))";const DropZoneSelectorPlugin=__exports.DropZoneSelectorPlugin=class DropZoneSelectorPlugin extends Plugin{static id="dropzone_selector";resources={dropzone_selector:[{selector:".accordion > .accordion-item",dropIn:".accordion:has(> .accordion-item)",},{plugin:this,get selector(){return this.plugin.getResource("so_snippet_addition_selector").join(", ");},dropIn:so_snippet_addition_drop_in,},{plugin:this,get selector(){return[...this.plugin.getResource("so_content_addition_selector"),".s_card",].join(", ");},exclude:`${special_cards_selector}`,dropIn:"nav, .row.o_grid_mode",get dropNear(){return`p, h1, h2, h3, ul, ol, div:not(.o_grid_item_image) > img, div:not(.o_grid_item_image) > a, .btn, ${this.plugin
                        .getResource("so_content_addition_selector")
                        .join(", ")}, .s_card:not(${special_cards_selector})`;},excludeNearParent:so_snippet_addition_drop_in,},{selector:".row > div",exclude:".s_col_no_resize.row > div, .s_col_no_resize",dropNear:".row:not(.s_col_no_resize) > div",},{selector:".row > div",exclude:".s_col_no_resize.row > div, .s_col_no_resize",dropNear:".row.o_grid_mode > div",},],so_snippet_addition_selector:["section",".parallax",".s_hr"],so_content_addition_selector:["blockquote",".s_text_highlight",".s_donation",".o_snippet_drop_in_only",],};}
return __exports;});;

/* /html_builder/static/src/core/field_change_replication_plugin.js */
odoo.define('@html_builder/core/field_change_replication_plugin',['@html_editor/plugin','@html_editor/utils/dom_traversal','@html_editor/utils/resource'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{closestElement}=require("@html_editor/utils/dom_traversal");const{withSequence}=require("@html_editor/utils/resource");const FieldChangeReplicationPlugin=__exports.FieldChangeReplicationPlugin=class FieldChangeReplicationPlugin extends Plugin{static id="fieldChangeReplication";static dependencies=["dom"];resources={handleNewRecords:this.handleMutations.bind(this),normalize_handlers:withSequence(9000,this.normalizeHandler.bind(this)),};setup(){this.fieldsToReplicate=new Set();}
handleMutations(records){records.filter((r)=>!(r.type==="attributes"&&r.attributeName.startsWith("data-oe-t"))).map((r)=>closestElement(r.target,"[data-oe-model], [data-oe-translation-source-sha]")).filter(Boolean).filter((fieldEl)=>!fieldEl.classList.contains("o_translation_without_style")).forEach((fieldEl)=>this.fieldsToReplicate.add(fieldEl));}
normalizeHandler(commonAncestor,stepState){const fields=this.fieldsToReplicate;this.fieldsToReplicate=new Set();if(stepState!=="original"){return;}
const touchedEls=new Set();for(const sourceEl of fields){const same=(attribute,quote='"')=>`[${attribute}=${quote}${sourceEl.getAttribute(attribute)}${quote}]`;let selector="";if(sourceEl.getAttribute("data-oe-model")){selector+=same("data-oe-model")+same("data-oe-id")+same("data-oe-field");}
if(sourceEl.getAttribute("data-oe-translation-source-sha")){selector+=same("data-oe-translation-source-sha");}
if(sourceEl.getAttribute("data-oe-type")){selector+=same("data-oe-type");}
if(sourceEl.getAttribute("data-oe-expression")){selector+=same("data-oe-expression");}else if(sourceEl.getAttribute("data-oe-xpath")){selector+=same("data-oe-xpath");}
if(sourceEl.getAttribute("data-oe-contact-options")){selector+=same("data-oe-contact-options","'");}
if(sourceEl.getAttribute("data-oe-type")==="many2one"){selector+=",[data-oe-model]"+
same("data-oe-type")+
same("data-oe-many2one-model")+
same("data-oe-many2one-id");selector+=",[data-oe-model][data-oe-field=name]"+`[data-oe-model="${sourceEl.getAttribute("data-oe-many2one-model")}"]`+`[data-oe-id="${sourceEl.getAttribute("data-oe-many2one-id")}"]`;}
if(sourceEl.getAttribute("data-oe-field")==="name"){selector+=",[data-oe-model][data-oe-type=many2one]"+`[data-oe-many2one-model="${sourceEl.getAttribute("data-oe-model")}"]`+`[data-oe-many2one-id="${sourceEl.getAttribute("data-oe-id")}"]`;}
const targetEls=[...this.editable.querySelectorAll(selector)].filter((targetEl)=>targetEl!==sourceEl);if(targetEls.length){const cloneEl=sourceEl.cloneNode(true);cloneEl.toggleAttribute("contenteditable",sourceEl.isContentEditable);this.dependencies.dom.removeSystemProperties(cloneEl);this.dispatchTo("clean_for_save_handlers",{root:cloneEl});for(const targetEl of targetEls){if(targetEl.classList.contains("o_translation_without_style")){if(targetEl.innerText!==cloneEl.innerText){targetEl.innerText=cloneEl.innerText;touchedEls.add(targetEl);}}else{if(targetEl.innerHTML!==cloneEl.innerHTML){targetEl.replaceChildren(...cloneEl.cloneNode(true).childNodes);touchedEls.add(targetEl);}}
this.dispatchTo("after_replication_handlers",{sourceEl,targetEl});}}}
for(const touchedEl of touchedEls){this.dispatchTo("normalize_handlers",touchedEl);}}}
return __exports;});;

/* /html_builder/static/src/core/grid_layout/grid_layout_plugin.js */
odoo.define('@html_builder/core/grid_layout/grid_layout_plugin',['@html_editor/plugin','@html_editor/utils/resource','@web/core/l10n/translation','@web/core/utils/numbers','@html_builder/utils/grid_layout_utils','@html_editor/utils/dom_info'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{clamp}=require("@web/core/utils/numbers");const{addBackgroundGrid,additionalRowLimit,checkIfImageColumn,cleanUpGrid,convertColumnToGrid,convertToNormalColumn,getGridItemProperties,getGridProperties,resizeGrid,setElementToMaxZindex,toggleGridMode,}=require("@html_builder/utils/grid_layout_utils");const{isElement}=require("@html_editor/utils/dom_info");const gridItemSelector=".row.o_grid_mode > div.o_grid_item";function isGridItem(el){return el.matches(gridItemSelector);}
const GridLayoutPlugin=__exports.GridLayoutPlugin=class GridLayoutPlugin extends Plugin{static id="gridLayout";static dependencies=["selection","builderOptions"];resources={get_overlay_buttons:withSequence(0,{getButtons:this.getActiveOverlayButtons.bind(this),}),on_cloned_handlers:this.onCloned.bind(this),on_removed_handlers:this.onRemoved.bind(this),on_snippet_dragged_handlers:this.onSnippetDragged.bind(this),on_snippet_over_dropzone_handlers:this.onSnippetOverDropzone.bind(this),on_snippet_move_handlers:this.onSnippetMove.bind(this),on_snippet_out_dropzone_handlers:this.onSnippetOutDropzone.bind(this),on_snippet_dropped_over_handlers:this.onSnippetDroppedOver.bind(this),on_snippet_dropped_near_handlers:this.onSnippetDroppedNear.bind(this),on_snippet_dropped_handlers:withSequence(1000,this.onSnippetDropped.bind(this)),is_draggable_handlers:this.isDraggable.bind(this),on_element_dragged_handlers:this.onElementDragged.bind(this),on_element_over_dropzone_handlers:this.onDropzoneOver.bind(this),on_element_move_handlers:this.onDragMove.bind(this),on_element_out_dropzone_handlers:this.onDropzoneOut.bind(this),on_element_dropped_over_handlers:this.onElementDroppedOver.bind(this),on_element_dropped_near_handlers:this.onElementDroppedNear.bind(this),on_element_dropped_handlers:this.onElementDropped.bind(this),savable_mutation_record_predicates:this.ignoreBackgroundGrid.bind(this),};setup(){this.overlayTarget=null;this.isRtl=this.config.isEditableRTL;this.iframe=this.document.defaultView.frameElement;}
hasGridLayoutOption(containerEl){const{targetEl}=this.dependencies.builderOptions.findOption(containerEl,"LayoutOption",true);return!!targetEl&&targetEl===containerEl;}
ignoreBackgroundGrid(record){if(record.type==="childList"){const addedOrRemovedNode=(record.addedTrees[0]||record.removedTrees[0]).node;if(isElement(addedOrRemovedNode)&&addedOrRemovedNode.matches(".o_we_background_grid")){return false;}}
return true;}
getActiveOverlayButtons(target){if(!isGridItem(target)){this.overlayTarget=null;return[];}
const buttons=[];this.overlayTarget=target;if(!this.config.isMobileView(this.overlayTarget)){buttons.push({class:"o_send_back oi",title:_t("Send to back"),handler:this.sendGridItemToBack.bind(this),},{class:"o_bring_front oi",title:_t("Bring to front"),handler:this.bringGridItemToFront.bind(this),});}
return buttons;}
onCloned({cloneEl}){if(isGridItem(cloneEl)){let{rowStart,rowEnd,columnStart,columnEnd}=getGridItemProperties(cloneEl);const columnSpan=columnEnd-columnStart;columnStart=columnEnd===13?1:columnStart+1;columnEnd=columnStart+columnSpan;const newGridArea=`${rowStart + 1} / ${columnStart} / ${rowEnd + 1} / ${columnEnd}`;cloneEl.style.gridArea=newGridArea;const rowEl=cloneEl.parentElement;setElementToMaxZindex(cloneEl,rowEl);resizeGrid(rowEl);}}
onRemoved({nextTargetEl}){if(nextTargetEl.classList.contains("o_grid_item")){resizeGrid(nextTargetEl.parentElement);}}
sendGridItemToBack(){const rowEl=this.overlayTarget.parentNode;const columnEls=[...rowEl.children].filter((el)=>el!==this.overlayTarget);const minZindex=Math.min(...columnEls.map((el)=>el.style.zIndex));if(minZindex>0){this.overlayTarget.style.zIndex=minZindex-1;}else{columnEls.forEach((columnEl)=>columnEl.style.zIndex++);this.overlayTarget.style.zIndex=0;}}
bringGridItemToFront(){const rowEl=this.overlayTarget.parentNode;setElementToMaxZindex(this.overlayTarget,rowEl);}
adjustGridItem(el,shouldResizeGrid=true){const gridItemEl=el.closest(".o_grid_item");if(gridItemEl&&gridItemEl!==el&&!this.config.isMobileView(gridItemEl)){const rowEl=gridItemEl.parentElement;const{rowGap,rowSize}=getGridProperties(rowEl);const{rowStart,rowEnd}=getGridItemProperties(gridItemEl);const oldRowSpan=rowEnd-rowStart;const{borderTop,borderBottom,paddingTop,paddingBottom}=window.getComputedStyle(gridItemEl);const borderY=parseFloat(borderTop)+parseFloat(borderBottom);const paddingY=parseFloat(paddingTop)+parseFloat(paddingBottom);const height=gridItemEl.scrollHeight+borderY+paddingY;const rowSpan=Math.ceil((height+rowGap)/(rowSize+rowGap));gridItemEl.style.gridRowEnd=rowStart+rowSpan;gridItemEl.classList.remove(`g-height-${oldRowSpan}`);gridItemEl.classList.add(`g-height-${rowSpan}`);if(shouldResizeGrid){resizeGrid(rowEl);}
return()=>{gridItemEl.style.gridRowEnd=rowEnd;gridItemEl.classList.remove(`g-height-${rowSpan}`);gridItemEl.classList.add(`g-height-${oldRowSpan}`);if(shouldResizeGrid){resizeGrid(rowEl);}};}
return()=>{};}
getOverlappingGridDropzone(dropzoneEl){const closestGridEl=dropzoneEl.closest(".o_grid_mode");const gridDropzoneEl=closestGridEl&&closestGridEl.querySelector(".oe_grid_zone");return gridDropzoneEl;}
wrapInGridItem(el,dropzoneEl,dragState){const columnEl=document.createElement("div");const columnSpan=dragState.snippet.gridColumnSpan||6;columnEl.classList.add("o_grid_item",`col-lg-${columnSpan}`,`g-col-lg-${columnSpan}`,"g-height-1");columnEl.style.gridArea=`1 / 1 / 2 / ${columnSpan + 1}`;dropzoneEl.after(columnEl);columnEl.append(el);dragState.draggedEl=columnEl;const{paddingToRemove,marginToRemove,marginToAdd}=dragState;el.classList.remove(...paddingToRemove,...marginToRemove);el.classList.add(...marginToAdd);this.adjustGridItem(el,false);const{rowStart,rowEnd}=getGridItemProperties(columnEl);dragState.columnSpan=columnSpan;dragState.rowSpan=rowEnd-rowStart;return columnEl;}
onSnippetDragged({snippetEl,dragState}){const paddingRegex=/^((pt|pb)\d{1,3}$)/;const marginRegex=/^((mt|my)-\d$)/;const paddingClasses=[...snippetEl.classList].filter((c)=>paddingRegex.test(c));const marginClasses=[...snippetEl.classList].filter((c)=>marginRegex.test(c));Object.assign(dragState,{paddingToRemove:paddingClasses,marginToRemove:marginClasses,});snippetEl.classList.remove(...paddingClasses,...marginClasses);this.document.body.appendChild(snippetEl);const{marginTop}=getComputedStyle(snippetEl);dragState.marginToAdd=parseInt(marginTop)?["mt-0"]:[];snippetEl.remove();snippetEl.classList.add(...paddingClasses,...paddingClasses);}
onSnippetOverDropzone({snippetEl,dragState}){const dropzoneEl=dragState.currentDropzoneEl;if(!dropzoneEl.classList.contains("oe_grid_zone")){const gridDropzoneEl=this.getOverlappingGridDropzone(dropzoneEl);if(gridDropzoneEl){gridDropzoneEl.classList.add("invisible");}}else{const columnEl=this.wrapInGridItem(snippetEl,dropzoneEl,dragState);const iframeRect=this.iframe.getBoundingClientRect();dragState.mousePositionYOnElement=0;dragState.mousePositionXOnElement=(iframeRect.x+columnEl.scrollWidth/2)*(this.isRtl?-1:1);}
this.onDropzoneOver({draggedEl:dragState.draggedEl,dragState});}
onSnippetOutDropzone({snippetEl,dragState}){const dropzoneEl=dragState.currentDropzoneEl;this.onDropzoneOut({draggedEl:dragState.draggedEl,dragState});if(!dropzoneEl.classList.contains("oe_grid_zone")){const gridDropzoneEl=this.getOverlappingGridDropzone(dropzoneEl);if(gridDropzoneEl){gridDropzoneEl.classList.remove("invisible");}}else{dropzoneEl.after(snippetEl);dragState.draggedEl.remove();dragState.draggedEl=snippetEl;const{paddingToRemove,marginToRemove,marginToAdd}=dragState;snippetEl.classList.add(...paddingToRemove,...marginToRemove);snippetEl.classList.remove(...marginToAdd);}}
onSnippetMove({dragState,x,y}){if(!dragState.overGrid){return;}
this.onDragMove({draggedEl:dragState.draggedEl,dragState,x,y});}
onSnippetDroppedOver({droppedEl,dragState}){const dropzoneEl=dragState.currentDropzoneEl;if(!dropzoneEl.classList.contains("oe_grid_zone")){return;}
this.onElementDroppedOver({droppedEl,dragState});}
onSnippetDroppedNear({droppedEl,dropzoneEl,dragState}){if(!dropzoneEl.classList.contains("oe_grid_zone")){return;}
this.wrapInGridItem(droppedEl,dropzoneEl,dragState);this.onElementDroppedNear({droppedEl:dragState.draggedEl,dropzoneEl,dragState});}
onSnippetDropped({snippetEl,dragState}){if("restoreGridItem"in dragState){dragState.restoreGridItem();this.adjustGridItem(snippetEl);}}
isDraggable(targetEl){const isColumn=targetEl.parentElement?.classList.contains("row");if(isColumn&&this.config.isMobileView(targetEl)){return false;}
return true;}
onElementDragged({draggedEl,dragState}){const parentEl=draggedEl.parentElement;const isColumn=parentEl.classList.contains("row");if(isColumn){const rowEl=parentEl;const containerEl=rowEl.parentElement;const columnEl=draggedEl;const hasGridOption=this.hasGridLayoutOption(containerEl);const isRowInGridMode=rowEl.classList.contains("o_grid_mode");const allowGridMode=hasGridOption||isRowInGridMode;if(allowGridMode){if(!isRowInGridMode){const preserveSelection=this.dependencies.selection.preserveSelection;toggleGridMode(containerEl,preserveSelection,this.config.mobileBreakpoint);}
const gridItemProps=getGridItemProperties(columnEl);const{columnStart,columnEnd,rowStart,rowEnd}=gridItemProps;dragState.columnSpan=columnEnd-columnStart;dragState.rowSpan=rowEnd-rowStart;const{gridArea,zIndex}=gridItemProps;dragState.startGridArea=gridArea;dragState.startZindex=zIndex;dragState.startGridEl=rowEl;}else{const style=window.getComputedStyle(columnEl);const{borderLeft,borderRight,borderTop,borderBottom}=style;const borderX=parseFloat(borderLeft)+parseFloat(borderRight);const borderY=parseFloat(borderTop)+parseFloat(borderBottom);const isImageColumn=checkIfImageColumn(columnEl);const sizedEl=isImageColumn?columnEl.querySelector("img"):columnEl;dragState.columnWidth=sizedEl.scrollWidth+borderX;dragState.columnHeight=sizedEl.scrollHeight+borderY;}}}
onDropzoneOver({draggedEl,dragState}){const dropzoneEl=dragState.currentDropzoneEl;if(!dropzoneEl.classList.contains("oe_grid_zone")){dragState.restoreGridItem=this.adjustGridItem(draggedEl);return;}
const rowEl=dropzoneEl.parentElement;const columnEl=draggedEl;if(!columnEl.classList.contains("o_grid_item")){const{columnWidth,columnHeight}=dragState;const spans=convertColumnToGrid(rowEl,columnEl,columnWidth,columnHeight,this.config.mobileBreakpoint);dragState.columnSpan=spans.columnSpan;dragState.rowSpan=spans.rowSpan;}
const{columnSpan,rowSpan}=dragState;const dragHelperEl=document.createElement("div");dragHelperEl.classList.add("o_we_drag_helper");dragHelperEl.style.gridArea=`1 / 1 / ${1 + rowSpan} / ${1 + columnSpan}`;rowEl.append(dragHelperEl);const backgroundGridEl=addBackgroundGrid(rowEl,rowSpan);const rowCount=Math.max(rowEl.dataset.rowCount,rowSpan);dropzoneEl.style.gridRowEnd=rowCount+1;const{startGridEl,startZindex}=dragState;if(rowEl===startGridEl){columnEl.style.zIndex=startZindex;}else{setElementToMaxZindex(columnEl,rowEl);}
setElementToMaxZindex(backgroundGridEl,rowEl);setElementToMaxZindex(dragHelperEl,rowEl);const{rowGap,rowSize,columnGap,columnSize}=getGridProperties(rowEl);const columnHeight=rowSpan*(rowSize+rowGap)-rowGap;const columnWidth=columnSpan*(columnSize+columnGap)-columnGap;Object.assign(columnEl.style,{height:`${columnHeight}px`,width:`${columnWidth}px`,position:"absolute",gridArea:"",});rowEl.style.position="relative";Object.assign(dragState,{startHeight:rowEl.clientHeight,currentHeight:rowEl.clientHeight,dragHelperEl,backgroundGridEl,overGrid:true,});}
onDropzoneOut({draggedEl,dragState}){const dropzoneEl=dragState.currentDropzoneEl;if(!dropzoneEl.classList.contains("oe_grid_zone")){if("restoreGridItem"in dragState){dragState.restoreGridItem();delete dragState.restoreGridItem;}
return;}
dragState.overGrid=false;const columnEl=draggedEl;const rowEl=dropzoneEl.parentElement;const{dragHelperEl,backgroundGridEl}=dragState;cleanUpGrid(rowEl,columnEl,dragHelperEl,backgroundGridEl);columnEl.style.removeProperty("z-index");resizeGrid(rowEl);const rowCount=parseInt(rowEl.dataset.rowCount);dropzoneEl.style.gridRowEnd=Math.max(rowCount+1,1);}
onElementDroppedOver({droppedEl,dragState}){const dropzoneEl=dragState.currentDropzoneEl;const columnEl=droppedEl;if(dropzoneEl.classList.contains("oe_grid_zone")){dragState.overGrid=false;const rowEl=dropzoneEl.parentElement;const{dragHelperEl,backgroundGridEl}=dragState;columnEl.style.gridArea=dragHelperEl.style.gridArea;cleanUpGrid(rowEl,columnEl,dragHelperEl,backgroundGridEl);resizeGrid(rowEl);}else if(columnEl.classList.contains("o_grid_item")){convertToNormalColumn(columnEl,this.config.mobileBreakpoint);}}
onElementDroppedNear({droppedEl,dropzoneEl,dragState}){const columnEl=droppedEl;if(dropzoneEl.classList.contains("oe_grid_zone")){const rowEl=dropzoneEl.parentElement;if(!columnEl.classList.contains("o_grid_item")){const{columnWidth,columnHeight}=dragState;const spans=convertColumnToGrid(rowEl,columnEl,columnWidth,columnHeight,this.config.mobileBreakpoint);dragState.columnSpan=spans.columnSpan;dragState.rowSpan=spans.rowSpan;}
const{columnSpan,rowSpan}=dragState;columnEl.style.gridArea=`1 / 1 / ${1 + rowSpan} / ${1 + columnSpan}`;const{startGridEl,startZindex}=dragState;if(rowEl===startGridEl){columnEl.style.zIndex=startZindex;}else{setElementToMaxZindex(columnEl,rowEl);}
resizeGrid(rowEl);}else if(columnEl.classList.contains("o_grid_item")){convertToNormalColumn(columnEl,this.config.mobileBreakpoint);}}
onDragMove({draggedEl,dragState,x,y}){if(!dragState.overGrid){return;}
const columnEl=draggedEl;const columnHeight=parseFloat(columnEl.style.height);const columnWidth=parseFloat(columnEl.style.width);const rowEl=columnEl.parentElement;const rowRect=rowEl.getBoundingClientRect();const rowTop=rowRect.top;const rowLeft=rowRect.left;const rowRight=rowRect.right;const{mousePositionYOnElement,mousePositionXOnElement}=dragState;let top=y-rowTop-mousePositionYOnElement;let left;if(this.isRtl){left=rowRight-x-mousePositionXOnElement-columnWidth;}else{left=x-rowLeft-mousePositionXOnElement;}
top=top<0?0:top;left=clamp(left,0,rowEl.clientWidth-columnWidth);const bottom=top+columnHeight;columnEl.style.top=`${top}px`;if(this.isRtl){columnEl.style.right=`${left}px`;}else{columnEl.style.left=`${left}px`;}
const{rowGap,rowSize,columnGap,columnSize}=getGridProperties(rowEl);const{columnSpan,rowSpan,dragHelperEl}=dragState;const rowStart=Math.round(top/(rowSize+rowGap))+1;const columnStart=Math.round(left/(columnSize+columnGap))+1;const rowEnd=rowStart+rowSpan;const columnEnd=columnStart+columnSpan;dragHelperEl.style.gridArea=`${rowStart} / ${columnStart} / ${rowEnd} / ${columnEnd}`;const dropzoneEl=dragState.currentDropzoneEl;const{startHeight,currentHeight,backgroundGridEl}=dragState;const rowOverflow=Math.round((bottom-currentHeight)/(rowSize+rowGap));const shouldUpdateRows=bottom>currentHeight||(bottom<=currentHeight&&bottom>startHeight);const rowCount=Math.max(rowEl.dataset.rowCount,rowSpan);const maxRowEnd=rowCount+additionalRowLimit+1;if(Math.abs(rowOverflow)>=1&&shouldUpdateRows){if(rowEnd<=maxRowEnd){const newGridEnd=parseInt(dropzoneEl.style.gridRowEnd)+rowOverflow;dropzoneEl.style.gridRowEnd=newGridEnd;backgroundGridEl.style.gridRowEnd=newGridEnd;dragState.currentHeight+=rowOverflow*(rowSize+rowGap);}else{dropzoneEl.style.gridRowEnd=maxRowEnd;backgroundGridEl.style.gridRowEnd=maxRowEnd;dragState.currentHeight=(maxRowEnd-1)*(rowSize+rowGap)-rowGap;}}}
onElementDropped({droppedEl,dragState}){const{startGridEl}=dragState;if(startGridEl){resizeGrid(startGridEl);}
if("restoreGridItem"in dragState){dragState.restoreGridItem();}
this.adjustGridItem(droppedEl);if(droppedEl.classList.contains("o_grid_item")){dragState.hasSamePositionAsStart=()=>{const parentEl=droppedEl.parentElement;const gridArea=droppedEl.style.gridArea;const{startGridEl,startGridArea}=dragState;return parentEl===startGridEl&&gridArea===startGridArea;};}}}
return __exports;});;

/* /html_builder/static/src/core/icon_plugin.js */
odoo.define('@html_builder/core/icon_plugin',['@html_editor/main/media/icon_plugin','@html_editor/main/toolbar/toolbar_plugin'],function(require){'use strict';let __exports={};const{IconPlugin:EditorIconPlugin}=require("@html_editor/main/media/icon_plugin");const{DISABLED_NAMESPACE}=require("@html_editor/main/toolbar/toolbar_plugin");const IconPlugin=__exports.IconPlugin=class IconPlugin extends EditorIconPlugin{toolbarNamespace=DISABLED_NAMESPACE;}
return __exports;});;

/* /html_builder/static/src/core/image_plugin.js */
odoo.define('@html_builder/core/image_plugin',['@html_editor/main/media/image_plugin','@html_editor/main/toolbar/toolbar_plugin'],function(require){'use strict';let __exports={};const{ImagePlugin:EditorImagePlugin}=require("@html_editor/main/media/image_plugin");const{DISABLED_NAMESPACE}=require("@html_editor/main/toolbar/toolbar_plugin");const ImagePlugin=__exports.ImagePlugin=class ImagePlugin extends EditorImagePlugin{toolbarNamespace=DISABLED_NAMESPACE;}
return __exports;});;

/* /html_builder/static/src/core/img.js */
odoo.define('@html_builder/core/img',['@odoo/owl','@web/core/utils/cache'],function(require){'use strict';let __exports={};const{Component,onWillStart,onWillUpdateProps,useEffect,useRef,useState,xml,}=require("@odoo/owl");const{Cache}=require("@web/core/utils/cache");const svgCache=new Cache(async(src)=>{let text;try{const response=await window.fetch(src);text=await response.text();}catch{text="<svg></svg>";}
const parser=new window.DOMParser();const xmlDoc=parser.parseFromString(text,"text/xml");return xmlDoc.getElementsByTagName("svg")[0];},JSON.stringify);const Img=__exports.Img=class Img extends Component{static props={src:String,class:{type:String,optional:true},style:{type:String,optional:true},alt:{type:String,optional:true},attrs:{type:Object,optional:true},svgCheck:{type:Boolean,optional:true},};static defaultProps={svgCheck:true,};static template=xml`
        <t t-if="state.loaded">
            <svg t-if="isSvg(props.src)" t-ref="svg"
                xmlns="http://www.w3.org/2000/svg"
                t-att-width="svg.width"
                t-att-viewBox="svg.viewBox"
                t-att-fill="svg.fill"
                class="hb-svg d-flex m-auto"
                t-att-class="props.class"
                t-att-style="props.style"
                t-att="props.attrs"/>
            <img t-else=""
                t-att-src="props.src"
                t-att-class="props.class"
                t-att-style="props.style"
                t-att-alt="props.alt"
                t-att="props.attrs"/>
        </t>
        `;setup(){this.svgRef=useRef("svg");this.svg={};this.state=useState({loaded:false});onWillStart(async()=>this.handleImgLoad(this.props.src));onWillUpdateProps(async(nextProps)=>{if(this.props.src!==nextProps.src){await this.handleImgLoad(nextProps.src);}});useEffect((imgLoaded)=>{if(imgLoaded&&this.isSvg(this.props.src)&&this.svg.children.length){const children=[];for(const child of this.svg.children){children.push(child.cloneNode(true));}
this.svgRef.el.replaceChildren(...children);}},()=>[this.state.loaded]);}
async handleImgLoad(src){const prom=this.isSvg(src)?this.getSvg():this.loadImage(src);if(this.isSvg(src)){prom.then((svg)=>{this.svg=svg;});}
if(this.env.imgGroup){this.env.imgGroup.addImgProm(prom);this.env.imgGroup.loaded.then(()=>{this.state.loaded=true;});}else{await prom;this.state.loaded=true;}}
loadImage(){return new Promise((resolve,reject)=>{const img=new Image();img.onload=()=>resolve({status:"loaded"});img.onerror=()=>resolve({status:"error"});img.src=this.props.src;});}
isSvg(src){return this.props.svgCheck&&src.split(".").pop()==="svg";}
async getSvg(){const svgEl=(await svgCache.read(this.props.src)).cloneNode(true);return{viewBox:svgEl.getAttribute("viewBox"),width:svgEl.getAttribute("width")||"",fill:svgEl.getAttribute("fill")||"",children:svgEl.children,};}}
return __exports;});;

/* /html_builder/static/src/core/img_group.js */
odoo.define('@html_builder/core/img_group',['@odoo/owl','@web/core/utils/timing'],function(require){'use strict';let __exports={};const{Component,useSubEnv,xml}=require("@odoo/owl");const{batched}=require("@web/core/utils/timing");const ImgGroup=__exports.ImgGroup=class ImgGroup extends Component{static template=xml`<t><t t-slot="default"/></t>`;static props={slots:Object,};setup(){this.load=()=>{};this.imgProms=[];this.loadImgs=batched(this._loadImgs.bind(this));useSubEnv({imgGroup:{loaded:new Promise((resolve)=>{this.load=resolve;}),addImgProm:(promise)=>{this.imgProms.push(promise);this.loadImgs();},},});}
async _loadImgs(){await Promise.all(this.imgProms);this.load();}}
return __exports;});;

/* /html_builder/static/src/core/media_website_plugin.js */
odoo.define('@html_builder/core/media_website_plugin',['@html_editor/plugin','@html_editor/utils/dom_info','@html_editor/utils/dom_traversal','@html_builder/utils/utils_css','@web/core/l10n/translation','@web/core/tooltip/tooltip'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{MEDIA_SELECTOR,isProtected}=require("@html_editor/utils/dom_info");const{closestElement}=require("@html_editor/utils/dom_traversal");const{shouldEditableMediaBeEditable}=require("@html_builder/utils/utils_css");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{Tooltip}=require("@web/core/tooltip/tooltip");const MediaWebsitePlugin=__exports.MediaWebsitePlugin=class MediaWebsitePlugin extends Plugin{static id="media_website";static dependencies=["media","selection","builderOptions","operation"];static shared=["replaceMedia"];resources={on_replaced_media_handlers:({newMediaEl})=>this.dependencies.builderOptions.setNextTarget(newMediaEl),on_snippet_dropped_handlers:this.onSnippetDropped.bind(this),};setup(){const basicMediaSelector=`${MEDIA_SELECTOR}, img`;this.addDomListener(this.editable,"dblclick",async(ev)=>{const targetEl=ev.target.closest(basicMediaSelector);if(!targetEl){return;}
if(this.isReplaceableMedia(targetEl)){await this.onDblClickEditableMedia(targetEl);}});this.popover=this.services.popover;this.removeCurrentTooltip=()=>{};this.addDomListener(this.editable,"click",(ev)=>{const targetEl=ev.target.closest(basicMediaSelector);if(!targetEl){return;}
if(this.isReplaceableMedia(targetEl)){this.openImageTooltip(targetEl);}});}
destroy(){super.destroy();this.removeCurrentTooltip();}
isReplaceableMedia(targetEl){let isEditable=targetEl.parentElement?.isContentEditable;if(!isEditable&&targetEl.classList.contains("o_editable_media")){isEditable=shouldEditableMediaBeEditable(targetEl);}
if(isEditable&&!isProtected(this.dependencies.selection.getEditableSelection().anchorNode)){return true;}
return false;}
async onDblClickEditableMedia(mediaEl){this.dependencies.operation.next(async()=>{this.removeCurrentTooltip();await this.replaceMedia(mediaEl);});}
async replaceMedia(mediaEl){const sel=this.dependencies.selection.getEditableSelection();const editableEl=closestElement(mediaEl||sel.startContainer,".o_editable")||this.editable;await this.dependencies.media.openMediaDialog({node:mediaEl},editableEl);}
openImageTooltip(mediaEl){this.removeCurrentTooltip();this.removeCurrentTooltip=this.popover.add(mediaEl,Tooltip,{tooltip:_t("Double-click to edit"),});setTimeout(this.removeCurrentTooltip,1500);}
async onSnippetDropped({snippetEl,dragState}){if(!snippetEl.matches(".media_iframe_video")){return;}
let isVideoSelected=false;await new Promise((resolve)=>{const onClose=this.dependencies.media.openMediaDialog({activeTab:"VIDEOS",save:async(selectedVideoEl)=>{isVideoSelected=true;snippetEl.insertAdjacentElement("afterend",selectedVideoEl);snippetEl.remove();dragState.replacedSnippetEl=selectedVideoEl;},});onClose.then(()=>{resolve();});});return!isVideoSelected;}}
return __exports;});;

/* /html_builder/static/src/core/move_plugin.js */
odoo.define('@html_builder/core/move_plugin',['@html_editor/plugin','@html_editor/utils/resource','@web/core/l10n/translation','@html_builder/utils/column_layout_utils','@html_builder/utils/utils','@html_builder/utils/scrolling','@web/core/l10n/localization'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{addMobileOrders,fillRemovedItemGap,removeMobileOrders,}=require("@html_builder/utils/column_layout_utils");const{isElementInViewport}=require("@html_builder/utils/utils");const{scrollTo}=require("@html_builder/utils/scrolling");const{localization}=require("@web/core/l10n/localization");const MovePlugin=__exports.MovePlugin=class MovePlugin extends Plugin{static id="move";static dependencies=["visibility"];resources={has_overlay_options:{hasOption:(el)=>this.isMovable(el)},get_overlay_buttons:withSequence(0,{getButtons:this.getActiveOverlayButtons.bind(this),}),on_cloned_handlers:this.onCloned.bind(this),on_will_remove_handlers:this.onWillRemove.bind(this),on_element_dropped_handlers:this.onElementDropped.bind(this),is_movable_selector:[{selector:"section, .s_showcase .row .row:not(.s_col_no_resize) > div",direction:"vertical",},{selector:".row:not(.s_col_no_resize) > div",exclude:".s_showcase .row .row > div",direction:"horizontal",},],};setup(){this.overlayTarget=null;this.noScroll=false;this.isEditableRTL=this.config.isEditableRTL;this.isBackendRTL=localization.direction==="rtl";const verticalSelector=[];const verticalExclude=[];const horizontalSelector=[];const horizontalExclude=[];const noScrollSelector=[];for(const movableSelector of this.getResource("is_movable_selector")){const{selector,exclude,direction,noScroll}=movableSelector;if(selector){const selectors=direction==="vertical"?verticalSelector:horizontalSelector;selectors.push(selector);}
if(exclude){const excludes=direction==="vertical"?verticalExclude:horizontalExclude;excludes.push(exclude);}
if(noScroll){noScrollSelector.push(selector);}}
this.verticalMove={selector:verticalSelector.join(", "),exclude:verticalExclude.length>0?verticalExclude.join(", "):false,};this.horizontalMove={selector:horizontalSelector.join(", "),exclude:horizontalExclude.length>0?horizontalExclude.join(", "):false,};this.noScrollSelector=noScrollSelector.length>0?noScrollSelector.join(", "):false;const rowEls=this.editable.querySelectorAll(".row");for(const rowEl of rowEls){const columnEls=[...rowEl.children];const orderedColumnEls=columnEls.filter((el)=>el.style.order);if(orderedColumnEls.length&&orderedColumnEls.length!==columnEls.length){removeMobileOrders(orderedColumnEls,this.config.mobileBreakpoint);}}}
isMovable(el){return((el.matches(this.verticalMove.selector)&&!el.matches(this.verticalMove.exclude))||(el.matches(this.horizontalMove.selector)&&!el.matches(this.horizontalMove.exclude)));}
isFullWidthColumn(el){const rowEl=el.parentElement;if(!rowEl||!rowEl.classList.contains("row")){return false;}
const rowRect=rowEl.getBoundingClientRect();const columnRect=el.getBoundingClientRect();const{marginLeft,marginRight}=getComputedStyle(el);const totalWidth=columnRect.width+parseFloat(marginLeft)+parseFloat(marginRight);return totalWidth>=rowRect.width-1;}
getActiveOverlayButtons(target){if(!this.isMovable(target)){this.overlayTarget=null;return[];}
const buttons=[];this.overlayTarget=target;this.noScroll=this.overlayTarget.matches(this.noScrollSelector);const reverseButtons=this.isEditableRTL!==this.isBackendRTL;if(!this.areArrowsHidden()){const isVertical=(this.overlayTarget.matches(this.verticalMove.selector)&&!this.overlayTarget.matches(this.verticalMove.exclude))||this.isFullWidthColumn(this.overlayTarget);const previousSiblingEl=this.dependencies.visibility.getVisibleSibling(this.overlayTarget,"prev");const nextSiblingEl=this.dependencies.visibility.getVisibleSibling(this.overlayTarget,"next");if(previousSiblingEl){const direction=isVertical?"up":reverseButtons?"right":"left";const button={class:`fa fa-fw fa-angle-${direction}`,title:isVertical?_t("Move up"):this.isEditableRTL?_t("Move right"):_t("Move left"),handler:this.onMoveClick.bind(this,"prev"),};buttons.push(button);}
if(nextSiblingEl){const direction=isVertical?"down":reverseButtons?"left":"right";const button={class:`fa fa-fw fa-angle-${direction}`,title:isVertical?_t("Move down"):this.isEditableRTL?_t("Move left"):_t("Move right"),handler:this.onMoveClick.bind(this,"next"),};buttons.push(button);}
if(reverseButtons&&!isVertical){buttons.reverse();}}
return buttons;}
onCloned({cloneEl,originalEl}){if(!this.isMovable(originalEl)){return;}
const hasMobileOrder=!!originalEl.style.order;if(hasMobileOrder){const siblingEls=[...originalEl.parentNode.children];const maxOrder=Math.max(...siblingEls.map((el)=>el.style.order));cloneEl.style.order=maxOrder+1;}}
onWillRemove(toRemoveEl){if(!this.isMovable(toRemoveEl)){return;}
const mobileOrder=toRemoveEl.style.order;if(mobileOrder){fillRemovedItemGap(toRemoveEl.parentElement,parseInt(mobileOrder));}}
onElementDropped({droppedEl,dragState}){if(!this.isMovable(droppedEl)){return;}
const parentEl=droppedEl.parentElement;const mobileOrder=droppedEl.style.order;const{startParentEl}=dragState;if(mobileOrder&&parentEl!==startParentEl){fillRemovedItemGap(startParentEl,parseInt(mobileOrder));}
removeMobileOrders(parentEl.children,this.config.mobileBreakpoint);}
areArrowsHidden(){const isMobile=this.config.isMobileView(this.overlayTarget);const isGridItem=this.overlayTarget.classList.contains("o_grid_item");const siblingsEl=[...this.overlayTarget.parentNode.children];const visibleSiblingEl=siblingsEl.find((el)=>el!==this.overlayTarget&&window.getComputedStyle(el).display!=="none");return!visibleSiblingEl||(isGridItem&&!isMobile);}
onMoveClick(direction){const isMobile=this.config.isMobileView(this.overlayTarget);let hasMobileOrder=!!this.overlayTarget.style.order;const parentEl=this.overlayTarget.parentNode;const siblingEls=parentEl.children;const isColumn=parentEl.classList.contains("row");if(isMobile&&isColumn&&!hasMobileOrder){addMobileOrders(siblingEls,this.config.mobileBreakpoint);hasMobileOrder=true;}else if(!isMobile&&hasMobileOrder){removeMobileOrders(siblingEls,this.config.mobileBreakpoint);hasMobileOrder=false;}
const siblingEl=this.dependencies.visibility.getVisibleSibling(this.overlayTarget,direction);if(hasMobileOrder){const currentOrder=this.overlayTarget.style.order;this.overlayTarget.style.order=siblingEl.style.order;siblingEl.style.order=currentOrder;}else{siblingEl.insertAdjacentElement(direction==="prev"?"beforebegin":"afterend",this.overlayTarget);}
if(!this.noScroll&&!isElementInViewport(this.overlayTarget)){const{top,height}=this.overlayTarget.getBoundingClientRect();const viewportHeight=this.document.defaultView.innerHeight;const heightDiff=viewportHeight-height;const isBottomHidden=heightDiff<top;scrollTo(this.overlayTarget,{extraOffset:50,forcedOffset:isBottomHidden?heightDiff-50:undefined,duration:500,});}}}
return __exports;});;

/* /html_builder/static/src/core/operation.js */
odoo.define('@html_builder/core/operation',['@web/core/utils/concurrency'],function(require){'use strict';let __exports={};const{Mutex}=require("@web/core/utils/concurrency");const OperationMutex=__exports.OperationMutex=class OperationMutex extends Mutex{constructor(){super();this._skipUntilEmpty=false;}
clearQueue(){this._skipUntilEmpty=this._queueSize>0;if(this._skipUntilEmpty){this.getUnlockedDef().then(()=>{this._skipUntilEmpty=false;});}}
async exec(action){return super.exec(()=>{if(this._skipUntilEmpty){return;}
return action();});}}
const Operation=__exports.Operation=class Operation{constructor(editableDocument=document){this.mutex=new OperationMutex();this.editableDocument=editableDocument;}
next(fn,{load=()=>Promise.resolve(),cancellable,cancelPrevious,cancelTime=50,withLoadingEffect=true,loadingEffectDelay=500,shouldInterceptClick=false,canTimeout=true,timeout=10000,}={}){this.cancelPrevious?.();let isCancel=false;let cancelResolve;this.cancelPrevious=cancellable&&(()=>{this.cancelPrevious=null;isCancel=true;cancelResolve?.();this.mutex.exec(async()=>{await cancelPrevious?.();});});const cancelTimePromise=new Promise((resolve)=>setTimeout(resolve,cancelTime));const cancelLoadPromise=new Promise((resolve)=>{cancelResolve=resolve;});let hasTimedOut=false;return this.mutex.exec(async()=>{if(isCancel){return;}
let cancelTimeoutPromise;if(canTimeout){cancelTimeoutPromise=new Promise((resolve)=>{setTimeout(()=>{hasTimedOut=true;resolve();},timeout);});}
const removeLoadingElement=this.addLoadingElement(withLoadingEffect,loadingEffectDelay,shouldInterceptClick);const applyOperation=async()=>{const loadResult=await load();if(isCancel){return;}
this.previousLoadResolve=null;if(!this.editableDocument.defaultView){return;}
await fn?.(loadResult);};try{const promises=[Promise.all([cancelLoadPromise,cancelTimePromise]),applyOperation(),];if(cancelTimeoutPromise){promises.push(cancelTimeoutPromise);}
await Promise.race(promises);}finally{if(hasTimedOut){this.mutex.clearQueue();}
removeLoadingElement();}
return{hasFailed:hasTimedOut};});}
addLoadingElement(withLoadingEffect,loadingEffectDelay,shouldInterceptClick){const loadingScreenEl=document.createElement("div");loadingScreenEl.classList.add(...["o_loading_screen","d-flex","justify-content-center","align-items-center"]);const spinnerEl=document.createElement("img");spinnerEl.setAttribute("src","/web/static/img/spin.svg");loadingScreenEl.appendChild(spinnerEl);let removeClickListener=()=>{};if(shouldInterceptClick){const onClick=(ev)=>{const trueTargetEls=this.editableDocument.elementsFromPoint(ev.clientX,ev.clientY);this.next(()=>{for(const trueTargetEl of trueTargetEls){if(trueTargetEl.isConnected){trueTargetEl.click();break;}}});};this.editableDocument.addEventListener("click",onClick);removeClickListener=()=>this.editableDocument.removeEventListener("click",onClick);}
this.editableDocument.body.appendChild(loadingScreenEl);let loadingTimeout;if(withLoadingEffect){loadingTimeout=setTimeout(()=>loadingScreenEl.classList.add("o_we_ui_loading"),loadingEffectDelay);}
return()=>{if(loadingTimeout){clearTimeout(loadingTimeout);}
removeClickListener();loadingScreenEl.remove();};}}
return __exports;});;

/* /html_builder/static/src/core/operation_plugin.js */
odoo.define('@html_builder/core/operation_plugin',['@html_editor/plugin','@odoo/owl','@web/core/l10n/translation','@html_builder/core/operation'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{useComponent}=require("@odoo/owl");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{Operation}=require("@html_builder/core/operation");const OperationPlugin=__exports.OperationPlugin=class OperationPlugin extends Plugin{static id="operation";static dependencies=["history"];static shared=["next","hasTimedOut"];setup(){this._hasTimedOut=false;this.operation=new Operation(this.document);this.addDomListener(this.editable,"keydown",()=>this.next());this.addDomListener(this.editable,"beforeinput",()=>this.next());}
async next(fn,params={canTimeout:false}){let rollback;const result=await this.operation.next(()=>{if(params.canTimeout){rollback=this.dependencies.history.makeSavePoint();}
if(fn){return fn();}},params);if(result&&result.hasFailed&&rollback){this._hasTimedOut=true;this.onTimeout(rollback);}
return result;}
onTimeout(rollback){rollback();this.services.notification.add(_t("A technical issue occurred in the builder, you should save or discard your changes."),{type:"danger",sticky:true,});}
hasTimedOut(){return this._hasTimedOut;}}
__exports.useOperation=useOperation;function useOperation(){const comp=useComponent();return(apply,...args)=>{comp.env.editor.shared.operation.next(async(...args)=>{await apply(...args);comp.env.editor.shared.history.addStep();},...args);};}
return __exports;});;

/* /html_builder/static/src/core/overlay_buttons/overlay_buttons.js */
odoo.define('@html_builder/core/overlay_buttons/overlay_buttons',['@odoo/owl'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const OverlayButtons=__exports.OverlayButtons=class OverlayButtons extends Component{static template="html_builder.OverlayButtons";static props={state:{type:Object},};setup(){this.state=this.props.state;}}
return __exports;});;

/* /html_builder/static/src/core/overlay_buttons/overlay_buttons_plugin.js */
odoo.define('@html_builder/core/overlay_buttons/overlay_buttons_plugin',['@html_editor/plugin','@odoo/owl','@web/core/utils/timing','@web/core/utils/scrolling','@html_builder/core/builder_options_plugin','@html_builder/core/overlay_buttons/overlay_buttons','@html_editor/utils/resource'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{reactive}=require("@odoo/owl");const{throttleForAnimation}=require("@web/core/utils/timing");const{getScrollingElement,getScrollingTarget}=require("@web/core/utils/scrolling");const{checkElement}=require("@html_builder/core/builder_options_plugin");const{OverlayButtons}=require("@html_builder/core/overlay_buttons/overlay_buttons");const{withSequence}=require("@html_editor/utils/resource");const OverlayButtonsPlugin=__exports.OverlayButtonsPlugin=class OverlayButtonsPlugin extends Plugin{static id="overlayButtons";static dependencies=["selection","overlay","history","operation"];static shared=["hideOverlayButtons","showOverlayButtons","hideOverlayButtonsUi","showOverlayButtonsUi",];resources={step_added_handlers:this.refreshButtons.bind(this),change_current_options_containers_listeners:this.addOverlayButtons.bind(this),on_mobile_preview_clicked:withSequence(20,this.refreshButtons.bind(this)),};setup(){this.iframe=this.editable.ownerDocument.defaultView.frameElement;this.overlay=this.dependencies.overlay.createOverlay(OverlayButtons,{positionOptions:{position:"top-middle",onPositioned:(overlayEl,position)=>{const iframeRect=this.iframe.getBoundingClientRect();if(this.target&&position.top<iframeRect.top){const targetRect=this.target.getBoundingClientRect();const newTop=iframeRect.top+targetRect.bottom+15;position.top=newTop;overlayEl.style.top=`${newTop}px`;}
return;},margin:15,flip:false,},closeOnPointerdown:false,},{sequence:49});this.target=null;this.state=reactive({isVisible:true,showUi:true,buttons:[],});this.resizeObserver=new ResizeObserver(()=>{this.overlay.updatePosition();});this.refresh=throttleForAnimation(this.refreshButtons.bind(this));this.addDomListener(window,"resize",this.refresh);const onMouseMoveOrDown=throttleForAnimation(()=>{this.showOverlayButtons();this.editable.removeEventListener("mousemove",onMouseMoveOrDown);this.editable.removeEventListener("mousedown",onMouseMoveOrDown);});this.addDomListener(this.editable,"keydown",()=>{this.hideOverlayButtons();this.editable.addEventListener("mousemove",onMouseMoveOrDown);this.editable.addEventListener("mousedown",onMouseMoveOrDown);});const scrollingElement=getScrollingElement(this.document);const scrollingTarget=getScrollingTarget(scrollingElement);this.addDomListener(scrollingTarget,"scroll",throttleForAnimation(()=>{this.hideOverlayButtons();clearTimeout(this.scrollingTimeout);this.scrollingTimeout=setTimeout(()=>{this.showOverlayButtons();},250);}),{capture:true});this._cleanups.push(()=>{this.removeOverlayButtons();this.resizeObserver.disconnect();});}
refreshButtons(){if(!this.target){return;}
const buttons=[];for(const{getButtons,editableOnly}of this.getResource("get_overlay_buttons")){if(checkElement(this.target,{editableOnly})){buttons.push(...getButtons(this.target));}}
for(const button of buttons){const handler=button.handler;button.handler=(...args)=>{this.dependencies.operation.next(async()=>{await handler(...args);this.dependencies.history.addStep();});};}
this.state.buttons=buttons;this.overlay.updatePosition();}
hideOverlayButtons(){this.state.isVisible=false;}
hideOverlayButtonsUi(){this.state.showUi=false;}
showOverlayButtons(){this.state.isVisible=true;}
showOverlayButtonsUi(){this.state.showUi=true;}
addOverlayButtons(optionsContainer){this.removeOverlayButtons();const optionWithOverlayButtons=optionsContainer.findLast((option)=>option.hasOverlayOptions);if(optionWithOverlayButtons){this.target=optionWithOverlayButtons.element;this.state.isVisible=true;this.refreshButtons();this.overlay.open({target:optionWithOverlayButtons.element,closeOnPointerdown:false,props:{state:this.state,},});this.resizeObserver.observe(this.target,{box:"border-box"});}}
removeOverlayButtons(){if(this.target){this.resizeObserver.unobserve(this.target);this.target=null;}
this.overlay.close();}}
return __exports;});;

/* /html_builder/static/src/core/remove_plugin.js */
odoo.define('@html_builder/core/remove_plugin',['@html_editor/plugin','@html_editor/utils/resource','@web/core/l10n/translation','@html_editor/core/delete_plugin','@html_editor/others/qweb_plugin','@html_builder/utils/utils','@html_editor/utils/dom_traversal'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{unremovableNodePredicates:deletePluginPredicates}=require("@html_editor/core/delete_plugin");const{isUnremovableQWebElement:qwebPluginPredicate}=require("@html_editor/others/qweb_plugin");const{isEditable}=require("@html_builder/utils/utils");const{closestElement}=require("@html_editor/utils/dom_traversal");const unremovableNodePredicates=[(node)=>!isEditable(node.parentNode),...deletePluginPredicates,qwebPluginPredicate,(node)=>node.parentNode.matches('[data-oe-type="image"]'),];__exports.isRemovable=isRemovable;function isRemovable(el){return!unremovableNodePredicates.some((p)=>p(el));}
const RemovePlugin=__exports.RemovePlugin=class RemovePlugin extends Plugin{static id="remove";static dependencies=["builderOptions","visibility"];resources={get_overlay_buttons:withSequence(3,{getButtons:this.getActiveOverlayButtons.bind(this),}),empty_node_predicates:(el)=>{const systemNodeSelectors=this.getResource("system_node_selectors").join(",");return(el.textContent.trim()===""&&(!systemNodeSelectors||[...el.children].every((child)=>closestElement(child,systemNodeSelectors))));},};static shared=["removeElement"];setup(){this.overlayTarget=null;const unremovableSelectors=[];for(const unremovableSelector of this.getResource("is_unremovable_selector")){unremovableSelectors.push(unremovableSelector);}
if(unremovableSelectors.length){unremovableNodePredicates.push((node)=>node.matches(unremovableSelectors.join(", ")));}}
getActiveOverlayButtons(target){if(!isRemovable(target)){this.overlayTarget=null;return[];}
const buttons=[];this.overlayTarget=target;const disabledReason=this.dependencies.builderOptions.getRemoveDisabledReason(target);buttons.push({class:"oe_snippet_remove bg-danger fa fa-trash",title:_t("Remove"),disabledReason,handler:()=>{this.removeElement(this.overlayTarget);},});return buttons;}
isEmptyAndRemovable(el,optionsTargetEls){return(this.getResource("empty_node_predicates").some((predicate)=>predicate(el))&&!el.classList.contains("oe_structure")&&!el.parentElement.classList.contains("carousel-item")&&(!optionsTargetEls.includes(el)||optionsTargetEls.some((targetEl)=>targetEl.contains(el)))&&isRemovable(el));}
removeElement(toRemoveEl,updateContainers=true){const optionTargetEls=this.getOptionsContainersElements().filter((targetEl)=>targetEl.contains(toRemoveEl));const nextTargetEl=this.removeCurrentTarget(toRemoveEl,optionTargetEls);this.dispatchTo("on_removed_handlers",{removedEl:toRemoveEl,nextTargetEl});if(updateContainers){this.dependencies.builderOptions.setNextTarget(nextTargetEl);}}
removeCurrentTarget(toRemoveEl,optionsTargetEls){this.dispatchTo("on_will_remove_handlers",toRemoveEl);let parentEl=toRemoveEl.parentElement;const previousSiblingEl=this.dependencies.visibility.getVisibleSibling(toRemoveEl,"prev");const nextSiblingEl=this.dependencies.visibility.getVisibleSibling(toRemoveEl,"next");if(parentEl.matches(".o_editable:not(body)")){parentEl=parentEl.closest("body");}
[toRemoveEl,...toRemoveEl.querySelectorAll("*")].forEach((el)=>{const tooltip=Tooltip.getInstance(el);if(tooltip){tooltip.dispose();}});toRemoveEl.remove();if(parentEl){const firstChildEl=parentEl.firstChild;if(firstChildEl&&!firstChildEl.tagName&&firstChildEl.textContent===" "){parentEl.removeChild(firstChildEl);}}
let nextTargetEl=previousSiblingEl||nextSiblingEl;if(!nextTargetEl){while(!optionsTargetEls.includes(parentEl)){const nextParentEl=parentEl.parentElement;if(!nextParentEl){break;}
if(this.isEmptyAndRemovable(parentEl,optionsTargetEls)){parentEl.remove();}
parentEl=nextParentEl;}
nextTargetEl=parentEl;optionsTargetEls=optionsTargetEls.filter((targetEl)=>targetEl.contains(nextTargetEl));if(this.isEmptyAndRemovable(parentEl,optionsTargetEls)){nextTargetEl=this.removeCurrentTarget(parentEl,optionsTargetEls);}}
return nextTargetEl;}
getOptionsContainersElements(){return this.dependencies.builderOptions.getContainers().map((option)=>option.element);}}
return __exports;});;

/* /html_builder/static/src/core/save_plugin.js */
odoo.define('@html_builder/core/save_plugin',['@html_builder/utils/escaping','@html_editor/plugin','@html_editor/utils/resource','@web/core/utils/arrays','@web/core/utils/functions'],function(require){'use strict';let __exports={};const{escapeTextNodes}=require("@html_builder/utils/escaping");const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{groupBy}=require("@web/core/utils/arrays");const{uniqueId}=require("@web/core/utils/functions");const SavePlugin=__exports.SavePlugin=class SavePlugin extends Plugin{static id="savePlugin";static shared=["save","saveView","ignoreDirty","groupElements"];static dependencies=["history"];resources={handleNewRecords:this.handleMutations.bind(this),start_edition_handlers:this.startObserving.bind(this),savable_selectors:["#wrapwrap .oe_structure[data-oe-xpath][data-oe-id]","#wrapwrap [data-oe-field]:not([data-oe-sanitize-prevent-edition])","#wrapwrap .s_cover[data-res-model]",],clean_for_save_handlers:[],save_element_handlers:[this.saveView.bind(this)],get_dirty_els:()=>this.editable.querySelectorAll(".o_dirty"),on_prepare_drag_handlers:withSequence(0,this.ignoreDirty.bind(this)),};setup(){this.canObserve=false;this.savableSelector=this.getResource("savable_selectors").join(", ");}
groupElements(toGroupEls){return groupBy(toGroupEls,(toGroupEl)=>{const model=toGroupEl.dataset.oeModel;const recordId=toGroupEl.dataset.oeId;const field=toGroupEl.dataset.oeField;if(!model){return uniqueId("special-element-to-save-");}
return`${model}::${recordId}::${field}`;});}
async save({shouldSkipAfterSaveHandlers=async()=>true}={}){let skipAfterSaveHandlers;try{await Promise.all(this.getResource("before_save_handlers").map((handler)=>handler()));await this._save();skipAfterSaveHandlers=await shouldSkipAfterSaveHandlers();}finally{if(!skipAfterSaveHandlers){this.getResource("after_save_handlers").forEach((handler)=>handler());}}}
async _save(){const dirtyEls=[];for(const getDirtyEls of this.getResource("get_dirty_els")){dirtyEls.push(...getDirtyEls());}
const groupedElements=this.groupElements(dirtyEls);const preSaveHandlers=[];for(const preSaveHandler of this.getResource("pre_save_handlers")){preSaveHandlers.push(preSaveHandler(groupedElements));}
await Promise.all(preSaveHandlers);const saveProms=Object.values(groupedElements).map(async(dirtyEls)=>{const cleanedEls=dirtyEls.map((dirtyEl)=>{dirtyEl.classList.remove("o_dirty");const cleanedEl=dirtyEl.cloneNode(true);this.dispatchTo("clean_for_save_handlers",{root:cleanedEl});return cleanedEl;});for(const saveElementsOverride of this.getResource("save_elements_overrides")){if(await saveElementsOverride(cleanedEls)){return;}}
for(const cleanedEl of cleanedEls){for(const saveElementHandler of this.getResource("save_element_handlers")){await saveElementHandler(cleanedEl);}}});const willSaves=this.getResource("save_handlers").map((c)=>c());await Promise.all(saveProms.concat(willSaves));this.dependencies.history.reset();}
saveView(el,delayTranslations=true){const viewID=Number(el.dataset["oeId"]);if(!viewID){return;}
let context={};if(this.services.website){const delay=delayTranslations?{delay_translations:true}:{};context={website_id:this.services.website.currentWebsite.id,lang:this.services.website.currentWebsite.metadata.lang,...delay,};}
escapeTextNodes(el);return this.services.orm.call("ir.ui.view","save",[viewID,el.outerHTML,(!el.dataset["oeExpression"]&&el.dataset["oeXpath"])||null],{context});}
startObserving(){this.canObserve=true;}
handleMutations(records,currentOperation){if(!this.canObserve){return;}
if(currentOperation==="undo"||currentOperation==="redo"){return;}
for(const record of records){if(record.attributeName==="contenteditable"){continue;}
let targetEl=record.target;if(!targetEl.isConnected){continue;}
if(targetEl.nodeType!==Node.ELEMENT_NODE){targetEl=targetEl.parentElement;}
if(!targetEl){continue;}
const savableEl=targetEl.closest(this.savableSelector);if(!savableEl||savableEl.classList.contains("o_dirty")||savableEl.hasAttribute("data-oe-readonly")){continue;}
savableEl.classList.add("o_dirty");}}
ignoreDirty(){this.canObserve=false;return()=>{this.canObserve=true;};}}
return __exports;});;

/* /html_builder/static/src/core/save_snippet_plugin.js */
odoo.define('@html_builder/core/save_snippet_plugin',['@html_builder/utils/escaping','@html_editor/plugin','@html_editor/utils/resource','@odoo/owl','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{escapeTextNodes}=require("@html_builder/utils/escaping");const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{markup}=require("@odoo/owl");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const savableSelector="[data-snippet], a.btn";const savableExclude=".o_no_save, .s_donation_donate_btn, .s_website_form_send, .js_subscribe_btn";function isSavable(el){return el.matches(savableSelector)&&!el.matches(savableExclude);}
const SaveSnippetPlugin=__exports.SaveSnippetPlugin=class SaveSnippetPlugin extends Plugin{static id="saveSnippet";resources={get_options_container_top_buttons:withSequence(1,this.getOptionsContainerTopButtons.bind(this)),};getOptionsContainerTopButtons(el){if(!isSavable(el)){return[];}
return[{class:"fa fa-fw fa-save oe_snippet_save o_we_hover_warning btn o-hb-btn btn-global-color-hover",title:_t("Save this block to use it elsewhere"),handler:this.saveSnippet.bind(this),},];}
async wrapWithBeforeAfterSaveHandlers(snippetEl,callback){await Promise.all(this.getResource("before_save_handlers").map((handler)=>handler(snippetEl)));let node;try{node=callback();}finally{this.getResource("after_save_handlers").forEach((handler)=>handler(snippetEl));}
return node;}
async saveSnippet(el){const cleanForSaveHandlers=[...this.getResource("clean_for_save_handlers"),({root})=>escapeTextNodes(root),];const savedName=await this.config.saveSnippet(el,cleanForSaveHandlers,this.wrapWithBeforeAfterSaveHandlers.bind(this));if(savedName){const message=_t("Saved as %s. Find it in your snippets.",markup`<strong>${savedName}</strong>`);this.services.notification.add(message,{type:"success",autocloseDelay:5000,});}}}
return __exports;});;

/* /html_builder/static/src/core/select_number_column.js */
odoo.define('@html_builder/core/select_number_column',['@html_builder/core/utils','@html_builder/utils/column_layout_utils'],function(require){'use strict';let __exports={};const{BaseOptionComponent,useDomState}=require("@html_builder/core/utils");const{areColsCustomized}=require("@html_builder/utils/column_layout_utils");const SelectNumberColumn=__exports.SelectNumberColumn=class SelectNumberColumn extends BaseOptionComponent{static template="html_builder.SelectNumberColumn";setup(){super.setup();this.state=useDomState((editingElement)=>{const columnEls=editingElement.querySelector(":scope > .row")?.children;return{isCustomColumn:columnEls&&areColsCustomized(columnEls,this.env.editor.config.isMobileView(editingElement),this.env.editor.config.mobileBreakpoint),canHaveZeroColumns:editingElement.matches(".s_allow_columns"),};});}}
return __exports;});;

/* /html_builder/static/src/core/setup_editor_plugin.js */
odoo.define('@html_builder/core/setup_editor_plugin',['@html_editor/plugin','@html_editor/utils/resource','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const SetupEditorPlugin=__exports.SetupEditorPlugin=class SetupEditorPlugin extends Plugin{static id="setup_editor_plugin";static shared=["getEditableAreas"];resources={clean_for_save_handlers:this.cleanForSave.bind(this),closest_savable_providers:withSequence(10,(el)=>el.closest(".o_editable")),unremovable_node_predicates:(node)=>node.classList?.contains("o_editable"),on_removed_handlers:this.cleanupEmptyStructures.bind(this),};setup(){const welcomeMessageEl=this.editable.querySelector("#wrap .o_homepage_editor_welcome_message");welcomeMessageEl?.remove();this.dispatchTo("before_setup_editor_handlers");let editableEls=this.getEditableElements(this.getResource("o_editable_selectors").join(", ")).filter((el)=>!el.matches("link, script")).filter((el)=>!el.hasAttribute("data-oe-readonly")).filter((el)=>!el.matches('img[data-oe-field="arch"], br[data-oe-field="arch"], input[data-oe-field="arch"]')).filter((el)=>!el.classList.contains("oe_snippet_editor")).filter((el)=>!el.matches("hr, br, input, textarea")).filter((el)=>!el.hasAttribute("data-oe-sanitize-prevent-edition"));editableEls.concat(Array.from(this.editable.querySelectorAll(".o_editable")));editableEls.forEach((el)=>el.classList.add("o_editable"));if(this.delegateTo("after_setup_editor_handlers")){return;}
editableEls=this.getEditableElements('.oe_structure.oe_empty, [data-oe-type="html"]');editableEls.forEach((el)=>{if(!el.hasAttribute("data-editor-message")){el.setAttribute("data-editor-message-default",true);el.setAttribute("data-editor-message",_t("DRAG BUILDING BLOCKS HERE"));}});}
getEditableElements(selector){const editableEls=[...this.editable.querySelectorAll(selector)].filter((el)=>!el.matches(".o_not_editable")).filter((el)=>{const parent=el.closest(".o_editable, .o_not_editable");return!parent||parent.matches(".o_editable");});return editableEls;}
cleanForSave({root}){root.classList.remove("o_editable");root.querySelectorAll(".o_editable").forEach((el)=>{el.classList.remove("o_editable");});}
getEditableAreas(rootEl){const editableEl=rootEl||this.editable;const editablesAreaEls=[...editableEl.querySelectorAll(".o_editable")];if(editableEl.matches(".o_editable")){editablesAreaEls.unshift(editableEl);}
return editablesAreaEls;}
cleanupEmptyStructures(){if(!this.editable){return;}
const emptyStructureEls=this.editable.querySelectorAll(".oe_empty");for(const emptyEl of emptyStructureEls){if(emptyEl.children.length===0){emptyEl.replaceChildren();}}}}
return __exports;});;

/* /html_builder/static/src/core/utils.js */
odoo.define('@html_builder/core/utils',['@html_editor/utils/dom_info','@odoo/owl','@web/core/utils/hooks','@web/core/utils/reactive','@web/core/utils/timing','@html_builder/core/builder_action'],function(require){'use strict';let __exports={};const{isElement,isTextNode}=require("@html_editor/utils/dom_info");const{Component,onMounted,onWillDestroy,onWillStart,onWillUpdateProps,reactive,status,toRaw,useComponent,useEffect,useEnv,useRef,useState,useSubEnv,}=require("@odoo/owl");const{useBus}=require("@web/core/utils/hooks");const{effect}=require("@web/core/utils/reactive");const{useDebounced}=require("@web/core/utils/timing");const{BuilderAction}=require("@html_builder/core/builder_action");function isConnectedElement(el){return el&&el.isConnected&&!!el.ownerDocument.defaultView;}
__exports.useDomState=useDomState;function useDomState(getState,{checkEditingElement=true}={}){const component=useComponent();const env=useEnv();const isValid=(el)=>(!el&&!checkEditingElement)||isConnectedElement(el);const handler=async(ev)=>{const editingElement=env.getEditingElement();if(isValid(editingElement)){try{const newStatePromise=getState(editingElement);if(ev){ev.detail.getStatePromises.push(newStatePromise);const newState=await newStatePromise;const shouldApply=await ev.detail.updatePromise;if(shouldApply){Object.assign(state,newState);}}else{Object.assign(state,await newStatePromise);}}catch(e){if(!isValid(editingElement)||status(component)==="destroyed"){return;}
throw e;}}};const state=useState({});onWillStart(handler);useBus(env.editorBus,"DOM_UPDATED",handler);return state;}
__exports.useActionInfo=useActionInfo;function useActionInfo(){const comp=useComponent();const getParam=(paramName)=>{let param=comp.props[paramName];param=param===undefined?comp.env.weContext[paramName]:param;if(typeof param==="object"){param=JSON.stringify(param);}
return param;};const actionParam=getParam("actionParam");return{actionId:comp.props.action||comp.env.weContext.action,actionParam,actionValue:comp.props.actionValue,classAction:getParam("classAction"),styleAction:getParam("styleAction"),styleActionValue:comp.props.styleActionValue,attributeAction:getParam("attributeAction"),attributeActionValue:comp.props.attributeActionValue,};}
function querySelectorAll(targets,selector){const elements=new Set();for(const target of targets){for(const el of target.querySelectorAll(selector)){elements.add(el);}}
return[...elements];}
__exports.useBuilderComponent=useBuilderComponent;function useBuilderComponent(){const comp=useComponent();const newEnv={};const oldEnv=useEnv();let editingElements;let applyTo=comp.props.applyTo;const updateEditingElements=()=>{editingElements=applyTo?querySelectorAll(oldEnv.getEditingElements(),applyTo):oldEnv.getEditingElements();};updateEditingElements();oldEnv.editorBus.addEventListener("UPDATE_EDITING_ELEMENT",updateEditingElements);onWillUpdateProps(async(nextProps)=>{if(comp.props.applyTo!==nextProps.applyTo){applyTo=nextProps.applyTo;oldEnv.editorBus.trigger("UPDATE_EDITING_ELEMENT");await oldEnv.triggerDomUpdated();}});onWillDestroy(()=>{oldEnv.editorBus.removeEventListener("UPDATE_EDITING_ELEMENT",updateEditingElements);});newEnv.getEditingElements=()=>editingElements;newEnv.getEditingElement=()=>editingElements[0];const weContext={};for(const key in basicContainerBuilderComponentProps){if(key in comp.props){weContext[key]=comp.props[key];}}
if(Object.keys(weContext).length){newEnv.weContext={...comp.env.weContext,...weContext};}
useSubEnv(newEnv);}
__exports.useDependencyDefinition=useDependencyDefinition;function useDependencyDefinition(id,item,{onReady}={}){const comp=useComponent();const ignore=comp.env.ignoreBuilderItem;if(onReady){onReady.then(()=>{comp.env.dependencyManager.add(id,item,ignore);});}else{comp.env.dependencyManager.add(id,item,ignore);}
onWillDestroy(()=>{comp.env.dependencyManager.removeByValue(item);});}
__exports.useDependencies=useDependencies;function useDependencies(dependencies){const env=useEnv();const isDependenciesVisible=()=>{const deps=Array.isArray(dependencies)?dependencies:[dependencies];return deps.filter(Boolean).every((dependencyId)=>{const match=dependencyId.match(/(!)?(.*)/);const inverse=!!match[1];const id=match[2];const isActiveFn=env.dependencyManager.get(id)?.isActive;if(!isActiveFn){return false;}
const isActive=isActiveFn();return inverse?!isActive:isActive;});};return isDependenciesVisible;}
function useIsActiveItem(){const env=useEnv();const listenedKeys=new Set();function isActive(itemId){const isActiveFn=env.dependencyManager.get(itemId)?.isActive;if(!isActiveFn){return false;}
return isActiveFn();}
const getState=()=>{const newState={};for(const itemId of listenedKeys){newState[itemId]=isActive(itemId);}
return newState;};const state=useDomState(getState);const listener=()=>{const newState=getState();Object.assign(state,newState);};env.dependencyManager.addEventListener("dependency-updated",listener);onWillDestroy(()=>{env.dependencyManager.removeEventListener("dependency-updated",listener);});return function isActiveItem(itemId){listenedKeys.add(itemId);if(state[itemId]===undefined){return isActive(itemId);}
return state[itemId];};}
__exports.useGetItemValue=useGetItemValue;function useGetItemValue(){const env=useEnv();const listenedKeys=new Set();function getValue(itemId){const getValueFn=env.dependencyManager.get(itemId)?.getValue;if(!getValueFn){return null;}
return getValueFn();}
const getState=()=>{const newState={};for(const itemId of listenedKeys){newState[itemId]=getValue(itemId);}
return newState;};const state=useDomState(getState);const listener=()=>{const newState=getState();Object.assign(state,newState);};env.dependencyManager.addEventListener("dependency-updated",listener);onWillDestroy(()=>{env.dependencyManager.removeEventListener("dependency-updated",listener);});return function getItemValue(itemId){listenedKeys.add(itemId);if(!(itemId in state)){return getValue(itemId);}
return state[itemId];};}
__exports.useSelectableComponent=useSelectableComponent;function useSelectableComponent(id,{onItemChange}={}){useBuilderComponent();const selectableItems=[];const refreshCurrentItemDebounced=useDebounced(refreshCurrentItem,0,{immediate:true});const env=useEnv();const state=reactive({currentSelectedItem:null,});function refreshCurrentItem(){if(env.editor.isDestroyed||env.editor.shared.history.getIsPreviewing()){return;}
let currentItem;let itemPriority=0;for(const selectableItem of selectableItems){if(selectableItem.isApplied()&&selectableItem.priority>=itemPriority){currentItem=selectableItem;itemPriority=selectableItem.priority;}}
if(currentItem&&currentItem!==toRaw(state.currentSelectedItem)){state.currentSelectedItem=currentItem;env.dependencyManager.triggerDependencyUpdated();}
if(currentItem){onItemChange?.(currentItem);}}
if(id){useDependencyDefinition(id,{type:"select",getSelectableItems:()=>selectableItems.slice(0),});}
onMounted(refreshCurrentItem);useBus(env.editorBus,"DOM_UPDATED",refreshCurrentItem);function cleanSelectedItem(...args){if(state.currentSelectedItem){return state.currentSelectedItem.clean(...args);}}
useSubEnv({selectableContext:{cleanSelectedItem,addSelectableItem:(item)=>{selectableItems.push(item);},removeSelectableItem:(item)=>{const index=selectableItems.indexOf(item);if(index!==-1){selectableItems.splice(index,1);}},update:refreshCurrentItemDebounced,items:selectableItems,refreshCurrentItem:()=>refreshCurrentItem(),getSelectableState:()=>state,},});}
__exports.useSelectableItemComponent=useSelectableItemComponent;function useSelectableItemComponent(id,{getLabel=()=>{}}={}){const{operation,isApplied,getActions,priority,clean,onReady}=useClickableBuilderComponent();const env=useEnv();let isSelectableActive=isApplied;let state;if(env.selectableContext){const selectableState=env.selectableContext.getSelectableState();isSelectableActive=()=>{env.selectableContext.refreshCurrentItem();return(toRaw(selectableState.currentSelectedItem)===selectableItem||(id&&selectableState.currentSelectedItem?.id===id));};const selectableItem={isApplied,priority,getLabel,clean,getActions,id,};env.selectableContext.addSelectableItem(selectableItem);state=useState({isActive:false,});effect(({currentSelectedItem})=>{state.isActive=toRaw(currentSelectedItem)===selectableItem||(id&&currentSelectedItem?.id===id);},[selectableState]);env.selectableContext.refreshCurrentItem();onMounted(env.selectableContext.update);onWillDestroy(()=>{env.selectableContext.removeSelectableItem(selectableItem);});}else{state=useDomState(async()=>{await onReady;return{isActive:isSelectableActive(),};});}
if(id){useDependencyDefinition(id,{isActive:isSelectableActive,getActions,cleanSelectedItem:env.selectableContext?.cleanSelectedItem,},{onReady});}
return{state,operation};}
function usePrepareAction(getAllActions){const env=useEnv();const getAction=env.editor.shared.builderActions.getAction;const asyncActions=[];for(const descr of getAllActions()){if(descr.actionId){const action=getAction(descr.actionId);if(action.has("prepare")){asyncActions.push({action,descr});}}}
let onReady;if(asyncActions.length){let resolve;onReady=new Promise((r)=>{resolve=r;});onWillStart(async function(){await Promise.all(asyncActions.map((obj)=>obj.action.prepare(obj.descr)));resolve();});onWillUpdateProps(async({actionParam,actionValue})=>{onReady=new Promise((r)=>{resolve=r;});await Promise.all(asyncActions.map((obj)=>obj.action.prepare({...obj.descr,actionParam:convertParamToObject(actionParam),actionValue,})));resolve();});}
return onReady;}
function useReloadAction(getAllActions){const env=useEnv();const getAction=env.editor.shared.builderActions.getAction;let reload=false;for(const descr of getAllActions()){if(descr.actionId){const action=getAction(descr.actionId);if(action.reload){reload=action.reload;}}}
return{reload};}
__exports.useHasPreview=useHasPreview;function useHasPreview(getAllActions){const comp=useComponent();const getAction=comp.env.editor.shared.builderActions.getAction;let hasPreview=true;for(const descr of getAllActions()){if(descr.actionId){const action=getAction(descr.actionId);if(action.preview===false){hasPreview=false;}}}
return(hasPreview&&(comp.props.preview===true||(comp.props.preview===undefined&&comp.env.weContext.preview!==false)));}
function useWithLoadingEffect(getAllActions){const env=useEnv();const getAction=env.editor.shared.builderActions.getAction;let withLoadingEffect=true;for(const descr of getAllActions()){if(descr.actionId){const action=getAction(descr.actionId);if(action.withLoadingEffect===false){withLoadingEffect=false;}}}
return withLoadingEffect;}
function useCanTimeout(getAllActions){const env=useEnv();const getAction=env.editor.shared.builderActions.getAction;let canTimeout=true;for(const descr of getAllActions()){if(descr.actionId){const action=getAction(descr.actionId);if(action.canTimeout===false){canTimeout=false;}}}
return canTimeout;}
__exports.revertPreview=revertPreview;function revertPreview(editor){if(editor.isDestroyed){return;}
return editor.shared.operation.next();}
__exports.useClickableBuilderComponent=useClickableBuilderComponent;function useClickableBuilderComponent(){useBuilderComponent();const comp=useComponent();const{getAllActions,callOperation,isApplied}=getAllActionsAndOperations(comp);const getAction=comp.env.editor.shared.builderActions.getAction;const onReady=usePrepareAction(getAllActions);const{reload}=useReloadAction(getAllActions);const applyOperation=comp.env.editor.shared.history.makePreviewableAsyncOperation(callApply);const inheritedActionIds=comp.props.inheritedActions||comp.env.weContext.inheritedActions||[];const hasPreview=useHasPreview(getAllActions);const operationWithReload=useOperationWithReload(callApply,reload);const withLoadingEffect=useWithLoadingEffect(getAllActions);const canTimeout=useCanTimeout(getAllActions);let preventNextPreview=false;const operation={commit:()=>{preventNextPreview=false;if(reload){callOperation(operationWithReload,{operationParams:{withLoadingEffect:withLoadingEffect,canTimeout:canTimeout,},});}else{callOperation(applyOperation.commit,{operationParams:{withLoadingEffect:withLoadingEffect,canTimeout:canTimeout,},});}},preview:()=>{if(preventNextPreview){return;}
preventNextPreview=true;callOperation(applyOperation.preview,{preview:true,operationParams:{cancellable:true,cancelPrevious:()=>applyOperation.revert(),canTimeout:canTimeout,},});},revert:()=>{preventNextPreview=false;revertPreview(comp.env.editor);},};if(!hasPreview){operation.preview=()=>{};}
function clean(nextApplySpecs,isPreviewing){const proms=[];for(const{actionId,actionParam,actionValue}of getAllActions()){for(const editingElement of comp.env.getEditingElements()){let nextAction;proms.push(getAction(actionId).clean?.({isPreviewing,editingElement,params:actionParam,value:actionValue,dependencyManager:comp.env.dependencyManager,selectableContext:comp.env.selectableContext,get nextAction(){nextAction=nextAction||nextApplySpecs.find((a)=>a.actionId===actionId)||{};return{params:nextAction.actionParam,value:nextAction.actionValue,};},}));}}
return Promise.all(proms);}
async function callApply(applySpecs,isPreviewing){await comp.env.selectableContext?.cleanSelectedItem(applySpecs,isPreviewing);const cleans=inheritedActionIds.map((actionId)=>comp.env.dependencyManager.get(actionId).cleanSelectedItem).filter(Boolean);const cleanPromises=[];for(const clean of new Set(cleans)){cleanPromises.push(clean(applySpecs,isPreviewing));}
await Promise.all(cleanPromises);const cleanOrApplyProms=[];const isAlreadyApplied=isApplied();for(const applySpec of applySpecs){const hasClean=!!applySpec.clean;const shouldClean=_shouldClean(comp,hasClean,isAlreadyApplied);if(shouldClean){cleanOrApplyProms.push(applySpec.action.clean({isPreviewing,editingElement:applySpec.editingElement,params:applySpec.actionParam,value:applySpec.actionValue,loadResult:applySpec.loadOnClean?applySpec.loadResult:null,dependencyManager:comp.env.dependencyManager,selectableContext:comp.env.selectableContext,}));}else{cleanOrApplyProms.push(applySpec.action.apply({isPreviewing,editingElement:applySpec.editingElement,params:applySpec.actionParam,value:applySpec.actionValue,loadResult:applySpec.loadResult,dependencyManager:comp.env.dependencyManager,selectableContext:comp.env.selectableContext,}));}}
return await Promise.all(cleanOrApplyProms);}
function getPriority(){return(getAllActions().map((a)=>getAction(a.actionId).getPriority?.({params:a.actionParam,value:a.actionValue,})||0).find((x)=>x!==0)||0);}
return{operation,isApplied,clean,priority:getPriority(),getActions:getAllActions,onReady,};}
function useOperationWithReload(callApply,reload){const env=useEnv();return async(...args)=>{const{editingElement}=args[0][0];env.services.ui.block();try{const applyResults=await callApply(...args);if(!applyResults.includes(BuilderAction.cancelReload)){env.editor.shared.history.addStep();await env.editor.shared.savePlugin.save();const target=env.editor.shared.builderOptions.getReloadSelector(editingElement);const url=reload.getReloadUrl?.();await env.editor.config.reloadEditor({target,url});}}finally{env.services.ui.unblock();}};}
function getValueWithDefault(userInputValue,defaultValue,formatRawValue){if(defaultValue!==undefined){if(!userInputValue||(typeof userInputValue==="string"&&!userInputValue.trim())){return formatRawValue(defaultValue);}}
return userInputValue;}
function handleBuilderActionError(error,editingElement,comp){const isOutdated=comp.env.editor.shared.versionError.checkNotifyOutdatedSnippet(editingElement);if(!isOutdated){throw error;}}
__exports.useInputBuilderComponent=useInputBuilderComponent;function useInputBuilderComponent({id,defaultValue,formatRawValue=(rawValue)=>rawValue,parseDisplayValue=(displayValue)=>displayValue,}={}){const comp=useComponent();const{getAllActions,callOperation}=getAllActionsAndOperations(comp);const getAction=comp.env.editor.shared.builderActions.getAction;const state=useDomState(getState);const onReady=usePrepareAction(getAllActions);const{reload}=useReloadAction(getAllActions);const withLoadingEffect=useWithLoadingEffect(getAllActions);const canTimeout=useCanTimeout(getAllActions);onWillUpdateProps((nextProps)=>{if("default"in nextProps){defaultValue=nextProps.default;}});async function callApply(applySpecs,isPreviewing){const proms=[];for(const applySpec of applySpecs){proms.push(applySpec.action.apply({isPreviewing,editingElement:applySpec.editingElement,params:applySpec.actionParam,value:applySpec.actionValue,loadResult:applySpec.loadResult,dependencyManager:comp.env.dependencyManager,}));}
return await Promise.all(proms);}
const applyOperation=comp.env.editor.shared.history.makePreviewableAsyncOperation(callApply);const operationWithReload=useOperationWithReload(callApply,reload);function getState(editingElement){if(!isConnectedElement(editingElement)){return{};}
const actionWithGetValue=getAllActions().find(({actionId})=>getAction(actionId).getValue);const{actionId,actionParam}=actionWithGetValue;try{const actionValue=getAction(actionId).getValue({editingElement,params:actionParam})||defaultValue;return{value:actionValue,};}catch(error){handleBuilderActionError(error,editingElement,comp);}}
function commit(userInputValue){userInputValue=getValueWithDefault(userInputValue,defaultValue,formatRawValue);const rawValue=parseDisplayValue(userInputValue);if(reload){callOperation(operationWithReload,{userInputValue:rawValue,operationParams:{withLoadingEffect:withLoadingEffect,canTimeout:canTimeout,},});}else{callOperation(applyOperation.commit,{userInputValue:rawValue,operationParams:{withLoadingEffect:withLoadingEffect,canTimeout:canTimeout,},});}
if(rawValue===null||(rawValue===defaultValue&&rawValue===state.value)){state.value=rawValue;}
return rawValue!==undefined?formatRawValue(rawValue):"";}
const shouldPreview=useHasPreview(getAllActions);function preview(userInputValue){if(shouldPreview){userInputValue=getValueWithDefault(userInputValue,defaultValue,formatRawValue);callOperation(applyOperation.preview,{preview:true,userInputValue:parseDisplayValue(userInputValue),operationParams:{cancellable:true,cancelPrevious:()=>applyOperation.revert(),canTimeout:canTimeout,},});}}
if(id){useDependencyDefinition(id,{type:"input",getValue:()=>state.value,},{onReady});}
return{state,commit,preview,onReady,};}
__exports.useApplyVisibility=useApplyVisibility;function useApplyVisibility(refName){const ref=useRef(refName);return(hasContent)=>{ref.el?.classList.toggle("d-none",!hasContent);};}
__exports.useVisibilityObserver=useVisibilityObserver;function useVisibilityObserver(contentName,callback){const contentRef=useRef(contentName);const applyVisibility=()=>{const hasContent=[...contentRef.el.childNodes].some((el)=>(isTextNode(el)&&el.textContent!=="")||(isElement(el)&&!el.classList.contains("d-none")));callback(hasContent);};const observer=new MutationObserver(applyVisibility);useEffect((contentEl)=>{if(!contentEl){return;}
applyVisibility();observer.observe(contentEl,{subtree:true,attributes:true,childList:true,attributeFilter:["class"],});return()=>{observer.disconnect();};},()=>[contentRef.el]);}
__exports.useInputDebouncedCommit=useInputDebouncedCommit;function useInputDebouncedCommit(ref){const comp=useComponent();return useDebounced(()=>{const normalizedDisplayValue=comp.commit(ref.el.value);ref.el.value=normalizedDisplayValue;},550);}
const basicContainerBuilderComponentProps=__exports.basicContainerBuilderComponentProps={id:{type:String,optional:true},applyTo:{type:String,optional:true},preview:{type:Boolean,optional:true},inheritedActions:{type:Array,element:String,optional:true},action:{type:String,optional:true},actionParam:{validate:()=>true,optional:true},classAction:{validate:()=>true,optional:true},attributeAction:{validate:()=>true,optional:true},dataAttributeAction:{validate:()=>true,optional:true},styleAction:{validate:()=>true,optional:true},};const validateIsNull={validate:(value)=>value===null};const clickableBuilderComponentProps=__exports.clickableBuilderComponentProps={...basicContainerBuilderComponentProps,inverseAction:{type:Boolean,optional:true},actionValue:{type:[Boolean,String,Number,{type:Array,element:[Boolean,String,Number]}],optional:true,},classActionValue:{type:[String,Array,validateIsNull],optional:true},attributeActionValue:{type:[String,Array,validateIsNull],optional:true},dataAttributeActionValue:{type:[String,Array,validateIsNull],optional:true},styleActionValue:{type:[String,Array,validateIsNull],optional:true},inheritedActions:{type:Array,element:String,optional:true},};__exports.getAllActionsAndOperations=getAllActionsAndOperations;function getAllActionsAndOperations(comp){const inheritedActionIds=comp.props.inheritedActions||comp.env.weContext.inheritedActions||[];function getActionsSpecs(actions,userInputValue){const getAction=comp.env.editor.shared.builderActions.getAction;const overridableMethods=["apply","clean","load","loadOnClean"];const specs=[];for(let{actionId,actionParam,actionValue}of actions){const action=getAction(actionId);actionValue=actionValue===undefined?userInputValue:actionValue;for(const editingElement of comp.env.getEditingElements()){const spec={editingElement,actionId,actionParam,actionValue,action,};for(const method of overridableMethods){if(!action.has||action.has(method)){spec[method]=action[method];}}
specs.push(spec);}}
return specs;}
function getShorthandActions(){const actions=[];const shorthands=[["classAction","classActionValue"],["attributeAction","attributeActionValue"],["dataAttributeAction","dataAttributeActionValue"],["styleAction","styleActionValue"],];for(const[actionId,actionValue]of shorthands){const actionParam=comp.env.weContext[actionId]||comp.props[actionId];if(actionParam!==undefined){actions.push({actionId,actionParam:convertParamToObject(actionParam),actionValue:comp.props[actionValue],});}}
return actions;}
function getCustomAction(){const actionId=comp.props.action||comp.env.weContext.action;if(actionId){const actionParam=comp.props.actionParam??comp.env.weContext.actionParam;return{actionId:actionId,actionParam:convertParamToObject(actionParam),actionValue:comp.props.actionValue,};}}
function getAllActions(){const actions=getShorthandActions();const{actionId,actionParam,actionValue}=getCustomAction()||{};if(actionId){actions.push({actionId,actionParam,actionValue});}
const inheritedActions=inheritedActionIds.map((actionId)=>comp.env.dependencyManager.get(actionId)?.getActions?.()||[]).flat()||[];return actions.concat(inheritedActions||[]);}
function callOperation(fn,params={}){const isPreviewing=!!params.preview;const actionsSpecs=getActionsSpecs(getAllActions(),params.userInputValue);comp.env.editor.shared.operation.next(async()=>{try{await fn(actionsSpecs,isPreviewing);}catch(error){handleBuilderActionError(error,comp.env.getEditingElement(),comp);}},{load:async()=>{try{return await Promise.all(actionsSpecs.map(async(applySpec)=>{if(!applySpec.action.has("load")){return;}
const hasClean=!!applySpec.action.has("clean");if(!applySpec.loadOnClean&&_shouldClean(comp,hasClean,isApplied())){return;}
const result=await applySpec.action.load({editingElement:applySpec.editingElement,params:applySpec.actionParam,value:applySpec.actionValue,});applySpec.loadResult=result;}));}catch(error){handleBuilderActionError(error,comp.env.getEditingElement(),comp);}},...params.operationParams,});}
function isApplied(){const getAction=comp.env.editor.shared.builderActions.getAction;const editingElements=comp.env.getEditingElements();if(!editingElements.length){return;}
const areActionsActiveTabs=getAllActions().map((o)=>{const{actionId,actionParam,actionValue}=o;const editingElement=editingElements[0];if(!isConnectedElement(editingElement)){return false;}
try{const isApplied=getAction(actionId).isApplied?.({editingElement,params:actionParam,value:actionValue,});return comp.props.inverseAction?!isApplied:isApplied;}catch(error){handleBuilderActionError(error,editingElement,comp);}});if(areActionsActiveTabs.every((el)=>el===undefined)){return false;}
if(areActionsActiveTabs.some((el)=>el===false)){return false;}
return true;}
return{getAllActions:getAllActions,callOperation:callOperation,isApplied:isApplied,};}
function _shouldClean(comp,hasClean,isApplied){if(!hasClean){return false;}
const shouldToggle=!comp.env.selectableContext;const shouldClean=shouldToggle&&isApplied;return comp.props.inverseAction?!shouldClean:shouldClean;}
__exports.convertParamToObject=convertParamToObject;function convertParamToObject(param){if(param===undefined){param={};}else if(param instanceof Array||param instanceof Function||!(param instanceof Object)){param={["mainParam"]:param,};}
return param;}
const BaseOptionComponent=__exports.BaseOptionComponent=class BaseOptionComponent extends Component{static components={};static props={};static template="";setup(){const context=this.env.editor.shared.builderOptions.getBuilderOptionContext(this.constructor);this.document=context.document;this.window=context.document.defaultView;this.editable=context.editable;this.config=context.config;this.services=context.services;this.dependencies=context.dependencies;this.getResource=context.getResource;this.dispatchTo=context.dispatchTo;this.delegateTo=context.delegateTo;this.isActiveItem=useIsActiveItem();const comp=useComponent();const editor=comp.env.editor;if(!comp.constructor.components){comp.constructor.components={};}
const Components=editor.shared.builderComponents.getComponents();Object.assign(comp.constructor.components,Components);}
isActiveItems(itemIds){return itemIds.map((i)=>this.isActiveItem(i)).find(Boolean)||false;}}
return __exports;});;

/* /html_builder/static/src/core/version_error_plugin.js */
odoo.define('@html_builder/core/version_error_plugin',['@html_editor/plugin','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const VersionErrorPlugin=__exports.VersionErrorPlugin=class VersionErrorPlugin extends Plugin{static id="versionError";static shared=["checkNotifyOutdatedSnippet"];static dependencies=[];resources={};isSnippetUpToDate(el){const snippetEl=el?.closest?.("[data-snippet]");if(!snippetEl){return true;}
const snippetKey=snippetEl.dataset.snippet;const snippet=this.config.snippetModel.getOriginalSnippet(snippetKey);if(!snippet){return true;}
const{vcss:originalVcss,vxml:originalVxml,vjs:originalVjs,}=snippet.content.dataset;const{vcss:elVcss,vxml:elVxml,vjs:elVjs}=snippetEl.dataset;return originalVcss===elVcss&&originalVxml===elVxml&&originalVjs===elVjs;}
checkNotifyOutdatedSnippet(editingElement){if(!this.isSnippetUpToDate(editingElement)){this.closeExistingNotification?.();this.closeExistingNotification=this.services.notification.add(_t("It might have caused problem during the editing. Please drag the new version from the snippet panel to update it."),{type:"warning",title:_t("This snippet is outdated"),sticky:true,});return true;}
return false;}}
return __exports;});;

/* /html_builder/static/src/core/visibility_plugin.js */
odoo.define('@html_builder/core/visibility_plugin',['@html_editor/plugin','@html_builder/utils/utils','@html_editor/utils/resource'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{getElementsWithOption}=require("@html_builder/utils/utils");const{withSequence}=require("@html_editor/utils/resource");const invisibleElementsSelector=".o_snippet_invisible, .o_snippet_mobile_invisible, .o_snippet_desktop_invisible";const deviceInvisibleSelector=".o_snippet_mobile_invisible, .o_snippet_desktop_invisible";const VisibilityPlugin=__exports.VisibilityPlugin=class VisibilityPlugin extends Plugin{static id="visibility";static dependencies=["builderOptions","disableSnippets","history"];static shared=["getVisibleSibling","toggleTargetVisibility","onOptionVisibilityUpdate","hideElement",];resources={on_mobile_preview_clicked:withSequence(10,this.onMobilePreviewClicked.bind(this)),system_attributes:["data-invisible"],system_classes:["o_snippet_override_invisible"],clean_for_save_handlers:this.cleanForSaveVisibility.bind(this),on_snippet_dropped_handlers:this.onSnippetDropped.bind(this),on_restore_containers_handlers:(newTargetEl)=>this.makeTargetVisible(newTargetEl),};setup(){const isMobilePreview=this.config.isMobileView(this.editable);this.editable.querySelectorAll(deviceInvisibleSelector).forEach((invisibleEl)=>{const isMobileHidden=invisibleEl.matches(".o_snippet_mobile_invisible");const isDesktopHidden=invisibleEl.matches(".o_snippet_desktop_invisible");if((isMobileHidden&&isMobilePreview)||(isDesktopHidden&&!isMobilePreview)){invisibleEl.setAttribute("data-invisible","1");}else{invisibleEl.removeAttribute("data-invisible");}});}
getVisibleSibling(target,direction){const systemNodeSelectors=this.getResource("system_node_selectors").join(",");const siblingEls=[...target.parentNode.children];const visibleSiblingEls=siblingEls.filter((el)=>!el.classList.contains("o_we_no_overlay")&&window.getComputedStyle(el).display!=="none"&&!el.closest(systemNodeSelectors));const targetMobileOrder=target.style.order;if(targetMobileOrder&&this.config.isMobileView(target)){visibleSiblingEls.sort((a,b)=>parseInt(a.style.order)-parseInt(b.style.order));}
const targetIndex=visibleSiblingEls.indexOf(target);const siblingIndex=direction==="prev"?targetIndex-1:targetIndex+1;if(siblingIndex===-1||siblingIndex===visibleSiblingEls.length){return false;}
return visibleSiblingEls[siblingIndex];}
makeTargetVisible(targetEl){let invisibleEl=targetEl.closest("[data-invisible='1']");if(!invisibleEl){return;}
while(invisibleEl){this.toggleTargetVisibility(invisibleEl,true);invisibleEl=targetEl.closest("[data-invisible='1']");}
this.config.updateInvisibleElementsPanel();}
cleanForSaveVisibility({root:rootEl}){const invisibleEls=getElementsWithOption(rootEl,invisibleElementsSelector);for(const invisibleEl of invisibleEls){this.toggleTargetVisibility(invisibleEl,false,false,true);if(invisibleEl.matches("[data-visibility='conditional']")){invisibleEl.removeAttribute("data-invisible");}}}
onSnippetDropped({snippetEl}){const invisibleEls=getElementsWithOption(snippetEl,invisibleElementsSelector);for(const invisibleEl of invisibleEls){this.toggleTargetVisibility(invisibleEl,true);}}
onMobilePreviewClicked(){const deviceInvisibleEls=this.editable.querySelectorAll(deviceInvisibleSelector);const currentContainerTargetEl=this.dependencies["builderOptions"].getTarget();for(const deviceInvisibleEl of[...deviceInvisibleEls]){deviceInvisibleEl.classList.remove("o_snippet_override_invisible");const show=!isTargetVisible(deviceInvisibleEl);const isShown=this.toggleVisibilityStatus(deviceInvisibleEl,show,true);if(!isShown&&deviceInvisibleEl.contains(currentContainerTargetEl)){this.dependencies.builderOptions.deactivateContainers();}}}
toggleTargetVisibility(editingEl,show,considerDeviceVisibility,isCleaning=false){show=this.toggleVisibilityStatus(editingEl,show,considerDeviceVisibility);const resourceName=show?"target_show":"target_hide";this.dispatchTo(resourceName,editingEl);return show;}
onOptionVisibilityUpdate(editingEl,show){if(this.dependencies.history.getIsPreviewing()){return;}
const isShown=this.toggleVisibilityStatus(editingEl,show);if(!isShown){this.dependencies.builderOptions.setNextTarget(false);}
this.config.updateInvisibleElementsPanel();this.dependencies.disableSnippets.disableUndroppableSnippets();}
toggleVisibilityStatus(editingEl,show,considerDeviceVisibility=false){if(considerDeviceVisibility&&editingEl.matches(".o_snippet_mobile_invisible, .o_snippet_desktop_invisible")){const isMobilePreview=this.config.isMobileView(editingEl);const isMobileHidden=editingEl.classList.contains("o_snippet_mobile_invisible");show=isMobilePreview!==isMobileHidden;}
if(show===undefined){show=!isTargetVisible(editingEl);}
if(show){delete editingEl.dataset.invisible;}else{editingEl.dataset.invisible="1";}
return show;}
hideElement(toHideEl){this.toggleTargetVisibility(toHideEl,false);this.dependencies.builderOptions.deactivateContainers();this.config.updateInvisibleElementsPanel();this.dependencies.disableSnippets.disableUndroppableSnippets();}}
function isTargetVisible(editingEl){return editingEl.dataset.invisible!=="1";}
return __exports;});;

/* /html_builder/static/src/plugins/add_product_option.js */
odoo.define('@html_builder/plugins/add_product_option',['@html_builder/core/utils','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const BaseAddProductOption=__exports.BaseAddProductOption=class BaseAddProductOption extends BaseOptionComponent{static template="html_builder.AddProductOption";buttonLabel=_t("Add Product");}
return __exports;});;

/* /html_builder/static/src/plugins/alert_option_plugin.js */
odoo.define('@html_builder/plugins/alert_option_plugin',['@html_builder/utils/option_sequence','@html_editor/plugin','@html_editor/utils/fonts','@web/core/registry','@html_editor/utils/resource','@html_builder/core/builder_action','@html_builder/core/utils'],function(require){'use strict';let __exports={};const{before,WIDTH}=require("@html_builder/utils/option_sequence");const{Plugin}=require("@html_editor/plugin");const{fonts}=require("@html_editor/utils/fonts");const{registry}=require("@web/core/registry");const{withSequence}=require("@html_editor/utils/resource");const{BuilderAction}=require("@html_builder/core/builder_action");const{BaseOptionComponent}=require("@html_builder/core/utils");class AlertOptionPlugin extends Plugin{static id="alertOption";resources={builder_actions:{AlertIconAction,},builder_options:[withSequence(before(WIDTH),AlertOption)],so_content_addition_selector:[".s_alert"],};}
const AlertOption=__exports.AlertOption=class AlertOption extends BaseOptionComponent{static template="html_builder.AlertOption";static selector=".s_alert";static name="alertTypeOption";}
const AlertIconAction=__exports.AlertIconAction=class AlertIconAction extends BuilderAction{static id="alertIcon";apply({editingElement,params:{mainParam:className}}){const icon=editingElement.querySelector(".s_alert_icon");if(!icon){return;}
fonts.computeFonts();const allFaIcons=fonts.fontIcons[0].alias;icon.classList.remove(...allFaIcons);icon.classList.add(className);}
clean({editingElement,params:{mainParam:className}}){const icon=editingElement.querySelector(".s_alert_icon");if(!icon){return;}
icon.classList.remove(className);}
isApplied({editingElement,params:{mainParam:className}}){const iconEl=editingElement.querySelector(".s_alert_icon");if(!iconEl){return;}
return iconEl.classList.contains(className);}}
registry.category("builder-plugins").add(AlertOptionPlugin.id,AlertOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/background_option/background_hook.js */
odoo.define('@html_builder/plugins/background_option/background_hook',[],function(require){'use strict';let __exports={};__exports.useBackgroundOption=useBackgroundOption;function useBackgroundOption(isActiveItem){return{showColorFilter:()=>isActiveItem("toggle_bg_image_id")};}
return __exports;});;

/* /html_builder/static/src/plugins/background_option/background_image_option.js */
odoo.define('@html_builder/plugins/background_option/background_image_option',['@html_builder/core/utils','@html_builder/utils/utils_css','@html_builder/plugins/image/image_size','@html_editor/utils/formatting'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const{getBgImageURLFromEl,normalizeColor}=require("@html_builder/utils/utils_css");const{ImageSize}=require("@html_builder/plugins/image/image_size");const{getHtmlStyle}=require("@html_editor/utils/formatting");const BackgroundImageOption=__exports.BackgroundImageOption=class BackgroundImageOption extends BaseOptionComponent{static template="html_builder.BackgroundImageOption";static dependencies=["history","backgroundImageOption"];static components={ImageSize};setup(){this.editingElement=this.env.getEditingElement();super.setup();this.toggleBgImageClasses();}
toggleBgImageClasses(){this.dependencies.history.ignoreDOMMutations(()=>{const backgroundURL=getBgImageURLFromEl(this.editingElement);this.dependencies.backgroundImageOption.setImageBackground(this.editingElement,backgroundURL);});}
showMainColorPicker(){const src=new URL(getBgImageURLFromEl(this.editingElement),window.location.origin);return(src.origin===window.location.origin&&(src.pathname.startsWith("/html_editor/shape/")||src.pathname.startsWith("/web_editor/shape/")));}
getColorPickerColorNames(){const colorNames=[];for(let nbr=1;nbr<=5;nbr++){const colorName=`c${nbr}`;if(getBackgroundImageColor(this.editingElement,colorName)){colorNames.push(colorName);}}
return colorNames;}}
__exports.getBackgroundImageColor=getBackgroundImageColor;function getBackgroundImageColor(editingEl,colorName){const backgroundImageColor=new URL(getBgImageURLFromEl(editingEl),window.location.origin).searchParams.get(colorName);if(backgroundImageColor){return normalizeColor(backgroundImageColor,getHtmlStyle(editingEl.ownerDocument));}}
return __exports;});;

/* /html_builder/static/src/plugins/background_option/background_image_option_plugin.js */
odoo.define('@html_builder/plugins/background_option/background_image_option_plugin',['@html_builder/utils/utils','@html_builder/utils/utils_css','@html_editor/plugin','@html_editor/utils/image_processing','@web/core/registry','@web/core/utils/colors','@html_builder/plugins/background_option/background_image_option','@html_builder/core/builder_action','@html_builder/core/core_builder_action_plugin','@html_editor/utils/resource'],function(require){'use strict';let __exports={};const{getValueFromVar}=require("@html_builder/utils/utils");const{getBgImageURLFromEl,isBackgroundImageAttribute}=require("@html_builder/utils/utils_css");const{Plugin}=require("@html_editor/plugin");const{removeOnImageChangeAttrs}=require("@html_editor/utils/image_processing");const{registry}=require("@web/core/registry");const{convertCSSColorToRgba}=require("@web/core/utils/colors");const{getBackgroundImageColor}=require("@html_builder/plugins/background_option/background_image_option");const{BuilderAction}=require("@html_builder/core/builder_action");const{StyleAction}=require("@html_builder/core/core_builder_action_plugin");const{withSequence}=require("@html_editor/utils/resource");const BackgroundImageOptionPlugin=__exports.BackgroundImageOptionPlugin=class BackgroundImageOptionPlugin extends Plugin{static id="backgroundImageOption";static dependencies=["builderActions","media","style"];static shared=["changeEditingEl","setImageBackground","loadReplaceBackgroundImage","applyReplaceBackgroundImage","removeBackgroundImage",];resources={builder_actions:{SelectFilterColorAction,ToggleBgImageAction,RemoveBgImageAction,ReplaceBgImageAction,DynamicColorAction,},content_not_editable_selectors:".o_we_bg_filter",system_node_selectors:".o_we_bg_filter",get_target_element_providers:withSequence(5,(el)=>el),};changeEditingEl(oldEditingEl,newEditingEl){const oldBgURL=getBgImageURLFromEl(oldEditingEl);const isModifiedImage=oldEditingEl.classList.contains("o_modified_image_to_save");const filteredOldDataset=Object.entries(oldEditingEl.dataset).filter(([key])=>isBackgroundImageAttribute(key));for(const[key]of filteredOldDataset){delete oldEditingEl.dataset[key];}
oldEditingEl.classList.remove("o_modified_image_to_save");const filterColorAction=this.dependencies.builderActions.getAction("selectFilterColor");const editingElement=this.getResource("get_target_element_providers")[0](oldEditingEl);const filter=filterColorAction.getValue({editingElement});this.setImageBackground(oldEditingEl,"");if(filter){filterColorAction.apply({editingElement,value:filter,});}
if(oldBgURL){this.setImageBackground(newEditingEl,oldBgURL);for(const[key,value]of filteredOldDataset){newEditingEl.dataset[key]=value;}
newEditingEl.classList.toggle("o_modified_image_to_save",isModifiedImage);}}
loadReplaceBackgroundImage({editingElement}){return new Promise((resolve)=>{const onClose=this.dependencies.media.openMediaDialog({onlyImages:true,node:editingElement,save:async(imageEl)=>{resolve(imageEl);},});onClose.then(resolve);});}
applyReplaceBackgroundImage({editingElement,loadResult:imageEl,params:{forceClean=false},}){if(!forceClean&&!imageEl){return;}
const src=imageEl?.src||"";this.setImageBackground(editingElement,src);for(const attr of removeOnImageChangeAttrs){delete editingElement.dataset[attr];}
if(imageEl){if(src.startsWith("data:")){editingElement.classList.add("o_modified_image_to_save");}
Object.assign(editingElement.dataset,imageEl.dataset);}}
setImageBackground(el,backgroundURL){if(backgroundURL){el.classList.add("oe_img_bg","o_bg_img_center","o_bg_img_origin_border_box");}else{const editingElement=this.getResource("get_target_element_providers")[0](el);this.dependencies.builderActions.getAction("selectFilterColor").apply({editingElement});el.classList.remove("oe_img_bg","o_bg_img_center","o_bg_img_origin_border_box","o_modified_image_to_save");}
this.dependencies.style.setBackgroundImageUrl(el,backgroundURL);}
removeBackgroundImage({editingElement,params}){this.applyReplaceBackgroundImage({editingElement,loadResult:"",params:{...params,forceClean:true},});this.dispatchTo("on_bg_image_hide_handlers",editingElement);}}
const SelectFilterColorAction=__exports.SelectFilterColorAction=class SelectFilterColorAction extends StyleAction{static id="selectFilterColor";static dependencies=["color","backgroundImageOption","builderActions"];apply({editingElement,value}){let filterEl=editingElement.querySelector(":scope > .o_we_bg_filter");if(filterEl&&value===undefined){value=filterEl.style.backgroundImage;}
const rgba=value&&convertCSSColorToRgba(value);if(!value||(rgba&&rgba.opacity<0.001)){if(filterEl){filterEl.remove();}
return;}
if(!filterEl){filterEl=document.createElement("div");filterEl.classList.add("o_we_bg_filter");let lastBackgroundEl;for(const fn of this.getResource("background_filter_target_providers")){lastBackgroundEl=fn(editingElement);if(lastBackgroundEl){break;}}
if(lastBackgroundEl){lastBackgroundEl.insertAdjacentElement("afterend",filterEl);}else{editingElement.prepend(filterEl);}}
this.dependencies.builderActions.getAction("styleAction").apply({editingElement:filterEl,params:{mainParam:"background-color",},value:value,});}
getValue({editingElement}){const filterEl=editingElement.querySelector(":scope > .o_we_bg_filter");if(!filterEl){return"";}
return super.getValue({editingElement:filterEl,params:{mainParam:"background-color",},});}}
const ToggleBgImageAction=__exports.ToggleBgImageAction=class ToggleBgImageAction extends BuilderAction{static id="toggleBgImage";static dependencies=["backgroundImageOption"];load(context){return this.dependencies.backgroundImageOption.loadReplaceBackgroundImage(context);}
apply(context){return this.dependencies.backgroundImageOption.applyReplaceBackgroundImage(context);}
isApplied({editingElement}){return!!getBgImageURLFromEl(editingElement);}
clean(context){this.dependencies.backgroundImageOption.removeBackgroundImage(context);}}
const RemoveBgImageAction=__exports.RemoveBgImageAction=class RemoveBgImageAction extends BuilderAction{static id="removeBgImage";static dependencies=["backgroundImageOption"];apply(context){this.dependencies.backgroundImageOption.removeBackgroundImage(context);}}
const ReplaceBgImageAction=__exports.ReplaceBgImageAction=class ReplaceBgImageAction extends BuilderAction{static id="replaceBgImage";static dependencies=["backgroundImageOption"];load(context){return this.dependencies.backgroundImageOption.loadReplaceBackgroundImage(context);}
apply(context){return this.dependencies.backgroundImageOption.applyReplaceBackgroundImage(context);}}
const DynamicColorAction=__exports.DynamicColorAction=class DynamicColorAction extends BuilderAction{static id="dynamicColor";static dependencies=["backgroundImageOption"];getValue({editingElement,params:{mainParam:colorName}}){return getBackgroundImageColor(editingElement,colorName);}
apply({editingElement,params:{mainParam:colorName},value}){value=getValueFromVar(value);const currentSrc=getBgImageURLFromEl(editingElement);const newURL=new URL(currentSrc,window.location.origin);newURL.searchParams.set(colorName,value);const src=newURL.pathname+newURL.search;this.dependencies.backgroundImageOption.setImageBackground(editingElement,src);}}
registry.category("builder-plugins").add(BackgroundImageOptionPlugin.id,BackgroundImageOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/background_option/background_option.js */
odoo.define('@html_builder/plugins/background_option/background_option',['@html_builder/core/utils','@html_builder/plugins/background_option/background_image_option','@html_builder/plugins/background_option/background_position_option','@html_builder/plugins/background_option/background_shape_option','@html_builder/plugins/background_option/background_hook','@html_builder/plugins/image/image_filter_option','@html_builder/plugins/image/image_format_option'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const{BackgroundImageOption}=require("@html_builder/plugins/background_option/background_image_option");const{BackgroundPositionOption}=require("@html_builder/plugins/background_option/background_position_option");const{BackgroundShapeOption}=require("@html_builder/plugins/background_option/background_shape_option");const{useBackgroundOption}=require("@html_builder/plugins/background_option/background_hook");const{ImageFilterOption}=require("@html_builder/plugins/image/image_filter_option");const{ImageFormatOption}=require("@html_builder/plugins/image/image_format_option");const BackgroundOption=__exports.BackgroundOption=class BackgroundOption extends BaseOptionComponent{static template="html_builder.BackgroundOption";static components={BackgroundImageOption,BackgroundPositionOption,BackgroundShapeOption,ImageFilterOption,ImageFormatOption,};static props={withColors:{type:Boolean},withImages:{type:Boolean},withColorCombinations:{type:Boolean},withShapes:{type:Boolean,optional:true},};static defaultProps={withShapes:false,};setup(){super.setup();const{showColorFilter}=useBackgroundOption(this.isActiveItem);this.showColorFilter=showColorFilter;}
computeMaxDisplayWidth(){return 1920;}}
return __exports;});;

/* /html_builder/static/src/plugins/background_option/background_option_plugin.js */
odoo.define('@html_builder/plugins/background_option/background_option_plugin',['@html_builder/plugins/utils','@html_editor/plugin','@web/core/registry'],function(require){'use strict';let __exports={};const{applyFunDependOnSelectorAndExclude}=require("@html_builder/plugins/utils");const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");class BackgroundOptionPlugin extends Plugin{static id="backgroundOption";resources={normalize_handlers:this.normalize.bind(this),system_classes:["o_colored_level"],};normalize(root){const markColorLevelSelectorParams=this.getResource("mark_color_level_selector_params");for(const markColorLevelSelectorParam of markColorLevelSelectorParams){applyFunDependOnSelectorAndExclude(this.markColorLevel,root,markColorLevelSelectorParam);}}
markColorLevel(editingEl){editingEl.classList.add("o_colored_level");}}
registry.category("builder-plugins").add(BackgroundOptionPlugin.id,BackgroundOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/background_option/background_position_option.js */
odoo.define('@html_builder/plugins/background_option/background_position_option',['@html_builder/core/utils'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const BackgroundPositionOption=__exports.BackgroundPositionOption=class BackgroundPositionOption extends BaseOptionComponent{static template="html_builder.BackgroundPositionOption";}
return __exports;});;

/* /html_builder/static/src/plugins/background_option/background_position_option_plugin.js */
odoo.define('@html_builder/plugins/background_option/background_position_option_plugin',['@html_builder/utils/utils_css','@html_editor/plugin','@web/core/registry','@html_builder/plugins/background_option/background_position_overlay','@html_builder/core/builder_action','@html_editor/utils/image_processing'],function(require){'use strict';let __exports={};const{getBgImageURLFromEl}=require("@html_builder/utils/utils_css");const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{BackgroundPositionOverlay}=require("@html_builder/plugins/background_option/background_position_overlay");const{BuilderAction}=require("@html_builder/core/builder_action");const{loadImage}=require("@html_editor/utils/image_processing");const getBgSizeValue=function({editingElement,params:{mainParam:styleName}}){const backgroundSize=editingElement.style.backgroundSize;const bgWidthAndHeight=backgroundSize.split(/\s+/g);const value=styleName==="width"?bgWidthAndHeight[0]:bgWidthAndHeight[1]||"";return value==="auto"?"":value;};class BackgroundPositionOptionPlugin extends Plugin{static id="backgroundPositionOption";static dependencies=["overlay","overlayButtons"];resources={builder_actions:{BackgroundTypeAction,SetBackgroundSizeAction,BackgroundPositionOverlayAction,},};}
const BackgroundTypeAction=__exports.BackgroundTypeAction=class BackgroundTypeAction extends BuilderAction{static id="backgroundType";apply({editingElement,value}){editingElement.classList.toggle("o_bg_img_opt_repeat",value==="repeat-pattern");editingElement.style.setProperty("background-position","");editingElement.style.setProperty("background-size",value!=="repeat-pattern"?"":"100px");}
isApplied({editingElement,value}){const hasElRepeatStyle=getComputedStyle(editingElement).backgroundRepeat==="repeat";return value==="repeat-pattern"?hasElRepeatStyle:!hasElRepeatStyle;}}
const SetBackgroundSizeAction=__exports.SetBackgroundSizeAction=class SetBackgroundSizeAction extends BuilderAction{static id="setBackgroundSize";getValue(context){return getBgSizeValue(context);}
apply({editingElement,params:{mainParam:styleName},value}){const otherParam=styleName==="width"?"height":"width";let otherBgSize=getBgSizeValue({editingElement:editingElement,params:{mainParam:otherParam},});let bgSize;value||="auto";if(styleName==="width"){otherBgSize=otherBgSize===""?"":` ${otherBgSize}`;bgSize=`${value}${otherBgSize}`;}else{otherBgSize||="auto";bgSize=`${otherBgSize} ${value}`;}
editingElement.style.setProperty("background-size",bgSize);}}
const BackgroundPositionOverlayAction=__exports.BackgroundPositionOverlayAction=class BackgroundPositionOverlayAction extends BuilderAction{static id="backgroundPositionOverlay";static dependencies=["overlayButtons","history"];setup(){this.withLoadingEffect=false;}
async load({editingElement}){const imgEl=await loadImage(getBgImageURLFromEl(editingElement));return new Promise((resolve)=>{this.dependencies.overlayButtons.hideOverlayButtonsUi();let appliedBgPosition="";const onRemove=()=>{this.dependencies.overlayButtons.showOverlayButtonsUi();resolve(appliedBgPosition);};const removeOverlay=this.services.overlay.add(BackgroundPositionOverlay,{editingElement:editingElement,mockEditingElOnImg:imgEl,applyPosition:(bgPosition)=>{appliedBgPosition=bgPosition;removeOverlay();},discardPosition:()=>removeOverlay(),editable:this.editable,history:{makeSavePoint:this.dependencies.history.makeSavePoint,},},{onRemove});});}
apply({editingElement,loadResult:bgPosition}){if(bgPosition){editingElement.style.backgroundPosition=bgPosition;}}}
registry.category("builder-plugins").add(BackgroundPositionOptionPlugin.id,BackgroundPositionOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/background_option/background_position_overlay.js */
odoo.define('@html_builder/plugins/background_option/background_position_overlay',['@html_builder/utils/scrolling','@odoo/owl'],function(require){'use strict';let __exports={};const{scrollTo}=require("@html_builder/utils/scrolling");const{Component,onMounted,onWillStart,onWillUnmount,useEffect,useExternalListener,useRef,}=require("@odoo/owl");const BackgroundPositionOverlay=__exports.BackgroundPositionOverlay=class BackgroundPositionOverlay extends Component{static template="html_builder.BackgroundPositionOverlay";static props={editingElement:{validate:(p)=>p.nodeType===Node.ELEMENT_NODE},mockEditingElOnImg:{validate:(p)=>p.tagName==="IMG"},applyPosition:{type:Function},discardPosition:{type:Function},editable:{validate:(p)=>p.nodeType===Node.ELEMENT_NODE},history:Object,};setup(){this.backgroundOverlayRef=useRef("backgroundOverlay");this.overlayMaskRef=useRef("overlayMask");this.overlayContentRef=useRef("overlayContent");this.bgDraggerRef=useRef("bgDragger");this.iframe=this.props.editable.ownerDocument.defaultView.frameElement;this.builderOverlayContainerEl=document.querySelector("[data-oe-local-overlay-id='builder-overlay-container']");this.targetContainerEl=this.props.editingElement.classList.contains("s_parallax_bg")?this.props.editingElement.parentElement:this.props.editingElement;this._dimensionOverlay=this.dimensionOverlay.bind(this);const editableDocument=this.props.editable.ownerDocument;useExternalListener(editableDocument,"pointerdown",this.discard.bind(this));useExternalListener(document,"pointerdown",this.discard.bind(this));useExternalListener(window,"resize",this._dimensionOverlay);useExternalListener(this.iframe.contentWindow,"resize",this._dimensionOverlay);useExternalListener(this.iframe.contentWindow,"scroll",this._dimensionOverlay);onWillStart(async()=>{const position=getComputedStyle(this.props.editingElement).backgroundPosition.split(" ").map((v)=>parseInt(v));const delta=this.getBackgroundDelta();this.originalPosition={left:position[0],top:position[1]};this.currentPosition={left:(position[0]/100)*delta.x||0,top:(position[1]/100)*delta.y||0,};const rect=this.targetContainerEl.getBoundingClientRect();const isEditingElEntirelyVisible=rect.top>=0&&rect.bottom<=this.targetContainerEl.ownerDocument.defaultView.innerHeight;if(!isEditingElEntirelyVisible){await scrollTo(this.targetContainerEl,{extraOffset:50});}});onMounted(()=>{this.reloadSavePoint=this.props.history.makeSavePoint();this.dimensionOverlay();this.targetContainerEl.classList.add("o_we_background_positioning");});useEffect(()=>{this.tooltip=window.Tooltip.getOrCreateInstance(this.bgDraggerRef.el,{trigger:"manual",container:this.backgroundOverlayRef.el,});this.tooltip.show();});onWillUnmount(()=>{this.builderOverlayContainerEl.style.clipPath="";this.tooltip.dispose();});}
apply(){const position=getComputedStyle(this.props.editingElement).backgroundPosition;this.reloadSavePoint();this.props.applyPosition(position);}
discard(){this.reloadSavePoint();this.props.discardPosition();}
onWheel(ev){if(ev.ctrlKey){return;}
this.iframe.contentWindow.scrollBy(ev.deltaX,ev.deltaY);}
onDragBackgroundStart(ev){this.backgroundOverlayRef.el.classList.add("o_we_grabbing");const documentEl=window.document;const onDragBackgroundMove=this.onDragBackgroundMove.bind(this);documentEl.addEventListener("mousemove",onDragBackgroundMove);documentEl.addEventListener("mouseup",()=>{this.backgroundOverlayRef.el.classList.remove("o_we_grabbing");documentEl.removeEventListener("mousemove",onDragBackgroundMove);},{once:true});}
onDragBackgroundMove(ev){ev.preventDefault();const delta=this.getBackgroundDelta();this.currentPosition.left=clamp(this.currentPosition.left+ev.movementX,[0,delta.x]);this.currentPosition.top=clamp(this.currentPosition.top+ev.movementY,[0,delta.y]);const percentPosition={left:(this.currentPosition.left/delta.x)*100,top:(this.currentPosition.top/delta.y)*100,};percentPosition.left=isFinite(percentPosition.left)?percentPosition.left:this.originalPosition.left;percentPosition.top=isFinite(percentPosition.top)?percentPosition.top:this.originalPosition.top;this.props.editingElement.style.backgroundPosition=`${percentPosition.left}% ${percentPosition.top}%`;function clamp(val,bounds){bounds=bounds.sort();return Math.max(bounds[0],Math.min(val,bounds[1]));}}
dimensionOverlay(){const iframeRect=this.iframe.getBoundingClientRect();const targetContainerRect=this.targetContainerEl.getBoundingClientRect();const scale=this.getIframeContainerScale();const scaledRect=new DOMRect(scale*targetContainerRect.x,scale*targetContainerRect.y,scale*targetContainerRect.width,scale*targetContainerRect.height);const clipPath=`polygon(
            evenodd,
            0 0, 100% 0,100% 100%, 0 100%, 0 0,
            ${scaledRect.left}px ${scaledRect.top}px,
            ${scaledRect.right}px ${scaledRect.top}px,
            ${scaledRect.right}px ${scaledRect.bottom}px,
            ${scaledRect.left}px ${scaledRect.bottom}px,
            ${scaledRect.left}px ${scaledRect.top}px)
        `;this.overlayMaskRef.el.style.clipPath=clipPath;this.builderOverlayContainerEl.style.clipPath=clipPath;Object.assign(this.backgroundOverlayRef.el.style,{left:`${iframeRect.left}px`,top:`${iframeRect.top}px`,height:`${this.props.editable.ownerDocument.body.clientHeight * scale}px`,width:`${this.props.editable.ownerDocument.body.clientWidth * scale}px`,});Object.assign(this.overlayContentRef.el.style,{left:`${scaledRect.left}px`,top:`${scaledRect.top}px`,});const overlayButtonsEl=this.overlayContentRef.el.querySelector(".o_we_overlay_buttons");overlayButtonsEl.style.top=`${Math.max(0, -scaledRect.top)}px`;this.bgDraggerRef.el.style.setProperty("width",`${scaledRect.width}px`,"important");this.bgDraggerRef.el.style.setProperty("height",`${scaledRect.height}px`,"important");if(this.tooltip){this.tooltip.update();}}
getIframeContainerScale(){const matrix=getComputedStyle(this.iframe.parentElement).transform;if(matrix==="none"){return 1;}
const values=matrix.match(/matrix\(([^)]+)\)/)[1].split(",").map(parseFloat);return values[0];}
getBackgroundDelta(){const naturalWidth=this.props.mockEditingElOnImg.naturalWidth;const naturalHeight=this.props.mockEditingElOnImg.naturalHeight;const editingElStyle=getComputedStyle(this.props.editingElement);const bgRect=editingElStyle.backgroundAttachment==="fixed"?this.iframe.getBoundingClientRect():this.props.editingElement.getBoundingClientRect();if(editingElStyle.backgroundSize==="cover"){const renderRatio=Math.max(bgRect.width/naturalWidth,bgRect.height/naturalHeight);return{x:bgRect.width-Math.round(renderRatio*naturalWidth),y:bgRect.height-Math.round(renderRatio*naturalHeight),};}
let[width,height]=editingElStyle.backgroundSize.split(" ");if(width==="auto"&&(height==="auto"||!height)){return{x:bgRect.width-naturalWidth,y:bgRect.height-naturalHeight,};}
[width,height]=[parseInt(width),parseInt(height)];return{x:bgRect.width-(width||(height*naturalWidth)/naturalHeight),y:bgRect.height-(height||(width*naturalHeight)/naturalWidth),};}}
return __exports;});;

/* /html_builder/static/src/plugins/background_option/background_shape_option.js */
odoo.define('@html_builder/plugins/background_option/background_shape_option',['@html_builder/core/utils','@html_builder/utils/utils','@html_builder/utils/utils_css','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{BaseOptionComponent,useDomState}=require("@html_builder/core/utils");const{toRatio}=require("@html_builder/utils/utils");const{getBgImageURLFromEl}=require("@html_builder/utils/utils_css");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const BackgroundShapeOption=__exports.BackgroundShapeOption=class BackgroundShapeOption extends BaseOptionComponent{static template="html_builder.BackgroundShapeOption";static dependencies=["backgroundShapeOption"];setup(){super.setup();this.backgroundShapePlugin=this.dependencies.backgroundShapeOption;this.toRatio=toRatio;this.state=useDomState((editingElement)=>{const shapeData=this.backgroundShapePlugin.getShapeData(editingElement);const shapeInfo=this.backgroundShapePlugin.getBackgroundShapes()[shapeData.shape];return{shapeName:shapeInfo?.selectLabel||_t("None"),isAnimated:shapeInfo?.animated,};});}
showBackgroundShapes(){this.backgroundShapePlugin.showBackgroundShapes(this.env.getEditingElements());}
getDefaultColorNames(){const editingEl=this.env.getEditingElement();return Object.keys(getDefaultColors(editingEl));}}
__exports.getDefaultColors=getDefaultColors;function getDefaultColors(editingElement){const shapeContainerEl=editingElement.querySelector(":scope > .o_we_shape");if(!shapeContainerEl){return{};}
const shapeContainerClonedEl=shapeContainerEl.cloneNode(true);shapeContainerClonedEl.classList.add("d-none");editingElement.ownerDocument.body.appendChild(shapeContainerClonedEl);shapeContainerClonedEl.style.setProperty("background-image","");const shapeSrc=shapeContainerClonedEl&&getBgImageURLFromEl(shapeContainerClonedEl);shapeContainerClonedEl.remove();if(!shapeSrc){return{};}
const url=new URL(shapeSrc,window.location.origin);return Object.fromEntries(url.searchParams.entries());}
return __exports;});;

/* /html_builder/static/src/plugins/background_option/background_shape_option_plugin.js */
odoo.define('@html_builder/plugins/background_option/background_shape_option_plugin',['@html_builder/utils/utils','@html_builder/utils/utils_css','@html_editor/plugin','@web/core/l10n/translation','@web/core/registry','@web/core/utils/objects','@html_builder/plugins/background_option/background_shapes_definition','@html_builder/plugins/shape/shape_selector','@html_builder/plugins/background_option/background_shape_option','@html_editor/utils/resource','@html_editor/utils/image','@html_builder/core/builder_action','@html_editor/utils/formatting'],function(require){'use strict';let __exports={};const{getValueFromVar}=require("@html_builder/utils/utils");const{normalizeColor}=require("@html_builder/utils/utils_css");const{Plugin}=require("@html_editor/plugin");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{registry}=require("@web/core/registry");const{deepCopy,deepMerge,pick}=require("@web/core/utils/objects");const{backgroundShapesDefinition}=require("@html_builder/plugins/background_option/background_shapes_definition");const{ShapeSelector}=require("@html_builder/plugins/shape/shape_selector");const{getDefaultColors}=require("@html_builder/plugins/background_option/background_shape_option");const{withSequence}=require("@html_editor/utils/resource");const{getBgImageURLFromURL}=require("@html_editor/utils/image");const{BuilderAction}=require("@html_builder/core/builder_action");const{getHtmlStyle}=require("@html_editor/utils/formatting");const BackgroundShapeOptionPlugin=__exports.BackgroundShapeOptionPlugin=class BackgroundShapeOptionPlugin extends Plugin{static id="backgroundShapeOption";static dependencies=["customizeTab"];resources={builder_actions:{SetBackgroundShapeAction,ToggleBgShapeAction,ShowOnMobileAction,FlipShapeAction,SetBgAnimationSpeedAction,BackgroundShapeColorAction,},background_shape_groups_providers:withSequence(0,()=>deepCopy(backgroundShapesDefinition)),background_shape_target_providers:withSequence(5,(editingElement)=>editingElement.querySelector(":scope > .o_we_bg_filter")),content_not_editable_selectors:".o_we_shape",system_node_selectors:".o_we_shape",};static shared=["getShapeStyleUrl","getShapeData","showBackgroundShapes","getBackgroundShapes","getImplicitColors","applyShape","createShapeContainer",];setup(){this.shapeBackgroundImagePerClass={};for(const styleSheet of this.document.styleSheets){if(styleSheet.href&&new URL(styleSheet.href).host!==location.host){continue;}
for(const rule of[...styleSheet.cssRules]){if(rule.selectorText&&rule.selectorText.startsWith(".o_we_shape.")){this.shapeBackgroundImagePerClass[rule.selectorText]=rule.style.backgroundImage;}}}
const flipEls=[...this.editable.querySelectorAll(".o_we_flip_x, .o_we_flip_y")];for(const flipEl of flipEls){this.applyShape(flipEl,()=>({flip:this.getShapeData(flipEl).flip}));}}
applyShape(editingElement,computeShapeData){const newShapeData=computeShapeData();const changedShape=!!newShapeData.shape;this.markShape(editingElement,newShapeData);const json=editingElement.dataset.oeShapeData;const{shape,colors,flip=[],animated="false",showOnMobile,shapeAnimationSpeed,}=json?JSON.parse(json):{};let shapeContainerEl=editingElement.querySelector(":scope > .o_we_shape");if(!shape){return this.insertShapeContainer(editingElement,null);}
if(changedShape){shapeContainerEl=this.createShapeContainer(editingElement,shape);}
shapeContainerEl.classList.remove("o_we_flip_x","o_we_flip_y");shapeContainerEl.classList.toggle("o_we_animated",animated==="true");const shouldCustomize=Boolean(colors)||flip.length>0||parseFloat(shapeAnimationSpeed)!==0;if(shouldCustomize){shapeContainerEl.style.setProperty("background-image",`url("${this.getShapeSrc(editingElement)}")`);shapeContainerEl.style.backgroundPosition="";if(flip.length){let[xPos,yPos]=getComputedStyle(shapeContainerEl).backgroundPosition.split(" ").map(parseFloat);xPos=flip.includes("x")?-xPos+100:xPos;yPos=flip.includes("y")?-yPos+100:yPos;shapeContainerEl.style.backgroundPosition=`${xPos}% ${yPos}%`;}}else{shapeContainerEl.style.setProperty("background-image","");shapeContainerEl.style.setProperty("background-position","");}
shapeContainerEl.classList.toggle("o_shape_show_mobile",Boolean(showOnMobile));}
createShapeContainer(editingElement,shape){const shapeContainer=this.insertShapeContainer(editingElement,document.createElement("div"));editingElement.style.setProperty("position","relative");shapeContainer.className=`o_we_shape o_${shape.replace(/\//g, "_")}`;return shapeContainer;}
getImplicitColors(editingElement,shapeName,previousColors={}){const selectedBackgroundUrl=this.getShapeStyleUrl(shapeName);const defaultColors=this.getShapeDefaultColors(selectedBackgroundUrl);let colors=previousColors;let sibling=editingElement.previousElementSibling;while(sibling){colors=Object.assign(this.getShapeData(sibling).colors||{},colors);sibling=sibling.previousElementSibling;}
const defaultKeys=Object.keys(defaultColors);colors=Object.assign(defaultColors,colors);return pick(colors,...defaultKeys);}
getShapeDefaultColors(selectedBackgroundUrl){const shapeSrc=selectedBackgroundUrl&&getBgImageURLFromURL(selectedBackgroundUrl);const url=new URL(shapeSrc,window.location.origin);return Object.fromEntries(url.searchParams.entries());}
getShapeData(editingElement){const defaultData={shape:"",colors:getDefaultColors(editingElement),flip:[],showOnMobile:false,shapeAnimationSpeed:"0",};const json=editingElement.dataset.oeShapeData;if(json){Object.assign(defaultData,JSON.parse(json.replace(/'/g,'"')));defaultData.shape=defaultData.shape.replace("web_editor","html_builder");}
return defaultData;}
getShapeSrc(editingElement){const{shape,colors,flip,shapeAnimationSpeed}=this.getShapeData(editingElement);if(!shape){return"";}
const searchParams=Object.entries(colors).map(([colorName,colorValue])=>{const encodedCol=encodeURIComponent(colorValue);return`${colorName}=${encodedCol}`;});if(flip.length){searchParams.push(`flip=${encodeURIComponent(flip.sort().join(""))}`);}
if(Number(shapeAnimationSpeed)){searchParams.push(`shapeAnimationSpeed=${encodeURIComponent(shapeAnimationSpeed)}`);}
return`/html_editor/shape/${encodeURIComponent(shape)}.svg?${searchParams.join("&")}`;}
getShapeStyleUrl(shapeId){const shapeClassName=`o_${shapeId.replace(/\//g, "_")}`;return this.shapeBackgroundImagePerClass[`.o_we_shape.${shapeClassName}`];}
insertShapeContainer(editingElement,newContainer){const shapeContainerEl=editingElement.querySelector(":scope > .o_we_shape");if(shapeContainerEl){this.removeShapeEl(shapeContainerEl);}
if(newContainer){let preShapeLayerEl;for(const fn of this.getResource("background_shape_target_providers")){preShapeLayerEl=fn(editingElement);if(preShapeLayerEl){break;}}
if(preShapeLayerEl){preShapeLayerEl.insertAdjacentElement("afterend",newContainer);}else{editingElement.prepend(newContainer);}}
return newContainer;}
markShape(editingElement,newData){const defaultColors=getDefaultColors(editingElement);const shapeData=Object.assign(this.getShapeData(editingElement),newData);const areColorsDefault=Object.entries(shapeData.colors).every(([colorName,colorValue])=>defaultColors[colorName]&&colorValue.toLowerCase()===defaultColors[colorName].toLowerCase());if(areColorsDefault){delete shapeData.colors;}
if(!shapeData.shape){delete editingElement.dataset.oeShapeData;}else{editingElement.dataset.oeShapeData=JSON.stringify(shapeData);}}
removeShapeEl(shapeEl){shapeEl.remove();}
showBackgroundShapes(editingElements){this.dependencies.customizeTab.openCustomizeComponent(ShapeSelector,editingElements,{shapeActionId:"setBackgroundShape",buttonWrapperClassName:"o-hb-bg-shape-btn",selectorTitle:_t("Background Shapes"),shapeGroups:this.getBackgroundShapeGroups(),imgThroughDiv:true,getShapeUrl:this.getShapeStyleUrl.bind(this),});}
getBackgroundShapeGroups(){if(!this.backgroundShapeGroups){const shapeGroups={};for(const provider of this.getResource("background_shape_groups_providers")){const providedGroups=provider(shapeGroups);if(providedGroups){Object.assign(shapeGroups,deepMerge(shapeGroups,providedGroups));}}
this.backgroundShapeGroups=shapeGroups;}
return this.backgroundShapeGroups;}
getBackgroundShapes(){if(!this.backgroundShapesById){const entries=Object.values(this.getBackgroundShapeGroups()).map((x)=>Object.values(x.subgroups).map((x)=>Object.entries(x.shapes)).flat()).flat();this.backgroundShapesById=Object.fromEntries(entries);}
return this.backgroundShapesById;}}
class BaseAnimationAction extends BuilderAction{static id="baseAnimation";static dependencies=["backgroundShapeOption"];setup(){this.applyShape=this.dependencies.backgroundShapeOption.applyShape;this.getShapeData=this.dependencies.backgroundShapeOption.getShapeData;this.getImplicitColors=this.dependencies.backgroundShapeOption.getImplicitColors;this.getBackgroundShapes=this.dependencies.backgroundShapeOption.getBackgroundShapes;this.createShapeContainer=this.dependencies.backgroundShapeOption.createShapeContainer;this.showBackgroundShapes=this.dependencies.backgroundShapeOption.showBackgroundShapes;}}
class SetBackgroundShapeAction extends BaseAnimationAction{static id="setBackgroundShape";apply({editingElement,params,value}){params=params||{};const shapeData=this.getShapeData(editingElement);const applyShapeParams={shape:value,colors:this.getImplicitColors(editingElement,value,shapeData.colors),flip:[],animated:params.animated,shapeAnimationSpeed:shapeData.shapeAnimationSpeed,};this.applyShape(editingElement,()=>applyShapeParams);}
isApplied({editingElement,value}){const currentShapeApplied=this.getShapeData(editingElement).shape;return currentShapeApplied===value;}}
class ToggleBgShapeAction extends BaseAnimationAction{static id="toggleBgShape";apply({editingElement}){const previousSibling=editingElement.previousElementSibling;let shapeToSelect;const allPossiblesShapesUrl=Object.keys(this.getBackgroundShapes());if(previousSibling){const previousShape=this.getShapeData(previousSibling).shape;shapeToSelect=allPossiblesShapesUrl.find((shape,i)=>allPossiblesShapesUrl[i-1]===previousShape);}
if(!shapeToSelect){shapeToSelect=allPossiblesShapesUrl[0];}
const showOnMobile=this.config.isMobileView(editingElement);this.createShapeContainer(editingElement,shapeToSelect);const applyShapeParams={shape:shapeToSelect,colors:this.getImplicitColors(editingElement,shapeToSelect),showOnMobile,};this.applyShape(editingElement,()=>applyShapeParams);this.showBackgroundShapes([editingElement]);}
clean({editingElement}){this.applyShape(editingElement,()=>({shape:""}));}
isApplied({editingElement}){return!!this.getShapeData(editingElement).shape;}}
class ShowOnMobileAction extends BaseAnimationAction{static id="showOnMobile";apply({editingElement}){this.applyShape(editingElement,()=>({showOnMobile:false,}));}
clean({editingElement}){this.applyShape(editingElement,()=>({showOnMobile:true,}));}
isApplied({editingElement}){return!this.getShapeData(editingElement).showOnMobile;}}
class FlipShapeAction extends BaseAnimationAction{static id="flipShape";apply({editingElement,params:{mainParam:axis}}){this.applyShape(editingElement,()=>{const flip=new Set(this.getShapeData(editingElement).flip);flip.add(axis);return{flip:[...flip]};});}
clean({editingElement,params:{mainParam:axis}}){this.applyShape(editingElement,()=>{const flip=new Set(this.getShapeData(editingElement).flip);flip.delete(axis);return{flip:[...flip]};});}
isApplied({editingElement,params:{mainParam:axis}}){const selector=`.o_we_flip_${axis}`;const hasFlipClass=!!editingElement.querySelector(`:scope > .o_we_shape${selector}`);return hasFlipClass||this.getShapeData(editingElement).flip.includes(axis);}}
class SetBgAnimationSpeedAction extends BaseAnimationAction{static id="setBgAnimationSpeed";apply({editingElement,value}){this.applyShape(editingElement,()=>({shapeAnimationSpeed:value,}));}
getValue({editingElement}){return this.getShapeData(editingElement).shapeAnimationSpeed;}}
class BackgroundShapeColorAction extends BaseAnimationAction{static id="backgroundShapeColor";getValue({editingElement,params:{mainParam:colorName}}){const{shape,colors:customColors}=this.getShapeData(editingElement);const colors=Object.assign(getDefaultColors(editingElement),customColors);const color=shape&&colors[colorName];return(color&&normalizeColor(color,getHtmlStyle(this.document)))||"";}
apply({editingElement,params:{mainParam:colorName},value}){this.applyShape(editingElement,()=>{value=getValueFromVar(value);const{colors:previousColors}=this.getShapeData(editingElement);const newColor=value||getDefaultColors(editingElement)[colorName];const newColors=Object.assign(previousColors,{[colorName]:newColor});return{colors:newColors};});}}
registry.category("builder-plugins").add(BackgroundShapeOptionPlugin.id,BackgroundShapeOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/background_option/background_shapes_definition.js */
odoo.define('@html_builder/plugins/background_option/background_shapes_definition',['@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const backgroundShapesDefinition=__exports.backgroundShapesDefinition={basic:{label:_t("Basic"),subgroups:{connections:{label:_t("Connections"),shapes:{"html_builder/Connections/01":{selectLabel:_t("Connections 01")},"html_builder/Connections/02":{selectLabel:_t("Connections 02")},"html_builder/Connections/03":{selectLabel:_t("Connections 03")},"html_builder/Connections/04":{selectLabel:_t("Connections 04")},"html_builder/Connections/05":{selectLabel:_t("Connections 05")},"html_builder/Connections/06":{selectLabel:_t("Connections 06")},"html_builder/Connections/07":{selectLabel:_t("Connections 07")},"html_builder/Connections/08":{selectLabel:_t("Connections 08")},"html_builder/Connections/09":{selectLabel:_t("Connections 09")},"html_builder/Connections/10":{selectLabel:_t("Connections 10")},"html_builder/Connections/11":{selectLabel:_t("Connections 11")},"html_builder/Connections/12":{selectLabel:_t("Connections 12")},"html_builder/Connections/13":{selectLabel:_t("Connections 13")},"html_builder/Connections/14":{selectLabel:_t("Connections 14")},"html_builder/Connections/15":{selectLabel:_t("Connections 15")},"html_builder/Connections/16":{selectLabel:_t("Connections 16")},"html_builder/Connections/17":{selectLabel:_t("Connections 17")},"html_builder/Connections/18":{selectLabel:_t("Connections 18")},"html_builder/Connections/19":{selectLabel:_t("Connections 19")},"html_builder/Connections/20":{selectLabel:_t("Connections 20")},},},containers:{label:_t("Containers"),shapes:{"html_builder/Containers/01":{selectLabel:_t("Container 01")},"html_builder/Containers/02":{selectLabel:_t("Container 02")},"html_builder/Containers/03":{selectLabel:_t("Container 03")},"html_builder/Containers/04":{selectLabel:_t("Container 04")},"html_builder/Containers/05":{selectLabel:_t("Container 05"),animated:true,},"html_builder/Containers/06":{selectLabel:_t("Container 06"),animated:true,},},},bold:{label:_t("Bold"),shapes:{"html_builder/Bold/16":{selectLabel:_t("Bold 01")},"html_builder/Bold/21":{selectLabel:_t("Bold 02")},"html_builder/Bold/17":{selectLabel:_t("Bold 03")},"html_builder/Bold/22":{selectLabel:_t("Bold 04")},"html_builder/Bold/13":{selectLabel:_t("Bold 05")},"html_builder/Bold/14":{selectLabel:_t("Bold 06")},"html_builder/Bold/15":{selectLabel:_t("Bold 07")},"html_builder/Bold/01_001":{selectLabel:_t("Bold 08")},"html_builder/Bold/18":{selectLabel:_t("Bold 09")},"html_builder/Bold/19":{selectLabel:_t("Bold 10")},"html_builder/Bold/23":{selectLabel:_t("Bold 11")},"html_builder/Bold/20":{selectLabel:_t("Bold 12")},},},angular:{label:_t("Angular"),shapes:{"html_builder/Angular/01":{selectLabel:_t("Angular 01")},"html_builder/Angular/02":{selectLabel:_t("Angular 02")},"html_builder/Angular/03":{selectLabel:_t("Angular 03")},"html_builder/Angular/04":{selectLabel:_t("Angular 04")},"html_builder/Angular/05":{selectLabel:_t("Angular 05")},"html_builder/Angular/06":{selectLabel:_t("Angular 06")},"html_builder/Angular/07":{selectLabel:_t("Angular 07")},"html_builder/Angular/08":{selectLabel:_t("Angular 08")},"html_builder/Angular/09":{selectLabel:_t("Angular 09")},"html_builder/Floats/07":{selectLabel:_t("Angular 10"),animated:true},},},blobs:{label:_t("Blobs"),shapes:{"html_builder/Blobs/02":{selectLabel:_t("Blob 01")},"html_builder/Blobs/05_001":{selectLabel:_t("Blob 02")},"html_builder/Blobs/03":{selectLabel:_t("Blob 03")},"html_builder/Blobs/06_001":{selectLabel:_t("Blob 04")},"html_builder/Blobs/14":{selectLabel:_t("Blob 05")},"html_builder/Blobs/17":{selectLabel:_t("Blob 06")},"html_builder/Blobs/15":{selectLabel:_t("Blob 07")},"html_builder/Blobs/18":{selectLabel:_t("Blob 08")},"html_builder/Blobs/01_001":{selectLabel:_t("Blob 09"),animated:true},"html_builder/Blobs/16":{selectLabel:_t("Blob 10")},"html_builder/Blobs/04_001":{selectLabel:_t("Blob 11")},"html_builder/Blobs/10_002":{selectLabel:_t("Blob 12")},"html_builder/Blobs/13":{selectLabel:_t("Blob 13")},"html_builder/Floats/03":{selectLabel:_t("Blob 14"),animated:true},"html_builder/Floats/04":{selectLabel:_t("Blob 15"),animated:true},"html_builder/Floats/06":{selectLabel:_t("Blob 16"),animated:true},},},},},linear:{label:_t("Linear"),subgroups:{airy:{label:_t("Airy"),shapes:{"html_builder/Airy/01_001":{selectLabel:_t("Airy 01")},"html_builder/Airy/06_001":{selectLabel:_t("Airy 02")},"html_builder/Airy/02_001":{selectLabel:_t("Airy 03")},"html_builder/Airy/07_001":{selectLabel:_t("Airy 04")},"html_builder/Airy/08_001":{selectLabel:_t("Airy 05")},"html_builder/Airy/10_001":{selectLabel:_t("Airy 06")},"html_builder/Airy/09_001":{selectLabel:_t("Airy 07")},"html_builder/Airy/11_001":{selectLabel:_t("Airy 08")},"html_builder/Airy/16":{selectLabel:_t("Airy 09")},"html_builder/Airy/17":{selectLabel:_t("Airy 10")},"html_builder/Airy/12_002":{selectLabel:_t("Airy 11"),animated:true},"html_builder/Airy/13_002":{selectLabel:_t("Airy 12"),animated:true},"html_builder/Airy/14_001":{selectLabel:_t("Airy 13")},"html_builder/Airy/15":{selectLabel:_t("Airy 14"),animated:true},},},grids:{label:_t("Grids"),shapes:{"html_builder/Grids/01":{selectLabel:_t("Grid 01")},"html_builder/Grids/02":{selectLabel:_t("Grid 02")},"html_builder/Grids/03":{selectLabel:_t("Grid 03")},"html_builder/Grids/04":{selectLabel:_t("Grid 04")},"html_builder/Grids/05":{selectLabel:_t("Grid 05")},"html_builder/Grids/06":{selectLabel:_t("Grid 06")},"html_builder/Grids/07":{selectLabel:_t("Grid 07")},"html_builder/Grids/08":{selectLabel:_t("Grid 08")},},},},},creative:{label:_t("Creative"),subgroups:{patterns:{label:_t("Patterns"),shapes:{"html_builder/Patterns/01":{selectLabel:_t("Pattern 01")},"html_builder/Patterns/02":{selectLabel:_t("Pattern 02")},"html_builder/Patterns/03":{selectLabel:_t("Pattern 03")},"html_builder/Patterns/04":{selectLabel:_t("Pattern 04")},"html_builder/Patterns/05":{selectLabel:_t("Pattern 05")},"html_builder/Floats/12":{selectLabel:_t("Pattern 06"),animated:true},},},blurry:{label:_t("Blurry"),shapes:{"html_builder/Blurry/01":{selectLabel:_t("Blurry 01")},"html_builder/Blurry/02":{selectLabel:_t("Blurry 02")},"html_builder/Blurry/03":{selectLabel:_t("Blurry 03")},"html_builder/Blurry/04":{selectLabel:_t("Blurry 04")},"html_builder/Blurry/05":{selectLabel:_t("Blurry 05")},"html_builder/Blurry/06":{selectLabel:_t("Blurry 06")},},},wavy:{label:_t("Wavy"),shapes:{"html_builder/Wavy/03":{selectLabel:_t("Wavy 01")},"html_builder/Wavy/10":{selectLabel:_t("Wavy 02")},"html_builder/Wavy/24":{selectLabel:_t("Wavy 03"),animated:true},"html_builder/Wavy/26":{selectLabel:_t("Wavy 04"),animated:true},"html_builder/Wavy/27":{selectLabel:_t("Wavy 05"),animated:true},"html_builder/Wavy/04":{selectLabel:_t("Wavy 06")},"html_builder/Wavy/11_001":{selectLabel:_t("Wavy 07")},"html_builder/Wavy/18":{selectLabel:_t("Wavy 08")},"html_builder/Wavy/08_001":{selectLabel:_t("Wavy 09")},"html_builder/Wavy/09_001":{selectLabel:_t("Wavy 10")},"html_builder/Wavy/22_001":{selectLabel:_t("Wavy 11")},"html_builder/Wavy/29":{selectLabel:_t("Wavy 12")},"html_builder/Wavy/30":{selectLabel:_t("Wavy 13")},"html_builder/Wavy/31":{selectLabel:_t("Wavy 14")},},},blockAndRainy:{label:_t("Block & Rainy"),shapes:{"html_builder/Blocks/02_001":{selectLabel:_t("Blocks 01")},"html_builder/Rainy/01_001":{selectLabel:_t("Rainy 01"),animated:true},"html_builder/Blocks/01_001":{selectLabel:_t("Blocks 02")},"html_builder/Rainy/02_001":{selectLabel:_t("Rainy 02"),animated:true},"html_builder/Rainy/06":{selectLabel:_t("Rainy 03")},"html_builder/Blocks/04":{selectLabel:_t("Blocks 03")},"html_builder/Rainy/07":{selectLabel:_t("Rainy 04")},"html_builder/Rainy/10":{selectLabel:_t("Rainy 05"),animated:true},"html_builder/Floats/10":{selectLabel:_t("Rainy 06"),animated:true},"html_builder/Floats/11":{selectLabel:_t("Rainy 07"),animated:true},"html_builder/Rainy/08_001":{selectLabel:_t("Rainy 08"),animated:true},"html_builder/Rainy/09_001":{selectLabel:_t("Rainy 09")},},},miscellaneous:{label:_t("Miscellaneous"),shapes:{"html_builder/Floats/01":{selectLabel:_t("Miscellaneous 01"),animated:true,},"html_builder/Floats/02":{selectLabel:_t("Miscellaneous 02"),animated:true,},"html_builder/Floats/05":{selectLabel:_t("Miscellaneous 03"),animated:true,},"html_builder/Floats/08":{selectLabel:_t("Miscellaneous 04"),animated:true,},"html_builder/Floats/09":{selectLabel:_t("Miscellaneous 05"),animated:true,},"html_builder/Floats/13":{selectLabel:_t("Miscellaneous 06"),animated:true,},"html_builder/Floats/14":{selectLabel:_t("Miscellaneous 07"),animated:true,},"html_builder/Zigs/01_001":{selectLabel:_t("Miscellaneous 08"),animated:true,},},},},},};return __exports;});;

/* /html_builder/static/src/plugins/badge_option_plugin.js */
odoo.define('@html_builder/plugins/badge_option_plugin',['@html_builder/utils/option_sequence','@html_editor/plugin','@html_editor/utils/resource','@web/core/registry','@html_builder/core/utils'],function(require){'use strict';let __exports={};const{ANIMATE,before}=require("@html_builder/utils/option_sequence");const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{registry}=require("@web/core/registry");const{BaseOptionComponent}=require("@html_builder/core/utils");const BadgeOption=__exports.BadgeOption=class BadgeOption extends BaseOptionComponent{static template="html_builder.BadgeOption";static selector=".s_badge";}
class BadgeOptionPlugin extends Plugin{static id="badgeOption";resources={builder_options:[withSequence(before(ANIMATE),BadgeOption)],so_content_addition_selector:[".s_badge"],unsplittable_node_predicates:(node)=>node.classList?.contains("s_badge"),};}
registry.category("builder-plugins").add(BadgeOptionPlugin.id,BadgeOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/base_vertical_alignment_option.js */
odoo.define('@html_builder/plugins/base_vertical_alignment_option',['@html_builder/core/utils'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const BaseVerticalAlignmentOption=__exports.BaseVerticalAlignmentOption=class BaseVerticalAlignmentOption extends BaseOptionComponent{static template="html_builder.VerticalAlignmentOption";level=1;justify=true;}
return __exports;});;

/* /html_builder/static/src/plugins/block_alignment_option_plugin.js */
odoo.define('@html_builder/plugins/block_alignment_option_plugin',['@html_editor/plugin','@web/core/registry','@html_editor/utils/resource','@html_builder/utils/option_sequence','@html_builder/core/utils'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{withSequence}=require("@html_editor/utils/resource");const{BLOCK_ALIGN}=require("@html_builder/utils/option_sequence");const{BaseOptionComponent}=require("@html_builder/core/utils");class BlockAlignmentOptionPlugin extends Plugin{static id="blockAlignmentOption";resources={builder_options:[withSequence(BLOCK_ALIGN,BlockAlignmentOption)],};}
const BlockAlignmentOption=__exports.BlockAlignmentOption=class BlockAlignmentOption extends BaseOptionComponent{static template="html_builder.BlockAlignmentOption";static selector=".s_alert, .s_blockquote, .s_text_highlight";}
registry.category("builder-plugins").add(BlockAlignmentOptionPlugin.id,BlockAlignmentOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/border_configurator_option.js */
odoo.define('@html_builder/plugins/border_configurator_option',['@html_builder/core/utils'],function(require){'use strict';let __exports={};const{BaseOptionComponent,useDomState}=require("@html_builder/core/utils");const BorderConfigurator=__exports.BorderConfigurator=class BorderConfigurator extends BaseOptionComponent{static template="html_builder.BorderConfiguratorOption";static dependencies=["builderActions"];static props={label:{type:String},direction:{type:String,optional:true},withRoundCorner:{type:Boolean,optional:true},withBSClass:{type:Boolean,optional:true},action:{type:String,optional:true},};static defaultProps={withRoundCorner:true,withBSClass:true,action:"styleAction",};setup(){super.setup();this.state=useDomState((editingElement)=>({hasBorder:this.hasBorder(editingElement),}));}
getStyleActionParam(param){const property=`border-${this.props.direction ? this.props.direction + "-" : ""}${param}`;if(this.props.withBSClass&&(param==="width"||param==="radius")){return`--box-${property}`;}
return property;}
hasBorder(editingElement){const{getAction}=this.dependencies.builderActions;const styleActionValue=getAction("styleAction").getValue({editingElement,params:{mainParam:this.getStyleActionParam("width"),},});const values=(styleActionValue||"0").match(/\d+/g);return values.some((value)=>parseInt(value)>0);}}
return __exports;});;

/* /html_builder/static/src/plugins/cta_badge_option_plugin.js */
odoo.define('@html_builder/plugins/cta_badge_option_plugin',['@html_builder/core/utils','@html_builder/plugins/border_configurator_option','@html_builder/plugins/shadow_option','@html_editor/plugin','@web/core/registry'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const{BorderConfigurator}=require("@html_builder/plugins/border_configurator_option");const{ShadowOption}=require("@html_builder/plugins/shadow_option");const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const CTABadgeOption=__exports.CTABadgeOption=class CTABadgeOption extends BaseOptionComponent{static template="html_builder.CTABadgeOption";static selector=".s_cta_badge";static components={BorderConfigurator,ShadowOption};}
class CTABadgeOptionPlugin extends Plugin{static id="ctaBadgeOption";resources={builder_options:[CTABadgeOption],so_content_addition_selector:[".s_cta_badge"],};}
registry.category("builder-plugins").add(CTABadgeOptionPlugin.id,CTABadgeOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/date_time_field_plugin.js */
odoo.define('@html_builder/plugins/date_time_field_plugin',['@html_editor/plugin','@web/core/registry'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");class DateTimeFieldPlugin extends Plugin{static id="dateTimeField";resources={content_not_editable_selectors:["[data-oe-field][data-oe-type=date]","[data-oe-field][data-oe-type=datetime]",],};}
registry.category("builder-plugins").add(DateTimeFieldPlugin.id,DateTimeFieldPlugin);return __exports;});;

/* /html_builder/static/src/plugins/font/font_plugin.js */
odoo.define('@html_builder/plugins/font/font_plugin',['@html_editor/plugin','@html_editor/utils/formatting','@web/core/registry','@web/core/l10n/translation','@web/core/utils/cache','@web/core/assets','@html_builder/plugins/font/font_size_selector','@html_editor/utils/resource'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{getCSSVariableValue,getHtmlStyle}=require("@html_editor/utils/formatting");const{registry}=require("@web/core/registry");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{Cache}=require("@web/core/utils/cache");const{loadCSS}=require("@web/core/assets");const{BuilderFontSizeSelector}=require("@html_builder/plugins/font/font_size_selector");const{withSequence}=require("@html_editor/utils/resource");const BuilderFontPlugin=__exports.BuilderFontPlugin=class BuilderFontPlugin extends Plugin{static id="builderFont";static shared=["getFontsCache","getFontsData"];static dependencies=["toolbar"];resources={fontCssVariables:["font","headings-font","h2-font","h3-font","h4-font","h5-font","h6-font","display-1-font","display-2-font","display-3-font","display-4-font","buttons-font",],font_items:[...[{name:_t("Header 1 Display 2"),tagName:"h1",extraClass:"display-2"},{name:_t("Header 1 Display 3"),tagName:"h1",extraClass:"display-3"},{name:_t("Header 1 Display 4"),tagName:"h1",extraClass:"display-4"},].map((item)=>withSequence(15,item)),withSequence(43,{name:_t("Light"),tagName:"p",extraClass:"lead"}),withSequence(46,{name:_t("Small"),tagName:"p",extraClass:"small"}),],};setup(){this.fontsCache=new Cache(this._fetchFonts.bind(this),JSON.stringify);const buttonGroups=this.dependencies.toolbar.getToolbarInfo().buttonGroups;for(const buttonGroup of buttonGroups){if(buttonGroup.id!=="font"){continue;}
for(const button of buttonGroup.buttons){if(button.id==="font-size"){button.Component=BuilderFontSizeSelector;}}}}
destroy(){super.destroy();this.fontsCache.invalidate();}
getFontsCache(){return this.fontsCache;}
async getFontsData(){return this.fontsCache.read({});}
async _fetchFonts(){const style=getHtmlStyle(this.document);const nbFonts=parseInt(getCSSVariableValue("number-of-fonts",style));const googleFontsProperty=getCSSVariableValue("google-fonts",style);let googleFonts=googleFontsProperty?googleFontsProperty.split(/\s*,\s*/g):[];googleFonts=googleFonts.map((font)=>font.substring(1,font.length-1));const googleLocalFontsProperty=getCSSVariableValue("google-local-fonts",style);const googleLocalFonts=googleLocalFontsProperty?googleLocalFontsProperty.slice(1,-1).split(/\s*,\s*/g):[];const uploadedLocalFontsProperty=getCSSVariableValue("uploaded-local-fonts",style);const uploadedLocalFonts=uploadedLocalFontsProperty?uploadedLocalFontsProperty.slice(1,-1).split(/\s*,\s*/g):[];googleFonts=googleFonts.filter((font)=>{const localFonts=googleLocalFonts.map((localFont)=>localFont.split(":")[0]);return localFonts.indexOf(`'${font}'`)===-1;});const allFonts=[];const fontsToLoad=[];for(const font of googleFonts){const fontURL=`https://fonts.googleapis.com/css?family=${encodeURIComponent(
                font
            ).replace(/%20/g, "+")}:300,300i,400,400i,700,700i`;fontsToLoad.push(fontURL);}
for(const font of googleLocalFonts){const attachmentId=font.split(/\s*:\s*/)[1];const fontURL=`/web/content/${encodeURIComponent(attachmentId)}`;fontsToLoad.push(fontURL);}
const proms=fontsToLoad.map(async(fontURL)=>loadCSS(fontURL));const _fonts=[];const themeFontsNb=nbFonts-(googleLocalFonts.length+googleFonts.length+uploadedLocalFonts.length);const localFontsOffset=nbFonts-googleLocalFonts.length-uploadedLocalFonts.length;const uploadedFontsOffset=nbFonts-uploadedLocalFonts.length;for(let fontNb=0;fontNb<nbFonts;fontNb++){const realFontNb=fontNb+1;const fontKey=getCSSVariableValue(`font-number-${realFontNb}`,style);allFonts.push(fontKey);let fontName=fontKey.slice(1,-1);const fontFamilyValue=`'${fontName}'`;let styleFontFamily=fontName;const isSystemFonts=fontName==="SYSTEM_FONTS";if(isSystemFonts){fontName=_t("System Fonts");styleFontFamily="var(--o-system-fonts)";}
let type=isSystemFonts?"system":"cloud";let indexForType=fontNb-themeFontsNb;if(fontNb>=localFontsOffset){if(fontNb<uploadedFontsOffset){type="google";indexForType=fontNb-localFontsOffset;}else{type="uploaded";indexForType=fontNb-uploadedFontsOffset;}}
_fonts.push({type,indexForType,fontFamilyValue,styleFontFamily,string:fontName,});}
await Promise.all(proms);return{allFonts,googleFonts,googleLocalFonts,uploadedLocalFonts,_fonts,};}}
registry.category("builder-plugins").add(BuilderFontPlugin.id,BuilderFontPlugin);return __exports;});;

/* /html_builder/static/src/plugins/font/font_size_selector.js */
odoo.define('@html_builder/plugins/font/font_size_selector',['@html_editor/main/font/font_size_selector'],function(require){'use strict';let __exports={};const{FontSizeSelector}=require("@html_editor/main/font/font_size_selector");const BuilderFontSizeSelector=__exports.BuilderFontSizeSelector=class BuilderFontSizeSelector extends FontSizeSelector{static template="html_builder.FontSizeSelector";setup(){super.setup();this.fontSizeTags={"display-1-font-size":"Display 1","display-2-font-size":"Display 2","display-3-font-size":"Display 3","display-4-font-size":"Display 4","h1-font-size":"Heading 1","h2-font-size":"Heading 2","h3-font-size":"Heading 3","h4-font-size":"Heading 4","h5-font-size":"Heading 5","h6-font-size":"Normal","font-size-base":"Normal","small-font-size":"Small",};}}
return __exports;});;

/* /html_builder/static/src/plugins/image/image_filter_option.js */
odoo.define('@html_builder/plugins/image/image_filter_option',['@html_builder/core/utils','@html_builder/utils/image','@html_editor/main/media/image_post_process_plugin','@html_editor/utils/image_processing','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{BaseOptionComponent,useDomState}=require("@html_builder/core/utils");const{getMimetypeBeforeShape}=require("@html_builder/utils/image");const{isImageSupportedForProcessing}=require("@html_editor/main/media/image_post_process_plugin");const{isWebGLEnabled}=require("@html_editor/utils/image_processing");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const ImageFilterOption=__exports.ImageFilterOption=class ImageFilterOption extends BaseOptionComponent{static template="html_builder.ImageFilterOption";static props={level:{type:Number,optional:true},};static defaultProps={level:0,};setup(){super.setup();this.state=useDomState(async(editingElement)=>{const canUseGlFilter=isWebGLEnabled();const mimetype=await getMimetypeBeforeShape(editingElement);const showFilter=await isImageSupportedForProcessing(editingElement,mimetype);return{isCustomFilter:editingElement.dataset.glFilter==="custom",showFilter,disableFilter:!canUseGlFilter,tooltip:!canUseGlFilter?_t("WebGL is not enabled on your browser."):undefined,};});}}
return __exports;});;

/* /html_builder/static/src/plugins/image/image_filter_option_plugin.js */
odoo.define('@html_builder/plugins/image/image_filter_option_plugin',['@html_builder/core/builder_action','@html_builder/utils/utils_css','@html_editor/main/media/image_post_process_plugin','@html_editor/plugin','@html_editor/utils/formatting','@web/core/registry'],function(require){'use strict';let __exports={};const{BuilderAction}=require("@html_builder/core/builder_action");const{normalizeColor}=require("@html_builder/utils/utils_css");const{defaultImageFilterOptions}=require("@html_editor/main/media/image_post_process_plugin");const{Plugin}=require("@html_editor/plugin");const{getHtmlStyle}=require("@html_editor/utils/formatting");const{registry}=require("@web/core/registry");class ImageFilterOptionPlugin extends Plugin{static id="ImageFilterOption";resources={builder_actions:{GlFilterAction,SetCustomFilterAction,},};}
const GlFilterAction=__exports.GlFilterAction=class GlFilterAction extends BuilderAction{static id="glFilter";static dependencies=["imagePostProcess"];isApplied({editingElement,params:{mainParam:glFilterName}}){if(glFilterName){return editingElement.dataset.glFilter===glFilterName;}else{return!editingElement.dataset.glFilter;}}
async load({editingElement:img,params:{mainParam:glFilterName}}){return await this.dependencies.imagePostProcess.processImage({img,newDataset:{glFilter:glFilterName,},});}
apply({loadResult:updateImageAttributes}){updateImageAttributes();}}
const SetCustomFilterAction=__exports.SetCustomFilterAction=class SetCustomFilterAction extends BuilderAction{static id="setCustomFilter";static dependencies=["imagePostProcess"];getValue({editingElement,params:{mainParam:filterProperty}}){const filterOptions=JSON.parse(editingElement.dataset.filterOptions||"{}");return filterOptions[filterProperty]||defaultImageFilterOptions[filterProperty];}
isApplied({editingElement,params:{mainParam:filterProperty},value:filterValue}){const filterOptions=JSON.parse(editingElement.dataset.filterOptions||"{}");return(filterValue===(filterOptions[filterProperty]||defaultImageFilterOptions[filterProperty]));}
async load({editingElement:img,params:{mainParam:filterProperty},value}){const filterOptions=JSON.parse(img.dataset.filterOptions||"{}");filterOptions[filterProperty]=filterProperty==="filterColor"?normalizeColor(value,getHtmlStyle(this.document)):value;return this.dependencies.imagePostProcess.processImage({img,newDataset:{filterOptions:JSON.stringify(filterOptions),},});}
apply({loadResult:updateImageAttributes}){updateImageAttributes();}}
registry.category("builder-plugins").add(ImageFilterOptionPlugin.id,ImageFilterOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/image/image_format_option.js */
odoo.define('@html_builder/plugins/image/image_format_option',['@html_builder/core/utils','@html_builder/utils/image','@html_editor/main/media/image_post_process_plugin','@html_editor/utils/image','@web/core/utils/numbers'],function(require){'use strict';let __exports={};const{BaseOptionComponent,useDomState}=require("@html_builder/core/utils");const{getMimetypeBeforeShape}=require("@html_builder/utils/image");const{isImageSupportedForProcessing}=require("@html_editor/main/media/image_post_process_plugin");const{getImageSrc}=require("@html_editor/utils/image");const{clamp}=require("@web/core/utils/numbers");const ImageFormatOption=__exports.ImageFormatOption=class ImageFormatOption extends BaseOptionComponent{static template="html_builder.ImageFormat";static dependencies=["imageFormatOption"];static props={level:{type:Number,optional:true},computeMaxDisplayWidth:{type:Function,optional:true},};static defaultProps={level:0,};MAX_SUGGESTED_WIDTH=1920;setup(){super.setup();const{computeAvailableFormats}=this.dependencies.imageFormatOption;this.state=useDomState(async(editingElement)=>{const formats=await computeAvailableFormats(editingElement,this.computeMaxDisplayWidth.bind(this));const hasSrc=!!getImageSrc(editingElement);const mimetype=await getMimetypeBeforeShape(editingElement);const compressionUnsupported=mimetype==="image/webp"&&this.webpCompressionUnuspported();const showFormat=await isImageSupportedForProcessing(editingElement,mimetype);return{showQuality:["image/jpeg","image/webp"].includes(mimetype),compressionUnsupported:compressionUnsupported,showFormat,formats:hasSrc?formats:[],};});}
computeMaxDisplayWidth(img){if(this.props.computeMaxDisplayWidth){return this.props.computeMaxDisplayWidth(img);}
return computeMaxDisplayWidth(img,this.MAX_SUGGESTED_WIDTH);}
webpCompressionUnuspported(){const canvas=document.createElement("canvas");canvas.width=canvas.height=1;return canvas.toDataURL("image/webp").slice(0,16)!=="data:image/webp;";}}
__exports.computeMaxDisplayWidth=computeMaxDisplayWidth;function computeMaxDisplayWidth(img,MAX_SUGGESTED_WIDTH=1920){const window=img.ownerDocument.defaultView;if(!window){return;}
const computedStyles=window.getComputedStyle(img);const displayWidth=parseFloat(computedStyles.getPropertyValue("width"));const gutterWidth=parseFloat(computedStyles.getPropertyValue("--o-grid-gutter-width"))||30;if(img.closest("nav")){return Math.round(Math.min(displayWidth*3,MAX_SUGGESTED_WIDTH));}else if(img.closest(".container, .o_container_small")){const mdContainerMaxWidth=parseFloat(computedStyles.getPropertyValue("--o-md-container-max-width"))||720;const mdContainerInnerWidth=mdContainerMaxWidth-gutterWidth;return Math.round(clamp(displayWidth,mdContainerInnerWidth,MAX_SUGGESTED_WIDTH));}else if(img.closest(".container-fluid")){const lgBp=parseFloat(computedStyles.getPropertyValue("--breakpoint-lg"))||992;const mdContainerFluidMaxInnerWidth=lgBp-gutterWidth;return Math.round(clamp(displayWidth,mdContainerFluidMaxInnerWidth,MAX_SUGGESTED_WIDTH));}
return Math.round(Math.min(displayWidth*1.5,MAX_SUGGESTED_WIDTH));}
return __exports;});;

/* /html_builder/static/src/plugins/image/image_format_option_plugin.js */
odoo.define('@html_builder/plugins/image/image_format_option_plugin',['@html_builder/core/builder_action','@html_editor/main/media/image_post_process_plugin','@html_editor/plugin','@html_editor/utils/image_processing','@web/core/l10n/translation','@web/core/registry','@html_editor/utils/dom_traversal'],function(require){'use strict';let __exports={};const{BuilderAction}=require("@html_builder/core/builder_action");const{DEFAULT_IMAGE_QUALITY,shouldPreventGifTransformation,}=require("@html_editor/main/media/image_post_process_plugin");const{Plugin}=require("@html_editor/plugin");const{loadImage,loadImageInfo}=require("@html_editor/utils/image_processing");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{registry}=require("@web/core/registry");const{selectElements}=require("@html_editor/utils/dom_traversal");class ImageFormatOptionPlugin extends Plugin{static id="imageFormatOption";static shared=["computeAvailableFormats"];resources={builder_actions:{SetImageFormatAction,SetImageQualityAction,},on_snippet_dropped_handlers:async({snippetEl})=>{for(const imgEl of selectElements(snippetEl,"img:not([data-mimetype]), .oe_img_bg:not([data-mimetype])")){const info=await loadImageInfo(imgEl);imgEl.dataset.mimetype=info.mimetypeBeforeConversion;}},};async computeAvailableFormats(img,computeMaxDisplayWidth){const data={...img.dataset,...(await loadImageInfo(img))};if(!data.mimetypeBeforeConversion||shouldPreventGifTransformation(data)){return[];}
const maxWidth=await this.getImageWidth(data.originalSrc,data.width);const optimizedWidth=Math.min(maxWidth,computeMaxDisplayWidth?.(img)||0);const widths={128:["128px",this.config.defaultImageMimetype??"image/webp"],256:["256px",this.config.defaultImageMimetype??"image/webp"],512:["512px",this.config.defaultImageMimetype??"image/webp"],1024:["1024px",this.config.defaultImageMimetype??"image/webp"],1920:["1920px",this.config.defaultImageMimetype??"image/webp"],};widths[img.naturalWidth]=[_t("%spx",img.naturalWidth),this.config.defaultImageMimetype??"image/webp",];widths[optimizedWidth]=[_t("%spx (Suggested)",optimizedWidth),this.config.defaultImageMimetype??"image/webp",];const mimetypeBeforeConversion=data.mimetypeBeforeConversion;widths[maxWidth]=[_t("%spx (Original)",maxWidth),mimetypeBeforeConversion,true];if(mimetypeBeforeConversion!==(this.config.defaultImageMimetype??"image/webp")){widths[maxWidth-0.1]=[_t("%spx",maxWidth),this.config.defaultImageMimetype??"image/webp",];}
return Object.entries(widths).filter(([width])=>width<=maxWidth).sort(([v1],[v2])=>v1-v2).map(([width,[label,mimetype,isOriginal]])=>{const id=`${width}-${mimetype}`;return{id,width:Math.round(width),label,mimetype,isOriginal};});}
async getImageWidth(originalSrc,width){const getNaturalWidth=()=>loadImage(originalSrc).then((i)=>i.naturalWidth);return width?Math.round(width):await getNaturalWidth();}}
const SetImageFormatAction=__exports.SetImageFormatAction=class SetImageFormatAction extends BuilderAction{static id="setImageFormat";static dependencies=["imagePostProcess"];isApplied({editingElement,params:{width,mimetype,isOriginal}}){const isOriginalUntouched=(!editingElement.dataset.resizeWidth||!editingElement.dataset.formatMimetype)&&isOriginal;return(isOriginalUntouched||(editingElement.dataset.resizeWidth===String(width)&&editingElement.dataset.formatMimetype===mimetype));}
async load({editingElement:img,params:{width,mimetype}}){return this.dependencies.imagePostProcess.processImage({img,newDataset:{resizeWidth:width,formatMimetype:mimetype,},});}
apply({loadResult:updateImageAttributes}){updateImageAttributes();}}
const SetImageQualityAction=__exports.SetImageQualityAction=class SetImageQualityAction extends BuilderAction{static id="setImageQuality";static dependencies=["imagePostProcess"];getValue({editingElement:img}){return("quality"in img.dataset&&img.dataset.quality)||DEFAULT_IMAGE_QUALITY;}
async load({editingElement:img,value:quality}){return this.dependencies.imagePostProcess.processImage({img,newDataset:{quality,},});}
apply({loadResult:updateImageAttributes}){updateImageAttributes();}}
registry.category("builder-plugins").add(ImageFormatOptionPlugin.id,ImageFormatOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/image/image_helpers.js */
odoo.define('@html_builder/plugins/image/image_helpers',[],function(require){'use strict';let __exports={};__exports.getShapeURL=getShapeURL;function getShapeURL(shapeName){const[module,directory,fileName]=shapeName.split("/");return`/${encodeURIComponent(module)}/static/image_shapes/${encodeURIComponent(
        directory
    )}/${encodeURIComponent(fileName)}.svg`;}
return __exports;});;

/* /html_builder/static/src/plugins/image/image_shape_option.js */
odoo.define('@html_builder/plugins/image/image_shape_option',['@html_builder/core/utils','@html_builder/utils/utils','@web/core/l10n/translation','@html_builder/plugins/shape/shape_selector','@web/core/utils/objects','@html_editor/utils/image_processing','@html_editor/main/media/image_post_process_plugin','@html_builder/utils/image'],function(require){'use strict';let __exports={};const{BaseOptionComponent,useDomState}=require("@html_builder/core/utils");const{toRatio}=require("@html_builder/utils/utils");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{ShapeSelector}=require("@html_builder/plugins/shape/shape_selector");const{deepCopy}=require("@web/core/utils/objects");const{loadImageInfo}=require("@html_editor/utils/image_processing");const{isImageSupportedForProcessing}=require("@html_editor/main/media/image_post_process_plugin");const{getMimetypeBeforeShape}=require("@html_builder/utils/image");const ImageShapeOption=__exports.ImageShapeOption=class ImageShapeOption extends BaseOptionComponent{static template="html_builder.ImageShapeOption";static dependencies=["customizeTab","imageShapeOption"];static props={withAnimatedShapes:{type:Boolean,optional:true},};static defaultProps={withAnimatedShapes:true,};setup(){super.setup();this.customizeTabPlugin=this.dependencies.customizeTab;this.imageShapeOption=this.dependencies.imageShapeOption;this.toRatio=toRatio;this.state=useDomState(async(editingElement)=>{const{originalSrc}=editingElement.dataset.originalSrc?editingElement.dataset:await loadImageInfo(editingElement);const shape=editingElement.dataset.shape;const mimetype=await getMimetypeBeforeShape(editingElement);const isImgSupportedForProcessing=await isImageSupportedForProcessing(editingElement,mimetype);return{hasShape:!!shape&&!this.imageShapeOption.isTechnicalShape(shape),shapeLabel:this.imageShapeOption.getShapeLabel(shape),showImageShape0:this.isShapeVisible(editingElement,0),showImageShape1:this.isShapeVisible(editingElement,1),showImageShape2:this.isShapeVisible(editingElement,2),showImageShape3:this.isShapeVisible(editingElement,3),showImageShape4:this.isShapeVisible(editingElement,4),showImageShapeTransform:this.imageShapeOption.isTransformableShape(shape),showImageShapeAnimation:this.imageShapeOption.isAnimableShape(shape),togglableRatio:this.imageShapeOption.isTogglableRatioShape(shape)&&isImgSupportedForProcessing,hasShapeTransformation:!!editingElement.dataset.shapeFlip||!!parseInt(editingElement.dataset.shapeRotate),isShapeSupported:!!originalSrc,};});}
getFilteredGroups(){if(this.props.withAnimatedShapes){return this.imageShapeOption.getImageShapeGroups();}
const allDefinitions=deepCopy(this.imageShapeOption.getImageShapeGroups());for(const[dName,definition]of Object.entries(allDefinitions)){for(const[gName,subgroup]of Object.entries(definition.subgroups)){for(const[sName,shape]of Object.entries(subgroup.shapes)){if(shape.animated){delete subgroup.shapes[sName];}}
if(Object.keys(subgroup.shapes).length===0){delete definition.subgroups[gName];}}
if(Object.keys(definition.subgroups).length===0){delete allDefinitions[dName];}}
return allDefinitions;}
isShapeVisible(img,shapeIndex){const shapeName=img.dataset.shape;const shapeColors=img.dataset.shapeColors;if(!shapeName||!shapeColors){return false;}
const colors=img.dataset.shapeColors.split(";");return colors[shapeIndex];}
showImageShapes(){this.customizeTabPlugin.openCustomizeComponent(ShapeSelector,this.env.getEditingElements(),{shapeActionId:"setImageShape",buttonWrapperClassName:"o-hb-img-shape-btn",selectorTitle:_t("Shapes"),shapeGroups:this.getFilteredGroups(),});}}
return __exports;});;

/* /html_builder/static/src/plugins/image/image_shape_option_plugin.js */
odoo.define('@html_builder/plugins/image/image_shape_option_plugin',['@html_editor/plugin','@web/core/registry','@html_editor/utils/color','@html_builder/plugins/image/image_helpers','@html_editor/utils/image_processing','@html_builder/utils/utils','@html_builder/plugins/image/image_shapes_definition','@html_editor/main/media/image_post_process_plugin','@web/core/l10n/translation','@html_builder/core/builder_action','@html_editor/utils/image','@html_editor/utils/resource','@web/core/utils/objects','@html_builder/utils/image'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{DEFAULT_PALETTE}=require("@html_editor/utils/color");const{getShapeURL}=require("@html_builder/plugins/image/image_helpers");const{activateCropper,createDataURL,cropperDataFields,loadImage,loadImageInfo,isGif,}=require("@html_editor/utils/image_processing");const{getValueFromVar}=require("@html_builder/utils/utils");const{imageShapeDefinitions}=require("@html_builder/plugins/image/image_shapes_definition");const{getImageTransformationData,shouldPreventGifTransformation,}=require("@html_editor/main/media/image_post_process_plugin");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{BuilderAction}=require("@html_builder/core/builder_action");const{getFetchedMimetype,getMimetype}=require("@html_editor/utils/image");const{withSequence}=require("@html_editor/utils/resource");const{deepCopy,deepMerge}=require("@web/core/utils/objects");const{handleImagesIfDataset}=require("@html_builder/utils/image");const CSS_ANIMATION_RULE_REGEX=/(?<declaration>animation(?:-duration)?:\s*.*?)(?<value>(?:\d+(?:\.\d+)?)|(?:\.\d+))(?<unit>ms|s)(?<separator>\s|;|"|$)/gm;const SVG_DUR_TIMECOUNT_VAL_REGEX=/(?<attribute_name>\sdur="\s*)(?<value>(?:\d+(?:\.\d+)?)|(?:\.\d+))(?<unit>h|min|ms|s)?\s*"/gm;const CSS_ANIMATION_RATIO_REGEX=/(--animation_ratio: (?<ratio>\d*(\.\d+)?));/m;const ImageShapeOptionPlugin=__exports.ImageShapeOptionPlugin=class ImageShapeOptionPlugin extends Plugin{static id="imageShapeOption";static dependencies=["history","userCommand","imagePostProcess","imageToolOption"];static shared=["getImageShapeGroups","isTransformableShape","isTechnicalShape","isAnimableShape","isTogglableRatioShape","getShapeLabel","loadShape",];resources={builder_actions:{SetImageShapeAction,SetImgShapeColorAction,FlipImageShapeAction,RotateImageShapeAction,SetImageShapeSpeedAction,ResetImageShapeTransformationAction,ToggleImageShapeRatioAction,},process_image_warmup_handlers:this.processImageWarmup.bind(this),process_image_post_handlers:this.processImagePost.bind(this),hover_effect_allowed_predicates:(el)=>this.canHaveHoverEffect(el),image_shape_groups_providers:withSequence(0,()=>deepCopy(imageShapeDefinitions)),on_media_dialog_saved_handlers:withSequence(5,this.onMediaDialogSavedHandlers.bind(this)),};setup(){this.shapeSvgTextCache={};this.imageShapes=this.makeImageShapes();for(const shapeId of Object.keys(this.imageShapes)){const oldShapeId=shapeId.replace("html_builder","web_editor");this.imageShapes[oldShapeId]=this.imageShapes[shapeId];}}
async onMediaDialogSavedHandlers(elements,{node}){const callback=async function(toProcessEl,nodeEl){const data=await loadImageInfo(toProcessEl);if(!data.originalSrc){return;}
toProcessEl.dataset.shape=nodeEl.dataset.shape;for(const shapeInfo of["shapeColors","shapeFlip","shapeRotate"]){if(nodeEl.dataset[shapeInfo]){toProcessEl.dataset[shapeInfo]=nodeEl.dataset[shapeInfo];}}};await handleImagesIfDataset(elements,node,"shape",callback);}
async canHaveHoverEffect(imgEl){const dataset=Object.assign({},imgEl.dataset,await loadImageInfo(imgEl));const isImageSupportedForShapes=await this.asyncIsImageSupportedForShapes(imgEl,dataset);return(imgEl.tagName==="IMG"&&!this.isDeviceShape(imgEl)&&!this.isAnimableShape(dataset.shape)&&isImageSupportedForShapes);}
isDeviceShape(img){const shapeName=img.dataset.shape;if(!shapeName){return false;}
const shapeCategory=shapeName.split("/")[1];return shapeCategory==="devices";}
isImageSupportedForShapes(img,dataset=img.dataset){if(!!dataset.hoverEffect||!!dataset.shape){return true;}
if(!dataset.originalId){return false;}
return isImageSupportedForProcessing(getMimetype(img,dataset));}
async asyncIsImageSupportedForShapes(img,dataset=img.dataset){if(!!dataset.hoverEffect||!!dataset.shape){return true;}
if(!dataset.originalId){return false;}
return isImageSupportedForProcessing(await getFetchedMimetype(img,dataset));}
async getShapeSvgText(shapeName){const shape=shapeName.replace("web_editor","html_builder");let shapeSvgText=this.shapeSvgTextCache[shape];if(shapeSvgText){return shapeSvgText;}
const shapeURL=getShapeURL(shape);shapeSvgText=await(await fetch(shapeURL)).text();this.shapeSvgTextCache[shape]=shapeSvgText;return shapeSvgText;}
async loadShape(img,newData={}){return this.dependencies.imagePostProcess.processImage({img,newDataset:newData});}
async processImageWarmup(img,newDataset){const getData=(propName)=>propName in newDataset?newDataset[propName]:img.dataset[propName];const combinedDataset={...img.dataset,...newDataset};const previousShapeId=img.dataset.shape||this.getDefaultShapeId(img.dataset);const shapeId=combinedDataset.shape||this.getDefaultShapeId(combinedDataset);if(!shapeId){return;}
const isNewShape=previousShapeId!==shapeId;const shapeSvgText=await this.getShapeSvgText(shapeId);const defaultShapeColors=this.getThemedSvgColors(shapeSvgText).join(";");newDataset.shapeColors=newDataset.shapeColors??(isNewShape?defaultShapeColors:img.dataset.shapeColors??defaultShapeColors);const getNaturalWidth=async()=>{if(img.naturalWidth){return img.naturalWidth;}
const loadedImgEl=await loadImage(img.getAttribute("src"));return loadedImgEl.naturalWidth;};const svgWidth=getData("resizeWidth")||getData("width")||(await getNaturalWidth());const svg=await this.computeShape(shapeSvgText,{...img.dataset,...newDataset,shapeId,shapeFlip:getData("shapeFlip")||"",shapeRotate:getData("shapeRotate")||0,shapeAnimationSpeed:Number(getData("shapeAnimationSpeed"))||0,shapeColors:newDataset.shapeColors,});const svgAspectRatio=parseInt(svg.getAttribute("width"))/parseInt(svg.getAttribute("height"));const imgAspectRatio=svg.dataset.imgAspectRatio;if(isNewShape&&!("aspectRatio"in newDataset)){const data=getImageTransformationData({...img.dataset,...newDataset});const shouldBeSquared=this.imageShapes[shapeId].togglableRatio&&!img.dataset.aspectRatio;if(shouldBeSquared&&!shouldPreventGifTransformation(data)){newDataset.aspectRatio="1/1";}}
const postProcessCroppedCanvas=async(canvas)=>{const img=await loadImage(canvas.toDataURL());document.createElement("div").appendChild(img);const cropper=await activateCropper(img,1,{y:0});const croppedCanvas=cropper.getCroppedCanvas();cropper.destroy();return croppedCanvas;};return{getHeight:svg.dataset.imgPerspective&&((canvas)=>canvas.width/svgAspectRatio),perspective:svg.dataset.imgPerspective||null,newDataset,postProcessCroppedCanvas:imgAspectRatio&&postProcessCroppedCanvas,svg,svgAspectRatio,svgWidth,};}
async processImagePost(b64url,handlerDataset,processContext){const{svg,svgAspectRatio,svgWidth}=processContext;if(!svg){return;}
svg.querySelectorAll("image").forEach((image)=>{image.setAttribute("xlink:href",b64url);});const loadedImage=await loadImage(b64url);if(!svg.dataset.forcedSize){svg.setAttribute("width",loadedImage.naturalWidth);svg.setAttribute("height",loadedImage.naturalHeight);}else{const imageWidth=Math.trunc(svgWidth);const newHeight=imageWidth/svgAspectRatio;svg.setAttribute("width",imageWidth);svg.setAttribute("height",newHeight);}
const blob=new Blob([svg.outerHTML],{type:"image/svg+xml",});const dataURL=await createDataURL(blob);return[dataURL,{...handlerDataset,mimetype:"image/svg+xml"}];}
async computeShape(svgText,params){const{shapeId,shapeFlip,shapeRotate,shapeAnimationSpeed,shapeColors}=params;svgText=this.replaceSvgColors(svgText,shapeColors.split(";"));if(shapeAnimationSpeed){svgText=this.replaceAnimationDuration(svgText,shapeAnimationSpeed);}
const svg=new DOMParser().parseFromString(svgText,"image/svg+xml").documentElement;if((shapeFlip||shapeRotate)&&this.isTransformableShape(shapeId)){const shapeTransformValues=[];if(shapeFlip){shapeTransformValues.push(`scale${shapeFlip === "x" ? "X" : shapeFlip === "y" ? "Y" : ""}(-1)`);}
if(shapeRotate){shapeTransformValues.push(`rotate(${shapeRotate}deg)`);}
const transformOrigin="transform-origin: 0.5px 0.5px;";svg.querySelector("#filterPath").setAttribute("style",`transform: ${shapeTransformValues.join(" ")}; ${transformOrigin}`);}
for(const cb of this.getResource("post_compute_shape_listeners")){await cb(svg,params);}
svg.removeChild(svg.querySelector("#preview"));return svg;}
replaceAnimationDuration(svgText,speed){const ratio=(speed>=0.0?1.0+speed:1.0/(1.0-speed)).toFixed(3);function callbackCssAnimationRule(match,declaration,value,unit,separator){value=parseFloat(value)/(ratio?ratio:1);return`${declaration}${value}${unit}${separator}`;}
function callbackSvgDurTimecountVal(match,attribute_name,value,unit){value=parseFloat(value)/(ratio?ratio:1);return`${attribute_name}${value}${unit ? unit : "s"}"`;}
svgText=svgText.replace(CSS_ANIMATION_RULE_REGEX,callbackCssAnimationRule);svgText=svgText.replace(SVG_DUR_TIMECOUNT_VAL_REGEX,callbackSvgDurTimecountVal);if(CSS_ANIMATION_RATIO_REGEX.test(svgText)){svgText=svgText.replace(CSS_ANIMATION_RATIO_REGEX,`--animation_ratio: ${ratio};`);}else{const regex=/<svg .*>/m;const subst=`$&\n\t<style>\n\t\t:root { \n\t\t\t--animation_ratio: ${ratio};\n\t\t}\n\t</style>`;svgText=svgText.replace(regex,subst);}
return svgText;}
replaceSvgColors(shapeSvgText,colors){const svgColors=this.getSvgColors(shapeSvgText);for(const[i,color]of colors.entries()){shapeSvgText=shapeSvgText.replace(new RegExp(svgColors[i],"g"),this.dependencies.imageToolOption.getCSSColorValue(color));}
return shapeSvgText;}
getSvgColors(shapeSvgText){return Object.values(DEFAULT_PALETTE).map((color)=>shapeSvgText.includes(color)?color:null);}
getThemedSvgColors(shapeSvgText){const svgColors=this.getSvgColors(shapeSvgText);return svgColors.map((color,i)=>color!==null?this.dependencies.imageToolOption.getCSSColorValue(`o-color-${i + 1}`):null);}
applyShapeColors(editingElement,newColors){}
isTransformableShape(shapeId){if(!shapeId){return false;}
const canTransform=this.imageShapes[shapeId].transform;return typeof canTransform==="undefined"?true:canTransform;}
isTechnicalShape(shapeId){if(!shapeId){return false;}
return this.imageShapes[shapeId].isTechnical;}
getShapeLabel(shapeId){if(!shapeId){return _t("None");}
return this.imageShapes[shapeId].selectLabel||_t("None");}
isAnimableShape(shape){if(!shape){return false;}
return this.imageShapes[shape].animated;}
isTogglableRatioShape(shape){if(!shape){return false;}
return this.imageShapes[shape].togglableRatio;}
getImageShapeGroups(){if(!this.imageShapeGroups){const shapeGroups={};for(const provider of this.getResource("image_shape_groups_providers")){const providedGroups=provider(shapeGroups);if(providedGroups){Object.assign(shapeGroups,deepMerge(shapeGroups,providedGroups));}}
this.imageShapeGroups=shapeGroups;}
return this.imageShapeGroups;}
makeImageShapes(){const entries=Object.values(this.getImageShapeGroups()).map((x)=>Object.values(x.subgroups).map((x)=>Object.entries(x.shapes)).flat()).flat();return Object.fromEntries(entries);}
getDefaultShapeId(dataset){for(const fn of this.getResource("default_shape_handlers")){const shapeId=fn(dataset);if(shapeId){return shapeId;}}}}
const SetImageShapeAction=__exports.SetImageShapeAction=class SetImageShapeAction extends BuilderAction{static id="setImageShape";static dependencies=["imageShapeOption"];async load({editingElement:img,value:shapeId}){const params={shape:shapeId,shapeFlip:undefined,shapeRotate:undefined,};if(!shapeId&&img.dataset.aspectRatio&&!cropperDataFields.some((field)=>field in img.dataset)){params["aspectRatio"]=undefined;}
return this.dependencies.imageShapeOption.loadShape(img,params);}
apply({editingElement:img,loadResult:updateImageAttributes}){updateImageAttributes();const imgFilename=img.dataset.originalSrc.split("/").pop().split(".")[0];img.dataset.fileName=`${imgFilename}.svg`;}
isApplied({editingElement:img,value}){const datasetShape=img.dataset.shape;if(!datasetShape){return false;}
const currentShape=datasetShape.replace("web_editor","html_builder");return currentShape===value;}}
const SetImgShapeColorAction=__exports.SetImgShapeColorAction=class SetImgShapeColorAction extends BuilderAction{static id="setImgShapeColor";static dependencies=["imageShapeOption","imageToolOption"];getValue({editingElement:img,params:{index:colorIndex}}){return img.dataset.shapeColors?.split(";")[colorIndex]||"";}
async load({editingElement:img,params:{index:colorIndex},value:color}){color=getValueFromVar(color);const newColorId=parseInt(colorIndex);const oldColors=img.dataset.shapeColors.split(";");const newColors=oldColors.slice(0);newColors[newColorId]=this.dependencies.imageToolOption.getCSSColorValue(color===""?`o-color-${newColorId + 1}`:color);return this.dependencies.imageShapeOption.loadShape(img,{shapeColors:newColors.join(";"),});}
apply({loadResult:updateImageAttributes}){updateImageAttributes();}}
const FlipImageShapeAction=__exports.FlipImageShapeAction=class FlipImageShapeAction extends BuilderAction{static id="flipImageShape";static dependencies=["imageShapeOption"];async load({editingElement:img,params:{axis}}){const currentAxis=img.dataset.shapeFlip||"";const newAxis=currentAxis.includes(axis)?currentAxis.replace(axis,""):currentAxis+axis;return this.dependencies.imageShapeOption.loadShape(img,{shapeFlip:newAxis==="yx"?"xy":newAxis,});}
apply({loadResult:updateImageAttributes}){updateImageAttributes();}}
const RotateImageShapeAction=__exports.RotateImageShapeAction=class RotateImageShapeAction extends BuilderAction{static id="rotateImageShape";static dependencies=["imageShapeOption"];async load({editingElement:img,params:{side}}){const currentRotateValue=parseInt(img.dataset.shapeRotate)||0;const rotation=side==="left"?-90:90;const newRotateValue=(currentRotateValue+rotation+360)%360;return this.dependencies.imageShapeOption.loadShape(img,{shapeRotate:newRotateValue});}
apply({loadResult:updateImageAttributes}){updateImageAttributes();}}
const SetImageShapeSpeedAction=__exports.SetImageShapeSpeedAction=class SetImageShapeSpeedAction extends BuilderAction{static id="setImageShapeSpeed";static dependencies=["imageShapeOption"];getValue({editingElement:img}){return img.dataset.shapeAnimationSpeed||0;}
async load({editingElement:img,value:speed}){return this.dependencies.imageShapeOption.loadShape(img,{shapeAnimationSpeed:speed,});}
apply({loadResult:updateImageAttributes}){updateImageAttributes();}}
const ResetImageShapeTransformationAction=__exports.ResetImageShapeTransformationAction=class ResetImageShapeTransformationAction extends BuilderAction{static id="resetImageShapeTransformation";static dependencies=["imageShapeOption"];async load({editingElement:img}){return this.dependencies.imageShapeOption.loadShape(img,{shapeFlip:undefined,shapeRotate:undefined,});}
apply({loadResult:updateImageAttributes}){updateImageAttributes();}}
const ToggleImageShapeRatioAction=__exports.ToggleImageShapeRatioAction=class ToggleImageShapeRatioAction extends BuilderAction{static id="toggleImageShapeRatio";static dependencies=["imageShapeOption"];isApplied({editingElement:img}){return img.dataset.aspectRatio!=="1/1";}
async load({editingElement:img}){const isStretched=img.dataset.aspectRatio!=="1/1";return this.dependencies.imageShapeOption.loadShape(img,{aspectRatio:isStretched?"1/1":"0/0",x:undefined,y:undefined,width:undefined,height:undefined,});}
apply({editingElement:img,loadResult:updateImageAttributes}){updateImageAttributes();}}
registry.category("builder-plugins").add(ImageShapeOptionPlugin.id,ImageShapeOptionPlugin);function isImageSupportedForProcessing(mimetype,strict=false){if(isGif(mimetype)){return!strict;}
return["image/jpeg","image/png","image/webp"].includes(mimetype);}
return __exports;});;

/* /html_builder/static/src/plugins/image/image_shapes_definition.js */
odoo.define('@html_builder/plugins/image/image_shapes_definition',['@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const imageShapeDefinitions=__exports.imageShapeDefinitions={basic:{label:_t("Basic"),subgroups:{geometrics:{label:_t("Geometrics"),shapes:{"html_builder/geometric/geo_square":{transform:false,isTechnical:true,},"html_builder/geometric/geo_shuriken":{selectLabel:_t("Shuriken"),transform:false,togglableRatio:true,},"html_builder/geometric/geo_diamond":{selectLabel:_t("Diamond"),transform:false,togglableRatio:true,},"html_builder/geometric/geo_triangle":{selectLabel:_t("Triangle"),togglableRatio:true,},"html_builder/geometric/geo_cornered_triangle":{selectLabel:_t("Corner Triangle"),togglableRatio:true,},"html_builder/geometric/geo_pentagon":{selectLabel:_t("Pentagon"),togglableRatio:true,},"html_builder/geometric/geo_hexagon":{selectLabel:_t("Hexagon"),togglableRatio:true,},"html_builder/geometric/geo_heptagon":{selectLabel:_t("Heptagon"),togglableRatio:true,},"html_builder/geometric/geo_star":{selectLabel:_t("Star 1"),togglableRatio:true,},"html_builder/geometric/geo_star_8pin":{selectLabel:_t("Star 2"),transform:false,togglableRatio:true,},"html_builder/geometric/geo_star_16pin":{selectLabel:_t("Star 3"),transform:false,togglableRatio:true,},"html_builder/geometric/geo_slanted":{selectLabel:_t("Slanted"),togglableRatio:true,},"html_builder/geometric/geo_emerald":{selectLabel:_t("Emerald"),togglableRatio:true,},"html_builder/geometric/geo_tetris":{selectLabel:_t("Tetris"),togglableRatio:true,},"html_builder/geometric/geo_kayak":{selectLabel:_t("Kayak"),togglableRatio:true,},"html_builder/geometric/geo_tear":{selectLabel:_t("Tear"),togglableRatio:true,},"html_builder/geometric/geo_gem":{selectLabel:_t("Gem"),togglableRatio:true,},"html_builder/geometric/geo_sonar":{selectLabel:_t("Sonar"),togglableRatio:true,},"html_builder/geometric/geo_door":{selectLabel:_t("Door"),togglableRatio:true,},"html_builder/geometric/geo_square_1":{selectLabel:_t("Square 1"),animated:true,},"html_builder/geometric/geo_square_2":{selectLabel:_t("Square 2"),animated:true,},"html_builder/geometric/geo_square_3":{selectLabel:_t("Square 3"),animated:true,},"html_builder/geometric/geo_square_4":{selectLabel:_t("Square 4"),animated:true,},"html_builder/geometric/geo_square_5":{selectLabel:_t("Square 5"),animated:true,},"html_builder/geometric/geo_square_6":{selectLabel:_t("Square 6"),animated:true,},},},geometrics_rounded:{label:_t("Geometrics Rounded"),shapes:{"html_builder/geometric_round/geo_round_circle":{selectLabel:_t("Circle"),transform:false,togglableRatio:true,},"html_builder/geometric_round/geo_round_square":{selectLabel:_t("Square (R)"),transform:false,togglableRatio:true,},"html_builder/geometric_round/geo_round_diamond":{selectLabel:_t("Diamond (R)"),transform:false,togglableRatio:true,},"html_builder/geometric_round/geo_round_shuriken":{selectLabel:_t("Shuriken (R)"),transform:false,togglableRatio:true,},"html_builder/geometric_round/geo_round_triangle":{selectLabel:_t("Triangle (R)"),togglableRatio:true,},"html_builder/geometric_round/geo_round_pentagon":{selectLabel:_t("Pentagon (R)"),togglableRatio:true,},"html_builder/geometric_round/geo_round_hexagon":{selectLabel:_t("Hexagon (R)"),togglableRatio:true,},"html_builder/geometric_round/geo_round_heptagon":{selectLabel:_t("Heptagon (R)"),togglableRatio:true,},"html_builder/geometric_round/geo_round_star":{selectLabel:_t("Star 1 (R)"),togglableRatio:true,},"html_builder/geometric_round/geo_round_star_7pin":{selectLabel:_t("Star 2 (R)"),togglableRatio:true,},"html_builder/geometric_round/geo_round_star_8pin":{selectLabel:_t("Star 3 (R)"),transform:false,togglableRatio:true,},"html_builder/geometric_round/geo_round_star_16pin":{selectLabel:_t("Star 4 (R)"),transform:false,togglableRatio:true,},"html_builder/geometric_round/geo_round_emerald":{selectLabel:_t("Emerald (R)"),togglableRatio:true,},"html_builder/geometric_round/geo_round_lemon":{selectLabel:_t("Lemon (R)"),togglableRatio:true,},"html_builder/geometric_round/geo_round_tear":{selectLabel:_t("Tear (R)"),togglableRatio:true,},"html_builder/geometric_round/geo_round_pill":{selectLabel:_t("Pill (R)"),togglableRatio:true,},"html_builder/geometric_round/geo_round_gem":{selectLabel:_t("Gem (R)"),togglableRatio:true,},"html_builder/geometric_round/geo_round_cornered":{selectLabel:_t("Cornered"),togglableRatio:true,},"html_builder/geometric_round/geo_round_door":{selectLabel:_t("Door (R)"),togglableRatio:true,},"html_builder/geometric_round/geo_round_sonar":{selectLabel:_t("Sonar (R)"),togglableRatio:true,},"html_builder/geometric_round/geo_round_clover":{selectLabel:_t("Clover (R)"),transform:false,togglableRatio:true,},"html_builder/geometric_round/geo_round_bread":{selectLabel:_t("Bread (R)"),transform:false,togglableRatio:true,},"html_builder/geometric_round/geo_round_square_1":{selectLabel:_t("Square 1 (R)"),animated:true,},"html_builder/geometric_round/geo_round_square_2":{selectLabel:_t("Square 2 (R)"),animated:true,},"html_builder/geometric_round/geo_round_blob_soft":{selectLabel:_t("Blob Soft"),animated:true,},"html_builder/geometric_round/geo_round_blob_medium":{selectLabel:_t("Blob Medium"),animated:true,},"html_builder/geometric_round/geo_round_blob_hard":{selectLabel:_t("Blob Hard"),animated:true,},},},geometric_panels:{label:_t("Geometrics Panels"),shapes:{"html_builder/panel/panel_duo":{selectLabel:_t("Duo"),},"html_builder/panel/panel_duo_r":{selectLabel:_t("Duo (R)"),},"html_builder/panel/panel_duo_step":{selectLabel:_t("Duo Step"),},"html_builder/panel/panel_duo_step_pill":{selectLabel:_t("Duo Step Pill"),},"html_builder/panel/panel_trio_in_r":{selectLabel:_t("Trio In (R)"),},"html_builder/panel/panel_trio_out_r":{selectLabel:_t("Trio Out (R)"),},"html_builder/panel/panel_window":{selectLabel:_t("Window"),transform:false,togglableRatio:true,},},},composites:{label:_t("Composites"),shapes:{"html_builder/composite/composite_double_pill":{selectLabel:_t("Double Pill"),},"html_builder/composite/composite_triple_pill":{selectLabel:_t("Triple Pill"),},"html_builder/composite/composite_half_circle":{selectLabel:_t("Half Circle"),},"html_builder/composite/composite_sonar":{selectLabel:_t("Double Sonar"),},"html_builder/composite/composite_cut_circle":{selectLabel:_t("Cut Circle"),},},},},},decorative:{label:_t("Decorative"),subgroups:{brushed:{label:_t("Brushed"),shapes:{"html_builder/brushed/brush_1":{selectLabel:_t("Brush 1"),togglableRatio:true,},"html_builder/brushed/brush_2":{selectLabel:_t("Brush 2"),togglableRatio:true,},"html_builder/brushed/brush_3":{selectLabel:_t("Brush 3"),togglableRatio:true,},"html_builder/brushed/brush_4":{selectLabel:_t("Brush 4"),},},},composition:{label:_t("Composition"),shapes:{"html_builder/composition/composition_organic_line":{selectLabel:_t("Organic Line"),transform:false,},"html_builder/composition/composition_oval_line":{selectLabel:_t("Oval Line"),transform:false,},"html_builder/composition/composition_triangle_line":{selectLabel:_t("Triangle Line"),animated:true,transform:false,},"html_builder/composition/composition_line_1":{selectLabel:_t("Line 1"),animated:true,transform:false,},"html_builder/composition/composition_line_3":{selectLabel:_t("Line 2"),animated:true,transform:false,},"html_builder/composition/composition_line_2":{selectLabel:_t("Line 2"),animated:true,transform:false,},"html_builder/composition/composition_mixed_1":{selectLabel:_t("Mixed 1"),animated:true,transform:false,},"html_builder/composition/composition_mixed_2":{selectLabel:_t("Mixed 2"),animated:true,transform:false,},"html_builder/composition/composition_planet_1":{selectLabel:_t("Planet 1"),animated:true,transform:false,},"html_builder/composition/composition_planet_2":{selectLabel:_t("Planet 2"),animated:true,transform:false,},"html_builder/composition/composition_square_1":{selectLabel:_t("Square Dot 1"),animated:true,transform:false,},"html_builder/composition/composition_square_2":{selectLabel:_t("Square Dot 2"),animated:true,transform:false,},"html_builder/composition/composition_square_3":{selectLabel:_t("Square Dot 3"),animated:true,transform:false,},"html_builder/composition/composition_square_4":{selectLabel:_t("Square Dot 4"),animated:true,transform:false,},"html_builder/composition/composition_square_line":{selectLabel:_t("Square Line"),animated:true,transform:false,},},},patterns:{label:_t("Patterns"),shapes:{"html_builder/pattern/pattern_organic_cross":{selectLabel:_t("Organic Cross"),transform:false,},"html_builder/pattern/pattern_organic_caps":{selectLabel:_t("Organic Caps"),transform:false,},"html_builder/pattern/pattern_oval_zebra":{selectLabel:_t("Oval Zebra"),transform:false,},"html_builder/pattern/pattern_wave_1":{selectLabel:_t("Wave 1"),animated:true,transform:false,},"html_builder/pattern/pattern_line_star":{selectLabel:_t("Star"),animated:true,transform:false,},"html_builder/pattern/pattern_line_sun":{selectLabel:_t("Sun"),animated:true,transform:false,},"html_builder/pattern/pattern_wave_2":{selectLabel:_t("Wave 2"),animated:true,transform:false,},"html_builder/pattern/pattern_wave_3":{selectLabel:_t("Wave 3"),animated:true,transform:false,},"html_builder/pattern/pattern_point":{selectLabel:_t("Point"),animated:true,transform:false,},"html_builder/pattern/pattern_organic_dot":{selectLabel:_t("Organic Dot"),animated:true,transform:false,},"html_builder/pattern/pattern_labyrinth":{selectLabel:_t("Labyrinth"),animated:true,transform:false,},"html_builder/pattern/pattern_circuit":{selectLabel:_t("Circuit"),animated:true,transform:false,},"html_builder/pattern/pattern_wave_4":{selectLabel:_t("Wave 4"),animated:true,transform:false,},},},solids:{label:_t("Solids"),shapes:{"html_builder/solid/solid_blob_1":{selectLabel:_t("Blob 1"),transform:false,},"html_builder/solid/solid_blob_2":{selectLabel:_t("Blob 2"),transform:false,},"html_builder/solid/solid_blob_3":{selectLabel:_t("Blob 3"),transform:false,},"html_builder/solid/solid_blob_4":{selectLabel:_t("Blob 4"),},"html_builder/solid/solid_blob_5":{selectLabel:_t("Blob 5"),transform:false,},"html_builder/solid/solid_blob_shadow_1":{selectLabel:_t("Blob Shadow 1"),transform:false,animated:true,},"html_builder/solid/solid_blob_shadow_2":{selectLabel:_t("Blob Shadow 2"),transform:false,animated:true,},"html_builder/solid/solid_square_1":{selectLabel:_t("Square 1"),transform:false,animated:true,},"html_builder/solid/solid_square_2":{selectLabel:_t("Square 2"),transform:false,animated:true,},"html_builder/solid/solid_square_3":{selectLabel:_t("Square 3"),transform:false,animated:true,},},},specials:{label:_t("Specials"),shapes:{"html_builder/special/special_speed":{selectLabel:_t("Speed"),animated:true,transform:false,},"html_builder/special/special_rain":{selectLabel:_t("Rain"),animated:true,transform:false,},"html_builder/special/special_snow":{selectLabel:_t("Snow"),animated:true,transform:false,},"html_builder/special/special_layered":{selectLabel:_t("Layered"),animated:true,transform:false,},"html_builder/special/special_filter":{selectLabel:_t("Filter"),animated:true,transform:false,},"html_builder/special/special_flag":{selectLabel:_t("Flag"),animated:true,},"html_builder/special/special_organic":{selectLabel:_t("Organic"),animated:true,},},},},},devices:{label:_t("Devices"),subgroups:{devices:{label:_t("Devices"),shapes:{"html_builder/devices/iphone_front_portrait":{selectLabel:_t("iPhone #1"),imgSize:"0.46:1",transform:false,},"html_builder/devices/iphone_3d_portrait_01":{selectLabel:_t("iPhone #2"),imgSize:"0.46:1",transform:false,},"html_builder/devices/iphone_3d_portrait_02":{selectLabel:_t("iPhone #3"),imgSize:"0.46:1",transform:false,},"html_builder/devices/iphone_front_landscape":{selectLabel:_t("iPhone #4"),imgSize:"2.17:1",transform:false,},"html_builder/devices/iphone_3d_landscape_01":{selectLabel:_t("iPhone #5"),imgSize:"2.17:1",transform:false,},"html_builder/devices/iphone_3d_landscape_02":{selectLabel:_t("iPhone #6"),imgSize:"2.17:1",transform:false,},"html_builder/devices/galaxy_front_portrait":{selectLabel:_t("Galaxy S #1"),imgSize:"0.45:1",transform:false,},"html_builder/devices/galaxy_3d_portrait_01":{selectLabel:_t("Galaxy S #2"),imgSize:"0.45:1",transform:false,},"html_builder/devices/galaxy_3d_portrait_02":{selectLabel:_t("Galaxy S #3"),imgSize:"0.45:1",transform:false,},"html_builder/devices/galaxy_front_landscape":{selectLabel:_t("Galaxy S #4"),imgSize:"2.22:1",transform:false,},"html_builder/devices/galaxy_3d_landscape_01":{selectLabel:_t("Galaxy S #5"),imgSize:"2.22:1",transform:false,},"html_builder/devices/galaxy_3d_landscape_02":{selectLabel:_t("Galaxy S #6"),imgSize:"2.22:1",transform:false,},"html_builder/devices/galaxy_front_portrait_half":{selectLabel:_t("Half Galaxy S"),imgSize:"0.45:1",transform:false,},"html_builder/devices/ipad_front_portrait":{selectLabel:_t("iPad #1"),imgSize:"0.75:1",transform:false,},"html_builder/devices/ipad_3d_portrait_01":{selectLabel:_t("iPad #2"),imgSize:"0.75:1",transform:false,},"html_builder/devices/ipad_3d_portrait_02":{selectLabel:_t("iPad #3"),imgSize:"0.75:1",transform:false,},"html_builder/devices/ipad_front_landscape":{selectLabel:_t("iPad #4"),imgSize:"4:3",transform:false,},"html_builder/devices/ipad_3d_landscape_01":{selectLabel:_t("iPad #5"),imgSize:"4:3",transform:false,},"html_builder/devices/ipad_3d_landscape_02":{selectLabel:_t("iPad #6"),imgSize:"4:3",transform:false,},"html_builder/devices/imac_front":{selectLabel:_t("iMac #1"),imgSize:"16:9",transform:false,},"html_builder/devices/imac_3d_01":{selectLabel:_t("iMac #2"),imgSize:"16:9",transform:false,},"html_builder/devices/imac_3d_02":{selectLabel:_t("iMac #3"),imgSize:"16:9",transform:false,},"html_builder/devices/macbook_front":{selectLabel:_t("MacBook #1"),imgSize:"1.6:1",transform:false,},"html_builder/devices/macbook_3d_01":{selectLabel:_t("MacBook #2"),imgSize:"1.6:1",transform:false,},"html_builder/devices/macbook_3d_02":{selectLabel:_t("MacBook #3"),imgSize:"1.6:1",transform:false,},"html_builder/devices/browser_01":{selectLabel:_t("Browser #1"),transform:false,},"html_builder/devices/browser_02":{selectLabel:_t("Browser #2"),transform:false,},"html_builder/devices/browser_03":{selectLabel:_t("Browser #3"),transform:false,},},},},},};return __exports;});;

/* /html_builder/static/src/plugins/image/image_size.js */
odoo.define('@html_builder/plugins/image/image_size',['@html_builder/core/utils','@html_editor/utils/image','@html_editor/utils/image_processing'],function(require){'use strict';let __exports={};const{BaseOptionComponent,useDomState}=require("@html_builder/core/utils");const{getImageSrc,isImageCorsProtected}=require("@html_editor/utils/image");const{getDataURLBinarySize}=require("@html_editor/utils/image_processing");const imageCacheSize=new Map();const ImageSize=__exports.ImageSize=class ImageSize extends BaseOptionComponent{static template="html_builder.ImageSize";setup(){super.setup();this.imagePostProcess=this.env.editor.shared.imagePostProcess;this.state=useDomState(async(el)=>({size:await this.getImageSize(el),}));}
async getImageSize(el){const src=getImageSrc(el);if(!src){return;}
let size;if(isBase64ImageSrc(src)){size=getDataURLBinarySize(src);}else{if(imageCacheSize.has(src)){size=imageCacheSize.get(src);}else{if(await isImageCorsProtected(el)){return;}
size=await this.imagePostProcess.getProcessedImageSize(el);imageCacheSize.set(src,size);}}
return`${(size / 1024).toFixed(1)} kB`;}}
function isBase64ImageSrc(src){return src&&src.startsWith("data:image/")&&src.includes(";base64,");}
return __exports;});;

/* /html_builder/static/src/plugins/image/image_size_plugin.js */
odoo.define('@html_builder/plugins/image/image_size_plugin',['@html_editor/plugin','@web/core/registry','@html_builder/plugins/image/image_size'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{ImageSize}=require("@html_builder/plugins/image/image_size");class ImageSizePlugin extends Plugin{static id="imageSize";static dependencies=["imagePostProcess"];resources={elements_to_options_title_components:{Component:ImageSize,selector:"img",},};}
registry.category("builder-plugins").add(ImageSizePlugin.id,ImageSizePlugin);return __exports;});;

/* /html_builder/static/src/plugins/image/image_snippet_option_plugin.js */
odoo.define('@html_builder/plugins/image/image_snippet_option_plugin',['@html_editor/plugin','@web/core/registry'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");class ImageSnippetOptionPlugin extends Plugin{static id="imageSnippetOption";static dependencies=["media"];static shared=["onSnippetDropped"];resources={on_snippet_dropped_handlers:this.onSnippetDropped.bind(this),so_content_addition_selector:[".s_image"],};async onSnippetDropped({snippetEl,dragState}){if(!snippetEl.matches(".s_image")){return;}
let isImageSelected=false;await new Promise((resolve)=>{const onClose=this.dependencies.media.openMediaDialog({onlyImages:true,save:async(selectedImageEl)=>{isImageSelected=true;snippetEl.replaceWith(selectedImageEl);if(dragState.draggedEl.classList.contains("o_grid_item")){dragState.draggedEl.classList.add("o_grid_item_image");}
dragState.replacedSnippetEl=selectedImageEl;},});onClose.then(()=>{resolve();});});return!isImageSelected;}}
registry.category("builder-plugins").add(ImageSnippetOptionPlugin.id,ImageSnippetOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/image/image_tool_option.js */
odoo.define('@html_builder/plugins/image/image_tool_option',['@html_builder/core/utils','@html_builder/plugins/image/image_shape_option','@html_builder/plugins/image/image_filter_option','@html_builder/plugins/image/image_format_option','@html_builder/plugins/image/image_transform_option','@html_builder/plugins/utils','@html_builder/utils/image','@html_editor/main/media/image_post_process_plugin'],function(require){'use strict';let __exports={};const{BaseOptionComponent,useDomState}=require("@html_builder/core/utils");const{ImageShapeOption}=require("@html_builder/plugins/image/image_shape_option");const{ImageFilterOption}=require("@html_builder/plugins/image/image_filter_option");const{ImageFormatOption}=require("@html_builder/plugins/image/image_format_option");const{ImageTransformOption}=require("@html_builder/plugins/image/image_transform_option");const{dynamicSVGSelector}=require("@html_builder/plugins/utils");const{getMimetypeBeforeShape}=require("@html_builder/utils/image");const{isImageSupportedForProcessing}=require("@html_editor/main/media/image_post_process_plugin");const ImageToolOption=__exports.ImageToolOption=class ImageToolOption extends BaseOptionComponent{static template="html_builder.ImageToolOption";static components={ImageShapeOption,ImageFilterOption,ImageFormatOption,ImageTransformOption,};static selector="img";static exclude="[data-oe-type='image'] > img:not([data-attachment-id])";static name="imageToolOption";setup(){super.setup();this.state=useDomState(async(editingElement)=>{const mimetype=await getMimetypeBeforeShape(editingElement);const showCropTool=await isImageSupportedForProcessing(editingElement,mimetype);return{isImageAnimated:editingElement.classList.contains("o_animate"),isDynamicSVG:editingElement.matches(dynamicSVGSelector),isImageBinaryField:editingElement.parentElement.matches("[data-oe-type=image]"),showCropTool,};});}}
return __exports;});;

/* /html_builder/static/src/plugins/image/image_tool_option_plugin.js */
odoo.define('@html_builder/plugins/image/image_tool_option_plugin',['@html_editor/utils/image_processing','@web/core/registry','@html_editor/plugin','@html_builder/plugins/image/image_tool_option','@html_editor/utils/image','@html_editor/utils/resource','@html_builder/utils/option_sequence','@html_builder/plugins/image/replace_media_option','@html_builder/plugins/image/image_format_option','@html_builder/core/builder_action','@html_builder/core/core_builder_action_plugin','@html_editor/utils/dom_traversal','@web/core/utils/colors','@html_editor/utils/formatting','@html_builder/core/utils','@html_editor/main/media/image_post_process_plugin'],function(require){'use strict';let __exports={};const{cropperDataFieldsWithAspectRatio,loadImage,loadImageInfo,}=require("@html_editor/utils/image_processing");const{registry}=require("@web/core/registry");const{Plugin}=require("@html_editor/plugin");const{ImageToolOption}=require("@html_builder/plugins/image/image_tool_option");const{getFetchedMimetype,isImageCorsProtected}=require("@html_editor/utils/image");const{withSequence}=require("@html_editor/utils/resource");const{REPLACE_MEDIA,IMAGE_TOOL,ALIGNMENT_STYLE_PADDING,}=require("@html_builder/utils/option_sequence");const{ReplaceMediaOption,searchSupportedParentLinkEl}=require("@html_builder/plugins/image/replace_media_option");const{computeMaxDisplayWidth}=require("@html_builder/plugins/image/image_format_option");const{BuilderAction}=require("@html_builder/core/builder_action");const{ClassAction}=require("@html_builder/core/core_builder_action_plugin");const{selectElements}=require("@html_editor/utils/dom_traversal");const{isCSSColor}=require("@web/core/utils/colors");const{getCSSVariableValue,getHtmlStyle}=require("@html_editor/utils/formatting");const{BaseOptionComponent}=require("@html_builder/core/utils");const{isImageSupportedForProcessing}=require("@html_editor/main/media/image_post_process_plugin");const IMAGE_LINK_ALIGN_CLASSES=["mx-auto","ms-auto","me-auto"];const ImageAndFaOption=__exports.ImageAndFaOption=class ImageAndFaOption extends BaseOptionComponent{static template="html_builder.ImageAndFaOption";static selector="span.fa, i.fa, img";static exclude="[data-oe-type='image'] > img, [data-oe-xpath]";static name="imageAndFaOption";}
class ImageToolOptionPlugin extends Plugin{static id="imageToolOption";static dependencies=["history","userCommand","imagePostProcess","imageCrop","media","builderOptions",];static shared=["getCSSColorValue"];resources={builder_options:[withSequence(REPLACE_MEDIA,ReplaceMediaOption),withSequence(IMAGE_TOOL,ImageToolOption),withSequence(ALIGNMENT_STYLE_PADDING,ImageAndFaOption),],builder_actions:{ImageAlignClassAction,CropImageAction,ResetCropAction,ReplaceMediaAction,SetLinkAction,SetUrlAction,SetNewWindowAction,AltAction,},on_media_dialog_saved_handlers:async(elements,{node})=>{for(const image of elements){if(image&&image.tagName==="IMG"){const imgInfo=await loadImageInfo(image);if(!imgInfo.originalSrc||!imgInfo.originalId){return;}
const isImgSupportedForProcessing=await isImageSupportedForProcessing(image,await getFetchedMimetype(image,imgInfo));const newDataset={};if(isImgSupportedForProcessing){newDataset.formatMimetype=this.config.defaultImageMimetype??"image/webp";const original=await loadImage(imgInfo.originalSrc);const maxWidth=image.dataset.width?image.naturalWidth:original.naturalWidth;const optimizedWidth=Math.min(maxWidth,computeMaxDisplayWidth(node||this.editable));newDataset.resizeWidth=optimizedWidth;}
const updateImageAttributes=await this.dependencies.imagePostProcess.processImage({img:image,newDataset,});updateImageAttributes();}}},hover_effect_allowed_predicates:(el)=>this.canHaveHoverEffect(el),normalize_handlers:this.migrateImages.bind(this),};setup(){this.htmlStyle=getHtmlStyle(this.document);}
async canHaveHoverEffect(imgEl){return imgEl.tagName==="IMG"&&!(await isImageCorsProtected(imgEl));}
migrateImages(rootEl){for(const el of selectElements(rootEl,"img[data-original-id]:not([data-attachment-id]), .oe_img_bg[data-original-id]:not([data-attachment-id])")){el.dataset.attachmentId=el.dataset.originalId;}
for(const el of selectElements(rootEl,"img[data-original-mimetype]:not([data-format-mimetype]), .oe_img_bg[data-original-mimetype]:not([data-format-mimetype])")){el.dataset.formatMimetype=el.dataset.originalMimetype;delete el.dataset.originalMimetype;}}
getCSSColorValue(color){if(!color||isCSSColor(color)){return color;}
return getCSSVariableValue(color,this.htmlStyle);}}
const CropImageAction=__exports.CropImageAction=class CropImageAction extends BuilderAction{static id="cropImage";static dependencies=["imageCrop","imagePostProcess"];isApplied({editingElement}){return cropperDataFieldsWithAspectRatio.some((field)=>editingElement.dataset[field]);}
load({editingElement:img}){return new Promise((resolve)=>{this.dependencies.imageCrop.openCropImage(img,{onClose:resolve,onSave:async(newDataset)=>{resolve(this.dependencies.imagePostProcess.processImage({img,newDataset}));},});});}
apply({loadResult:updateImageAttributes}){updateImageAttributes?.();}}
const ResetCropAction=__exports.ResetCropAction=class ResetCropAction extends BuilderAction{static id="resetCrop";static dependencies=["imagePostProcess"];async load({editingElement:img}){const newDataset=Object.fromEntries(cropperDataFieldsWithAspectRatio.map((field)=>[field,undefined]));return this.dependencies.imagePostProcess.processImage({img,newDataset});}
apply({loadResult:updateImageAttributes}){updateImageAttributes();}}
const ReplaceMediaAction=__exports.ReplaceMediaAction=class ReplaceMediaAction extends BuilderAction{static id="replaceMedia";static dependencies=["media_website"];setup(){this.canTimeout=false;}
async apply({editingElement:mediaEl}){await this.dependencies.media_website.replaceMedia(mediaEl);}}
const SetLinkAction=__exports.SetLinkAction=class SetLinkAction extends BuilderAction{static id="setLink";setup(){this.preview=false;}
apply({editingElement}){const parentEl=searchSupportedParentLinkEl(editingElement);if(parentEl.tagName!=="A"){const wrapperEl=document.createElement("a");editingElement.after(wrapperEl);wrapperEl.appendChild(editingElement);const alignClasses=IMAGE_LINK_ALIGN_CLASSES.filter((cls)=>editingElement.classList.contains(cls));for(const className of IMAGE_LINK_ALIGN_CLASSES){wrapperEl.classList.toggle(className,alignClasses.includes(className));}}else{const fragment=document.createDocumentFragment();fragment.append(...parentEl.childNodes);parentEl.replaceWith(fragment);}}
isApplied({editingElement}){const parentEl=searchSupportedParentLinkEl(editingElement);return parentEl.tagName==="A";}}
const ImageAlignClassAction=__exports.ImageAlignClassAction=class ImageAlignClassAction extends ClassAction{static id="imageAlignClassAction";apply(context){super.apply(context);this.syncLinkAlignment(context.editingElement);}
syncLinkAlignment(editingElement){const linkEl=editingElement.parentElement;if(!linkEl||linkEl.tagName!=="A"||linkEl.firstElementChild!==editingElement||linkEl.childElementCount!==1||linkEl.textContent.replace(/\u200B/g,"").trim()){return;}
const alignClasses=IMAGE_LINK_ALIGN_CLASSES.filter((cls)=>editingElement.classList.contains(cls));for(const className of IMAGE_LINK_ALIGN_CLASSES){linkEl.classList.toggle(className,alignClasses.includes(className));}}}
const SetUrlAction=__exports.SetUrlAction=class SetUrlAction extends BuilderAction{static id="setUrl";setup(){this.preview=false;}
apply({editingElement,value}){const linkEl=searchSupportedParentLinkEl(editingElement);let url=value;if(!url){linkEl.removeAttribute("href");return;}
if(!url.startsWith("/")&&!url.startsWith("#")&&!/^([a-zA-Z]*.):.+$/gm.test(url)){url="http://"+url;}
linkEl.setAttribute("href",url);}
getValue({editingElement}){const linkEl=searchSupportedParentLinkEl(editingElement);return linkEl.getAttribute("href");}}
const SetNewWindowAction=__exports.SetNewWindowAction=class SetNewWindowAction extends BuilderAction{static id="setNewWindow";setup(){this.preview=false;}
apply({editingElement,value}){const linkEl=searchSupportedParentLinkEl(editingElement);linkEl.setAttribute("target","_blank");}
clean({editingElement}){const linkEl=searchSupportedParentLinkEl(editingElement);linkEl.removeAttribute("target");}
isApplied({editingElement}){const linkEl=searchSupportedParentLinkEl(editingElement);return linkEl.getAttribute("target")==="_blank";}}
const AltAction=__exports.AltAction=class AltAction extends BuilderAction{static id="alt";getValue({editingElement:imgEl}){return imgEl.alt;}
apply({editingElement:imgEl,value}){const trimmedValue=value.trim();if(trimmedValue){imgEl.alt=trimmedValue;if(imgEl.getAttribute("role")==="presentation"){imgEl.removeAttribute("role");}}else{imgEl.removeAttribute("alt");}}}
registry.category("builder-plugins").add(ImageToolOptionPlugin.id,ImageToolOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/image/image_transform_option.js */
odoo.define('@html_builder/plugins/image/image_transform_option',['@html_builder/core/utils','@html_editor/main/media/image_transform_button','@odoo/owl','@web/core/registry'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const{useImageTransform}=require("@html_editor/main/media/image_transform_button");const{onWillDestroy}=require("@odoo/owl");const{registry}=require("@web/core/registry");const ImageTransformOption=__exports.ImageTransformOption=class ImageTransformOption extends BaseOptionComponent{static template="website.ImageTransformOption";setup(){super.setup();this.transform=useImageTransform({document:document,closeImageTransformation:this.closeImageTransformation.bind(this),buttonSelector:'[data-action-id="transformImage"], [data-action-id="transformImage"] *',});onWillDestroy(()=>{this.closeImageTransformation();});}
closeImageTransformation(){if(this.transform.isImageTransformationOpen()){registry.category("main_components").remove("ImageTransformation");}}}
return __exports;});;

/* /html_builder/static/src/plugins/image/image_transform_option_plugin.js */
odoo.define('@html_builder/plugins/image/image_transform_option_plugin',['@html_editor/plugin','@web/core/registry','@html_editor/main/media/image_transformation','@html_builder/core/builder_action','@web/core/utils/concurrency'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{ImageTransformation}=require("@html_editor/main/media/image_transformation");const{BuilderAction}=require("@html_builder/core/builder_action");const{Deferred}=require("@web/core/utils/concurrency");const ImageTransformOptionPlugin=__exports.ImageTransformOptionPlugin=class ImageTransformOptionPlugin extends Plugin{static id="imageTransformOption";resources={builder_actions:{TransformImageAction,ResetTransformImageAction,},};}
class TransformImageAction extends BuilderAction{static id="transformImage";static dependencies=["history"];isApplied({editingElement}){return editingElement.matches(`[style*="transform"]`);}
async apply({editingElement,params:{isImageTransformationOpen,closeImageTransformation},}){if(!isImageTransformationOpen()){const deferredTillMounted=new Deferred();registry.category("main_components").add("ImageTransformation",{Component:ImageTransformation,props:{image:editingElement,document:this.document,editable:this.editable,destroy:()=>closeImageTransformation(),onApply:()=>{this.dependencies.history.addStep();},onComponentMounted:()=>{deferredTillMounted.resolve();},},});await deferredTillMounted;}}}
class ResetTransformImageAction extends BuilderAction{static id="resetTransformImage";static dependencies=["image"];apply({editingElement,params:{mainParam:closeImageTransformation}}){this.dependencies.image.resetImageTransformation(editingElement);closeImageTransformation();}}
registry.category("builder-plugins").add(ImageTransformOptionPlugin.id,ImageTransformOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/image/replace_media_option.js */
odoo.define('@html_builder/plugins/image/replace_media_option',['@html_builder/core/utils','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{BaseOptionComponent,useDomState}=require("@html_builder/core/utils");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const ReplaceMediaOption=__exports.ReplaceMediaOption=class ReplaceMediaOption extends BaseOptionComponent{static template="html_builder.ReplaceMediaOption";static selector="img, .media_iframe_video, span.fa, i.fa";static exclude="[data-oe-xpath], a[href^='/website/social/'] > i.fa, a[class*='s_share_'] > i.fa";static name="replaceMediaOption";setup(){super.setup();this.state=useDomState((editingElement)=>({tooltipName:this.getTooltipName(editingElement),canSetLink:this.canSetLink(editingElement),hasHref:this.hasHref(editingElement),}));}
canSetLink(editingElement){return(isImageSupportedForStyle(editingElement)&&!searchSupportedParentLinkEl(editingElement).matches("a[data-oe-xpath]")&&!editingElement.classList.contains("media_iframe_video"));}
hasHref(editingElement){const parentEl=searchSupportedParentLinkEl(editingElement);return parentEl.tagName==="A"&&parentEl.hasAttribute("href");}
getTooltipName(editingElement){const classes=editingElement.classList;if(classes.contains("media_iframe_video")){return _t("Replace Video");}else if(classes.contains("img")){return _t("Replace Image");}else if(classes.contains("fa")||Array.from(classes).some((cls)=>cls.startsWith("s_share_"))){return _t("Replace Icon");}else{return _t("Replace Media");}}}
__exports.isImageSupportedForStyle=isImageSupportedForStyle;function isImageSupportedForStyle(img){if(!img.parentElement){return false;}
const isTFieldImg="oeType"in img.parentElement.dataset;const isEditableRootElement="oeXpath"in img.dataset;return!isTFieldImg&&!isEditableRootElement;}
__exports.searchSupportedParentLinkEl=searchSupportedParentLinkEl;function searchSupportedParentLinkEl(editingElement){const parentEl=editingElement.parentElement;return parentEl.matches("figure")?parentEl.parentElement:parentEl;}
return __exports;});;

/* /html_builder/static/src/plugins/image_field_plugin.js */
odoo.define('@html_builder/plugins/image_field_plugin',['@html_editor/plugin','@web/core/registry'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const ImageFieldPlugin=__exports.ImageFieldPlugin=class ImageFieldPlugin extends Plugin{static id="imageField";resources={content_editable_selectors:"[data-oe-field][data-oe-type=image] img",content_not_editable_selectors:"[data-oe-field][data-oe-type=image]",};}
registry.category("builder-plugins").add(ImageFieldPlugin.id,ImageFieldPlugin);return __exports;});;

/* /html_builder/static/src/plugins/layout_column_option.js */
odoo.define('@html_builder/plugins/layout_column_option',['@html_builder/core/select_number_column','@html_builder/core/utils'],function(require){'use strict';let __exports={};const{SelectNumberColumn}=require("@html_builder/core/select_number_column");const{BaseOptionComponent}=require("@html_builder/core/utils");const LayoutColumnOption=__exports.LayoutColumnOption=class LayoutColumnOption extends BaseOptionComponent{static template="html_builder.LayoutColumnOption";static components={SelectNumberColumn,};static selector="section.s_features_grid, section.s_process_steps";static applyTo=":scope > *:has(> .row), :scope > .s_allow_columns";static name="layoutColumnOption";}
return __exports;});;

/* /html_builder/static/src/plugins/layout_column_option_plugin.js */
odoo.define('@html_builder/plugins/layout_column_option_plugin',['@html_builder/core/builder_action','@html_builder/utils/column_layout_utils','@html_editor/plugin','@web/core/registry','@html_editor/utils/resource','@html_builder/plugins/layout_column_option','@html_builder/utils/option_sequence'],function(require){'use strict';let __exports={};const{BuilderAction}=require("@html_builder/core/builder_action");const{getFirstItem,getNbColumns,getRow}=require("@html_builder/utils/column_layout_utils");const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{withSequence}=require("@html_editor/utils/resource");const{LayoutColumnOption}=require("@html_builder/plugins/layout_column_option");const{LAYOUT_COLUMN}=require("@html_builder/utils/option_sequence");class LayoutColumnOptionPlugin extends Plugin{static id="LayoutColumnOption";static dependencies=["clone","selection"];resources={builder_options:[withSequence(LAYOUT_COLUMN,LayoutColumnOption)],on_cloned_handlers:this.onCloned.bind(this),builder_actions:{ChangeColumnCountAction,},selection_placeholder_container_predicates:(container)=>{if(container.nodeName==="DIV"&&container.parentElement.classList.contains("row")){return true;}},selection_blocker_predicates:(blocker)=>{if(blocker.nodeType===Node.ELEMENT_NODE&&blocker.classList.contains("row")){return false;}},};onCloned({cloneEl}){const cloneElClassList=cloneEl.classList;const offsetRegex=new RegExp(`^offset-(${this.config.mobileBreakpoint}-)?([0-9]{1,2})$`);const offsetClasses=[...cloneElClassList].filter((cls)=>cls.match(offsetRegex));cloneElClassList.remove(...offsetClasses);}}
const ChangeColumnCountAction=__exports.ChangeColumnCountAction=class ChangeColumnCountAction extends BuilderAction{static id="changeColumnCount";static dependencies=["selection","clone","builderOptions"];async apply({editingElement,value:nbColumns}){if(nbColumns==="custom"){return;}
let rowEl=getRow(editingElement);let columnEls,prevNbColumns;if(!rowEl){const cursors=this.dependencies.selection.preserveSelection();rowEl=document.createElement("div");const columnEl=document.createElement("div");rowEl.classList.add("row");columnEl.classList.add(`col-${this.config.mobileBreakpoint}-12`);columnEl.append(...editingElement.children);rowEl.append(columnEl);editingElement.append(rowEl);cursors.restore();columnEls=[columnEl];prevNbColumns=0;}else{columnEls=rowEl.children;prevNbColumns=getNbColumns(columnEls,this.config.isMobileView(this.editable),this.config.mobileBreakpoint);}
if(nbColumns===prevNbColumns){return;}
this._resizeColumns(columnEls,nbColumns||1);const itemsDelta=nbColumns-rowEl.children.length;if(itemsDelta>0){for(let i=0;i<itemsDelta;i++){const lastEl=rowEl.lastElementChild;await this.dependencies.clone.cloneElement(lastEl,{activateClone:false});}}
if(nbColumns===0){const cursors=this.dependencies.selection.preserveSelection();const columnEl=editingElement.querySelector(".row > div");editingElement.append(...columnEl.children);rowEl.remove();cursors.restore();}else if(prevNbColumns===0){const firstColumnEl=editingElement.querySelector(".row > div");this.dependencies.builderOptions.setNextTarget(firstColumnEl);}}
isApplied({editingElement,value}){const columnEls=getRow(editingElement)?.children;return(getNbColumns(columnEls,this.config.isMobileView(this.editable),this.config.mobileBreakpoint)===value);}
_resizeColumns(columnEls,nbColumns){const isMobile=this.config.isMobileView(this.editable);const itemSize=Math.floor(12/nbColumns)||1;const firstItem=getFirstItem(columnEls,isMobile);const firstItemOffset=Math.floor((12-itemSize*nbColumns)/2);const resolutionModifier=isMobile?"":`-${this.config.mobileBreakpoint}`;const replacingRegex=new RegExp(`(?:^|\\s+)(col|offset)${resolutionModifier}(-\\d{1,2})?(?!\\S)`,"g");for(const columnEl of columnEls){columnEl.className=columnEl.className.replace(replacingRegex,"");columnEl.classList.add(`col${resolutionModifier}-${itemSize}`);if(firstItemOffset&&columnEl===firstItem){columnEl.classList.add(`offset${resolutionModifier}-${firstItemOffset}`);}
const hasMobileOffset=columnEl.className.match(/(^|\s+)offset-\d{1,2}(?!\S)/);const desktopOffsetRegexp=new RegExp(`(^|\\s+)offset-${this.config.mobileBreakpoint}-[1-9][0-1]?(?!\\S)`);const hasDesktopOffset=columnEl.className.match(desktopOffsetRegexp);columnEl.classList.toggle(`offset-${this.config.mobileBreakpoint}-0`,hasMobileOffset&&!hasDesktopOffset);}}}
registry.category("builder-plugins").add(LayoutColumnOptionPlugin.id,LayoutColumnOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/many2one_option.js */
odoo.define('@html_builder/plugins/many2one_option',['@html_builder/core/utils','@odoo/owl','@web/core/utils/hooks'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const{onWillStart}=require("@odoo/owl");const{useService}=require("@web/core/utils/hooks");const Many2OneOption=__exports.Many2OneOption=class Many2OneOption extends BaseOptionComponent{static template="html_builder.Many2OneOption";static selector="[data-oe-many2one-model]:not([data-oe-readonly])";static editableOnly=false;setup(){super.setup();this.orm=useService("orm");onWillStart(async()=>{const el=this.env.getEditingElement();const contactOpts=JSON.parse(el.dataset.oeContactOptions||"{}");this.nullText=contactOpts.null_text;this.model=el.dataset.oeMany2oneModel;this.domain=JSON.parse(el.dataset.oeMany2oneDomain||"[]");const searchResult=await this.orm.searchRead("ir.model",[["model","=",this.model]],["name"]);this.label=searchResult[0]?.name;});}}
return __exports;});;

/* /html_builder/static/src/plugins/many2one_option_plugin.js */
odoo.define('@html_builder/plugins/many2one_option_plugin',['@html_editor/plugin','@web/core/registry','@html_builder/plugins/many2one_option','@html_builder/core/builder_action'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{Many2OneOption}=require("@html_builder/plugins/many2one_option");const{BuilderAction}=require("@html_builder/core/builder_action");const Many2OneOptionPlugin=__exports.Many2OneOptionPlugin=class Many2OneOptionPlugin extends Plugin{static id="many2OneOption";resources={builder_options:[Many2OneOption],builder_actions:{Many2OneAction,},content_not_editable_selectors:"[data-oe-field][data-oe-many2one-id]",after_replication_handlers:({sourceEl,targetEl})=>{if(sourceEl.hasAttribute("data-oe-many2one-model")&&targetEl.hasAttribute("data-oe-many2one-model")){targetEl.setAttribute("data-oe-many2one-id",sourceEl.getAttribute("data-oe-many2one-id"));}},};}
const Many2OneAction=__exports.Many2OneAction=class Many2OneAction extends BuilderAction{static id="many2One";async load({editingElement,value}){const{id}=JSON.parse(value);const{oeModel,oeId,oeField}=editingElement.dataset;const allContactOptions=new Set(this.editable.querySelectorAll(`[data-oe-model="${oeModel}"][data-oe-id="${oeId}"][data-oe-field="${oeField}"][data-oe-type="contact"]`).values().map((el)=>el.dataset.oeContactOptions));return Object.fromEntries(await Promise.all(allContactOptions.values().map(async(contactOptions)=>[contactOptions,await this.services.orm.call("ir.qweb.field.contact","get_record_to_html",[[id]],{options:JSON.parse(contactOptions)}),])));}
apply({editingElement,value,loadResult}){const{id,name}=JSON.parse(value);const{oeModel,oeId,oeField,oeContactOptions}=editingElement.dataset;const selector=`[data-oe-model="${oeModel}"][data-oe-id="${oeId}"][data-oe-field="${oeField}"]`+
(oeContactOptions===undefined?"[data-oe-contact-options]":`:not([data-oe-contact-options='${oeContactOptions}'])`);for(const el of[...this.editable.querySelectorAll(selector),editingElement]){el.dataset.oeMany2oneId=id;if(el.dataset.oeType==="contact"){el.replaceChildren(...new DOMParser().parseFromString(loadResult[el.dataset.oeContactOptions],"text/html").body.childNodes);}else{el.textContent=name;}}}
getValue({editingElement}){return JSON.stringify({id:parseInt(editingElement.dataset.oeMany2oneId)});}}
registry.category("builder-plugins").add(Many2OneOptionPlugin.id,Many2OneOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/monetary_field_plugin.js */
odoo.define('@html_builder/plugins/monetary_field_plugin',['@html_editor/plugin','@web/core/registry'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const monetarySel="[data-oe-field][data-oe-type=monetary]";const MonetaryFieldPlugin=__exports.MonetaryFieldPlugin=class MonetaryFieldPlugin extends Plugin{static id="monetaryField";static dependencies=["selection"];resources={content_editable_selectors:`${monetarySel} .oe_currency_value`,content_not_editable_selectors:monetarySel,};setup(){const handleEvent=(ev,condition)=>{const fieldEl=ev.target.closest(monetarySel);const amountEl=fieldEl?.querySelector(".oe_currency_value");if(amountEl?.isContentEditable&&condition({fieldEl,amountEl})){this.dependencies.selection.setSelection({anchorNode:amountEl,anchorOffset:0,focusNode:amountEl,focusOffset:amountEl.childNodes.length,});}};this.addDomListener(this.editable,"focusin",(ev)=>handleEvent(ev,({fieldEl})=>fieldEl!==ev.relatedTarget?.closest(monetarySel)));this.addDomListener(this.editable,"click",(ev)=>handleEvent(ev,({amountEl})=>!this.dependencies.selection.getTargetedNodes().some((node)=>amountEl.contains(node))));}}
registry.category("builder-plugins").add(MonetaryFieldPlugin.id,MonetaryFieldPlugin);return __exports;});;

/* /html_builder/static/src/plugins/rating_option_plugin.js */
odoo.define('@html_builder/plugins/rating_option_plugin',['@html_builder/core/builder_action','@html_builder/core/utils','@html_editor/plugin','@web/core/registry'],function(require){'use strict';let __exports={};const{BuilderAction}=require("@html_builder/core/builder_action");const{BaseOptionComponent}=require("@html_builder/core/utils");const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const RatingOption=__exports.RatingOption=class RatingOption extends BaseOptionComponent{static template="html_builder.RatingOption";static selector=".s_rating";}
class RatingOptionPlugin extends Plugin{static id="ratingOption";static dependencies=["history","media"];selector=".s_rating";resources={builder_options:RatingOption,so_content_addition_selector:[".s_rating"],builder_actions:{SetIconsAction,CustomIconAction,ActiveIconsNumberAction,TotalIconsNumberAction,},};}
const SetIconsAction=__exports.SetIconsAction=class SetIconsAction extends BuilderAction{static id="setIcons";apply({editingElement,params:{mainParam:iconParam}}){editingElement.dataset.icon=iconParam;renderIcons(editingElement);delete editingElement.dataset.activeCustomIcon;delete editingElement.dataset.inactiveCustomIcon;}
isApplied({editingElement,params:{mainParam:iconParam}}){return getIconType(editingElement)===iconParam;}}
const CustomIconAction=__exports.CustomIconAction=class CustomIconAction extends BuilderAction{static id="customIcon";static dependencies=["media"];async load({editingElement,params:{mainParam:customParam}}){return new Promise((resolve)=>{const isCustomActive=customParam==="customActiveIcon";const media=document.createElement("i");media.className=isCustomActive?getActiveCustomIcons(editingElement):getInactiveCustomIcons(editingElement);const mediaDialogParams={visibleTabs:["ICONS"],media,save:(icon)=>{resolve(icon);},};const onClose=this.dependencies.media.openMediaDialog(mediaDialogParams,this.editable);onClose.then(resolve);});}
apply({editingElement,loadResult:savedIconEl,params:{mainParam:customParam}}){if(!savedIconEl){return;}
const isCustomActive=customParam==="customActiveIcon";const customClass=savedIconEl.className;const activeIconEls=getActiveIcons(editingElement);const inactiveIconEls=getInactiveIcons(editingElement);const iconEls=isCustomActive?activeIconEls:inactiveIconEls;iconEls.forEach((iconEl)=>(iconEl.className=customClass));const faClassActiveCustomIcons=activeIconEls.length>0?activeIconEls[0].getAttribute("class"):customClass;const faClassInactiveCustomIcons=inactiveIconEls.length>0?inactiveIconEls[0].getAttribute("class"):customClass;editingElement.dataset.activeCustomIcon=faClassActiveCustomIcons;editingElement.dataset.inactiveCustomIcon=faClassInactiveCustomIcons;editingElement.dataset.icon="custom";}}
const ActiveIconsNumberAction=__exports.ActiveIconsNumberAction=class ActiveIconsNumberAction extends BuilderAction{static id="activeIconsNumber";apply({editingElement,value}){const nbActiveIcons=parseInt(value);const nbTotalIcons=getAllIcons(editingElement).length;createIcons({editingElement:editingElement,nbActiveIcons:nbActiveIcons,nbTotalIcons:nbTotalIcons,});}
getValue({editingElement}){return getActiveIcons(editingElement).length;}}
const TotalIconsNumberAction=__exports.TotalIconsNumberAction=class TotalIconsNumberAction extends BuilderAction{static id="totalIconsNumber";apply({editingElement,value}){const nbTotalIcons=Math.max(parseInt(value),1);const nbActiveIcons=getActiveIcons(editingElement).length;createIcons({editingElement:editingElement,nbActiveIcons:nbActiveIcons,nbTotalIcons:nbTotalIcons,});}
getValue({editingElement}){return getAllIcons(editingElement).length;}}
registry.category("builder-plugins").add(RatingOptionPlugin.id,RatingOptionPlugin);function createIcons({editingElement,nbActiveIcons,nbTotalIcons}){const activeIconEl=editingElement.querySelector(".s_rating_active_icons");const inactiveIconEl=editingElement.querySelector(".s_rating_inactive_icons");const iconEls=getAllIcons(editingElement);[...iconEls].forEach((iconEl)=>iconEl.remove());for(let i=0;i<nbTotalIcons;i++){const targetEl=i<nbActiveIcons?activeIconEl:inactiveIconEl;targetEl.appendChild(document.createElement("i"));targetEl.appendChild(document.createTextNode(" "));}
renderIcons(editingElement);}
function getActiveCustomIcons(editingElement){return editingElement.dataset.activeCustomIcon||"";}
function getActiveIcons(editingElement){return editingElement.querySelectorAll(".s_rating_active_icons > i");}
function getAllIcons(editingElement){return editingElement.querySelectorAll(".s_rating_icons i");}
function getIconType(editingElement){return editingElement.dataset.icon;}
function getInactiveCustomIcons(editingElement){return editingElement.dataset.inactiveCustomIcon||"";}
function getInactiveIcons(editingElement){return editingElement.querySelectorAll(".s_rating_inactive_icons  > i");}
function renderIcons(editingElement){const iconType=getIconType(editingElement);const icons={"fa-star":"fa-star-o","fa-thumbs-up":"fa-thumbs-o-up","fa-circle":"fa-circle-o","fa-square":"fa-square-o","fa-heart":"fa-heart-o",};const faClassActiveIcons=iconType==="custom"?getActiveCustomIcons(editingElement):"fa "+iconType;const faClassInactiveIcons=iconType==="custom"?getInactiveCustomIcons(editingElement):"fa "+icons[iconType];const activeIconEls=getActiveIcons(editingElement);const inactiveIconEls=getInactiveIcons(editingElement);activeIconEls.forEach((activeIconEl)=>(activeIconEl.className=faClassActiveIcons));inactiveIconEls.forEach((inactiveIconEl)=>(inactiveIconEl.className=faClassInactiveIcons));}
return __exports;});;

/* /html_builder/static/src/plugins/separator_option_plugin.js */
odoo.define('@html_builder/plugins/separator_option_plugin',['@html_builder/core/utils','@html_editor/plugin','@web/core/registry','@html_builder/plugins/border_configurator_option'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{BorderConfigurator}=require("@html_builder/plugins/border_configurator_option");class SeparatorOptionPlugin extends Plugin{static id="separatorOption";resources={builder_options:[SeparatorOption],dropzone_selector:{selector:".s_hr",dropNear:"p, h1, h2, h3, blockquote, .s_hr",},so_content_addition_selector:[".s_hr"],is_movable_selector:{selector:".s_hr",direction:"vertical"},};}
const SeparatorOption=__exports.SeparatorOption=class SeparatorOption extends BaseOptionComponent{static template="html_builder.SeparatorOption";static selector=".s_hr";static applyTo="hr";static components={BorderConfigurator};}
registry.category("builder-plugins").add(SeparatorOptionPlugin.id,SeparatorOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/shadow_option.js */
odoo.define('@html_builder/plugins/shadow_option',['@html_builder/core/utils'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const ShadowOption=__exports.ShadowOption=class ShadowOption extends BaseOptionComponent{static template="html_builder.ShadowOption";static props={setShadowModeAction:{type:String,optional:true},setShadowAction:{type:String,optional:true},};static defaultProps={setShadowModeAction:"setShadowMode",setShadowAction:"setShadow",};}
return __exports;});;

/* /html_builder/static/src/plugins/shadow_option_plugin.js */
odoo.define('@html_builder/plugins/shadow_option_plugin',['@html_builder/core/builder_action','@html_editor/plugin','@web/core/registry','@html_builder/utils/utils_css'],function(require){'use strict';let __exports={};const{BuilderAction}=require("@html_builder/core/builder_action");const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{parseBoxShadow}=require("@html_builder/utils/utils_css");const shadowClass="shadow";const ShadowOptionPlugin=__exports.ShadowOptionPlugin=class ShadowOptionPlugin extends Plugin{static id="shadowOption";resources={builder_actions:{SetShadowModeAction,SetShadowAction,},};}
__exports.getDefaultShadow=getDefaultShadow;function getDefaultShadow(mode){const el=document.createElement("div");el.classList.add(shadowClass);document.body.appendChild(el);const shadow=`${getComputedStyle(el).boxShadow}${mode === "inset" ? " inset" : ""}`;el.remove();return shadow;}
function getShadowMode(editingElement){const currentBoxShadow=getComputedStyle(editingElement)["box-shadow"];if(currentBoxShadow==="none"){return"none";}
if(currentBoxShadow.includes("inset")){return"inset";}
if(!currentBoxShadow.includes("inset")&&currentBoxShadow!=="none"){return"outset";}}
function setBoxShadow(editingElement,value){editingElement.style.setProperty("box-shadow",value,"important");}
__exports.getCurrentShadow=getCurrentShadow;function getCurrentShadow(editingElement){return parseShadow(getComputedStyle(editingElement)["box-shadow"]);}
function parseShadow(value){if(!value||value==="none"){return{};}
return parseBoxShadow(value);}
__exports.shadowToString=shadowToString;function shadowToString(shadow){if(!shadow){return"";}
return`${shadow.color} ${shadow.offsetX} ${shadow.offsetY} ${shadow.blur} ${shadow.spread} ${
        shadow.mode ? shadow.mode : ""
    }`;}
registry.category("builder-plugins").add(ShadowOptionPlugin.id,ShadowOptionPlugin);const SetShadowModeAction=__exports.SetShadowModeAction=class SetShadowModeAction extends BuilderAction{static id="setShadowMode";isApplied({editingElement,value:shadowMode}){return shadowMode===getShadowMode(editingElement);}
getValue({editingElement}){return getShadowMode(editingElement,"mode");}
apply({editingElement,value:shadowMode}){if(shadowMode==="none"){editingElement.classList.remove(shadowClass);setBoxShadow(editingElement,"");return;}
if(!editingElement.classList.contains(shadowClass)){editingElement.classList.add(shadowClass);}
if(editingElement.style["box-shadow"]===""){setBoxShadow(editingElement,getDefaultShadow(shadowMode));}else{const shadow=getCurrentShadow(editingElement);if(shadowMode==="inset"){shadow.mode="inset";}else{shadow.mode="";}
setBoxShadow(editingElement,shadowToString(shadow));}}}
const SetShadowAction=__exports.SetShadowAction=class SetShadowAction extends BuilderAction{static id="setShadow";apply({editingElement,params:{mainParam:attributeName},value}){const shadow=getCurrentShadow(editingElement);shadow[attributeName]=value;setBoxShadow(editingElement,shadowToString(shadow));}
getValue({editingElement,params:{mainParam:attributeName}}){return getCurrentShadow(editingElement)[attributeName];}}
return __exports;});;

/* /html_builder/static/src/plugins/shape/shape_selector.js */
odoo.define('@html_builder/plugins/shape/shape_selector',['@odoo/owl','@html_builder/core/img_group','@html_builder/core/utils','@web/core/utils/timing','@html_builder/plugins/image/image_helpers','@web/core/hotkeys/hotkey_hook','@web/core/utils/hooks'],function(require){'use strict';let __exports={};const{useRef,useState}=require("@odoo/owl");const{ImgGroup}=require("@html_builder/core/img_group");const{BaseOptionComponent}=require("@html_builder/core/utils");const{useThrottleForAnimation}=require("@web/core/utils/timing");const{getShapeURL}=require("@html_builder/plugins/image/image_helpers");const{useHotkey}=require("@web/core/hotkeys/hotkey_hook");const{useAutofocus}=require("@web/core/utils/hooks");const ShapeSelector=__exports.ShapeSelector=class ShapeSelector extends BaseOptionComponent{static template="html_builder.shapeSelector";static props={onClose:Function,selectorTitle:String,shapeGroups:Object,shapeActionId:String,buttonWrapperClassName:{type:String,optional:true},imgThroughDiv:{type:Boolean,optional:true},getShapeUrl:{type:Function,optional:true},};static components={ImgGroup};setup(){super.setup();this.rootRef=useRef("root");this.tabsRef=useRef("tabs");this.state=useState({activeGroup:"basic"});this.onScroll=useThrottleForAnimation(this._onScroll);useHotkey("escape",()=>this.props.onClose());useAutofocus({refName:"backButton"});}
getShapeUrl(shapePath){return this.props.getShapeUrl?this.props.getShapeUrl(shapePath):getShapeURL(shapePath);}
getShapeClass(shapePath){return`o_${shapePath.replaceAll("/", "_")}`;}
scrollToShapes(id){const container=this.rootRef.el;const selectedElement=container?.querySelector(`[data-shape-group-id="${id}"]`);if(container&&selectedElement){container.scrollTop=selectedElement.offsetTop-container.offsetTop;}}
_onScroll(){const pagerContainerRect=this.rootRef.el.getBoundingClientRect();const threshold=pagerContainerRect.height/2;const anchorEls=this.tabsRef.el.querySelectorAll(".o-hb-select-pager-tab");for(const anchorEl of anchorEls){const groupId=anchorEl.dataset.groupId;const sectionEl=this.rootRef.el.querySelector(`[data-shape-group-id="${groupId}"]`);const nextSectionEl=sectionEl.nextElementSibling;const sectionTop=sectionEl.getBoundingClientRect().top-pagerContainerRect.top;const nextSectionTop=nextSectionEl&&nextSectionEl.getBoundingClientRect().top-pagerContainerRect.top;if(sectionTop<threshold&&(!nextSectionEl||nextSectionTop>threshold)){this.state.activeGroup=groupId;}}}}
return __exports;});;

/* /html_builder/static/src/plugins/size_option_plugin.js */
odoo.define('@html_builder/plugins/size_option_plugin',['@html_builder/utils/option_sequence','@html_editor/utils/resource','@html_editor/plugin','@web/core/registry','@html_builder/core/utils'],function(require){'use strict';let __exports={};const{after,BLOCK_ALIGN}=require("@html_builder/utils/option_sequence");const{withSequence}=require("@html_editor/utils/resource");const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{BaseOptionComponent}=require("@html_builder/core/utils");const SizeOption=__exports.SizeOption=class SizeOption extends BaseOptionComponent{static template="html_builder.SizeOption";static selector=".s_alert";}
class SizeOptionPlugin extends Plugin{static id="sizeOption";resources={builder_options:[withSequence(after(BLOCK_ALIGN),SizeOption)],};}
registry.category("builder-plugins").add(SizeOptionPlugin.id,SizeOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/text_alignment_option_plugin.js */
odoo.define('@html_builder/plugins/text_alignment_option_plugin',['@html_builder/utils/option_sequence','@html_editor/plugin','@web/core/registry','@html_editor/utils/resource','@html_builder/core/utils'],function(require){'use strict';let __exports={};const{TEXT_ALIGNMENT}=require("@html_builder/utils/option_sequence");const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{withSequence}=require("@html_editor/utils/resource");const{BaseOptionComponent}=require("@html_builder/core/utils");class TextAlignmentOptionPlugin extends Plugin{static id="textAlignmentOption";resources={builder_options:[withSequence(TEXT_ALIGNMENT,TextAlignmentOption)],};}
const TextAlignmentOption=__exports.TextAlignmentOption=class TextAlignmentOption extends BaseOptionComponent{static template="html_builder.TextAlignmentOption";static selector=".s_share, .s_text_highlight, .s_social_media";}
registry.category("builder-plugins").add(TextAlignmentOptionPlugin.id,TextAlignmentOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/utils.js */
odoo.define('@html_builder/plugins/utils',[],function(require){'use strict';let __exports={};const dynamicSVGSelector=__exports.dynamicSVGSelector="img[src^='/html_editor/shape/'], img[src^='/web_editor/shape/']";__exports.applyFunDependOnSelectorAndExclude=applyFunDependOnSelectorAndExclude;function applyFunDependOnSelectorAndExclude(fn,rootEl,selectorParams){const editingEls=getEditingEls(rootEl,selectorParams);if(!editingEls.length){return false;}
return Promise.all(editingEls.map((el)=>fn(el)));}
__exports.getEditingEls=getEditingEls;function getEditingEls(rootEl,{selector,exclude,applyTo}){const closestSelector=rootEl.closest(selector);let editingEls=closestSelector?[closestSelector]:[...rootEl.querySelectorAll(selector)];if(exclude){editingEls=editingEls.filter((selectorEl)=>!selectorEl.matches(exclude));}
if(!applyTo){return editingEls;}
const targetEls=[];for(const editingEl of editingEls){const applyToEls=applyTo?editingEl.querySelectorAll(applyTo):[editingEl];targetEls.push(...applyToEls);}
return targetEls;}
return __exports;});;

/* /html_builder/static/src/plugins/vertical_alignment_option.js */
odoo.define('@html_builder/plugins/vertical_alignment_option',['@html_builder/plugins/base_vertical_alignment_option'],function(require){'use strict';let __exports={};const{BaseVerticalAlignmentOption}=require("@html_builder/plugins/base_vertical_alignment_option");const VerticalAlignmentOption=__exports.VerticalAlignmentOption=class VerticalAlignmentOption extends BaseVerticalAlignmentOption{static selector=".s_text_image, .s_image_text, .s_three_columns, .s_showcase, .s_numbers, .s_faq_collapse, .s_references, .s_accordion_image, .s_shape_image, .s_reviews_wall";static applyTo=".row";static name="verticalAlignmentOption";}
return __exports;});;

/* /html_builder/static/src/plugins/vertical_alignment_option_plugin.js */
odoo.define('@html_builder/plugins/vertical_alignment_option_plugin',['@html_editor/plugin','@web/core/registry','@html_builder/core/core_builder_action_plugin','@html_builder/plugins/vertical_alignment_option','@html_editor/utils/resource','@html_builder/utils/option_sequence'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{ClassAction}=require("@html_builder/core/core_builder_action_plugin");const{VerticalAlignmentOption}=require("@html_builder/plugins/vertical_alignment_option");const{withSequence}=require("@html_editor/utils/resource");const{VERTICAL_ALIGNMENT}=require("@html_builder/utils/option_sequence");const VerticalAlignmentOptionPlugin=__exports.VerticalAlignmentOptionPlugin=class VerticalAlignmentOptionPlugin extends Plugin{static id="verticalAlignmentOption";resources={builder_options:[withSequence(VERTICAL_ALIGNMENT,VerticalAlignmentOption)],builder_actions:{SetVerticalAlignmentAction,},};}
const SetVerticalAlignmentAction=__exports.SetVerticalAlignmentAction=class SetVerticalAlignmentAction extends ClassAction{static id="setVerticalAlignment";getPriority({params:{mainParam:classNames}={mainParam:""}}){return classNames==="align-items-stretch"?0:1;}
isApplied({params:{mainParam:classNames}}){if(classNames==="align-items-stretch"){return true;}
return super.isApplied(...arguments);}}
registry.category("builder-plugins").add(VerticalAlignmentOptionPlugin.id,VerticalAlignmentOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/vertical_justify_option_plugin.js */
odoo.define('@html_builder/plugins/vertical_justify_option_plugin',['@html_builder/utils/option_sequence','@html_editor/plugin','@web/core/registry','@html_editor/utils/resource','@html_builder/core/utils'],function(require){'use strict';let __exports={};const{END}=require("@html_builder/utils/option_sequence");const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{withSequence}=require("@html_editor/utils/resource");const{BaseOptionComponent}=require("@html_builder/core/utils");class VerticalJustifyOptionPlugin extends Plugin{static id="verticalJustifyOption";resources={builder_options:[withSequence(END,VerticalJustifyOption)],};}
const VerticalJustifyOption=__exports.VerticalJustifyOption=class VerticalJustifyOption extends BaseOptionComponent{static template="html_builder.VerticalJustifyOption";static selector=".s_masonry_block .o_grid_item, .s_quadrant .o_grid_item, .s_banner_categories .o_grid_item";static exclude=".o_grid_item_image";}
registry.category("builder-plugins").add(VerticalJustifyOptionPlugin.id,VerticalJustifyOptionPlugin);return __exports;});;

/* /html_builder/static/src/plugins/width_option_plugin.js */
odoo.define('@html_builder/plugins/width_option_plugin',['@html_editor/plugin','@html_editor/utils/resource','@web/core/registry','@html_builder/utils/option_sequence','@html_builder/core/utils'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{registry}=require("@web/core/registry");const{WIDTH}=require("@html_builder/utils/option_sequence");const{BaseOptionComponent}=require("@html_builder/core/utils");class WidthOptionPlugin extends Plugin{static id="widthOption";resources={builder_options:[withSequence(WIDTH,WidthOption)],};}
const WidthOption=__exports.WidthOption=class WidthOption extends BaseOptionComponent{static template="html_builder.WidthOption";static selector=".s_alert, .s_blockquote, .s_text_highlight";static name="widthOption";}
registry.category("builder-plugins").add(WidthOptionPlugin.id,WidthOptionPlugin);return __exports;});;

/* /html_builder/static/src/sidebar/block_tab.js */
odoo.define('@html_builder/sidebar/block_tab',['@odoo/owl','@web/core/utils/hooks','@web/core/tooltip/tooltip','@web/core/utils/scrolling','@web/core/l10n/translation','@web/core/utils/ui','@html_editor/utils/drag_and_drop','@html_editor/utils/formatting','@html_builder/snippets/snippet_service','@html_builder/utils/scrolling','@html_builder/sidebar/snippet','@html_builder/sidebar/custom_inner_snippet'],function(require){'use strict';let __exports={};const{Component,onMounted,onWillDestroy,useRef,useState}=require("@odoo/owl");const{useService}=require("@web/core/utils/hooks");const{Tooltip}=require("@web/core/tooltip/tooltip");const{closestScrollableY,getScrollingElement,isScrollableY}=require("@web/core/utils/scrolling");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{closest}=require("@web/core/utils/ui");const{useDragAndDrop}=require("@html_editor/utils/drag_and_drop");const{getCSSVariableValue}=require("@html_editor/utils/formatting");const{useSnippets}=require("@html_builder/snippets/snippet_service");const{scrollTo}=require("@html_builder/utils/scrolling");const{Snippet}=require("@html_builder/sidebar/snippet");const{CustomInnerSnippet}=require("@html_builder/sidebar/custom_inner_snippet");const BlockTab=__exports.BlockTab=class BlockTab extends Component{static template="html_builder.BlockTab";static components={Snippet,CustomInnerSnippet};static props={snippetsName:String,};setup(){this.dialog=useService("dialog");this.orm=useService("orm");this.popover=useService("popover");this.snippetModel=useSnippets(this.props.snippetsName);this.blockTabRef=useRef("block-tab");this.state=useState({ongoingInsertion:false});onMounted(()=>{this.makeSnippetDraggable();});onWillDestroy(()=>{this.draggableComponent?.destroy();});}
get document(){return this.env.editor.document;}
get editable(){return this.env.editor.editable;}
get shared(){return this.env.editor.shared;}
onSnippetGroupClick(snippet){this.shared.operation.next(async()=>{this.cancelDragAndDrop=this.shared.history.makeSavePoint();this.dragState={};let snippetEl;this.state.ongoingInsertion=true;await new Promise((resolve)=>{this.snippetModel.openSnippetDialog(snippet,{onSelect:(snippet)=>{snippetEl=snippet.content.cloneNode(true);const selectors=this.shared.dropzone.getSelectors(snippetEl);let dropzoneEls=this.shared.dropzone.activateDropzones(selectors);const filteredDropzoneEls=dropzoneEls.filter((dropzoneEl)=>!dropzoneEl.closest("[data-snippet]:not(:has(> .modal))"));dropzoneEls=filteredDropzoneEls.length?filteredDropzoneEls:dropzoneEls;this.editable.querySelectorAll(".oe_drop_zone").forEach((dropzoneEl)=>dropzoneEl.classList.add("invisible"));const iframeWindow=this.document.defaultView;const viewPortCenterPoint={x:iframeWindow.innerWidth/2,y:iframeWindow.innerHeight/2,};const validDropzoneEls=dropzoneEls.filter((el)=>el.getBoundingClientRect().top>=viewPortCenterPoint.y/2);const closestDropzoneEl=closest(validDropzoneEls,viewPortCenterPoint)||dropzoneEls.at(-1);closestDropzoneEl.after(snippetEl);this.shared.dropzone.removeDropzones();return snippetEl;},onClose:()=>{resolve();},},this.env.editor);});if(snippetEl){await scrollTo(snippetEl,{extraOffset:50});await this.processDroppedSnippet(snippetEl);}
this.state.ongoingInsertion=false;delete this.cancelDragAndDrop;},{withLoadingEffect:false,shouldInterceptClick:true,canTimeout:false,});}
async onSnippetGroupDrop(snippet,hookEl){this.state.ongoingInsertion=true;const hookParentEl=hookEl.parentElement;this.snippetModel.snippetStructures.forEach((snippet)=>{const{selectorChildren}=this.shared.dropzone.getSelectors(snippet.content);snippet.isExcluded=![...selectorChildren].some((el)=>el===hookParentEl);});let selectedSnippetEl;await new Promise((resolve)=>{this.snippetModel.openSnippetDialog(snippet,{onSelect:(snippet)=>{selectedSnippetEl=snippet.content.cloneNode(true);hookEl.replaceWith(selectedSnippetEl);return selectedSnippetEl;},onClose:()=>{if(!selectedSnippetEl){hookEl.remove();}
this.snippetModel.snippetStructures.forEach((snippet)=>delete snippet.isExcluded);resolve();},},this.env.editor);});if(selectedSnippetEl){await scrollTo(selectedSnippetEl,{extraOffset:50});await this.processDroppedSnippet(selectedSnippetEl);}else{this.cancelDragAndDrop();}
this.state.ongoingInsertion=false;delete this.cancelDragAndDrop;}
showSnippetTooltip(ev){const snippetEl=ev.currentTarget.closest(".o_snippet.o_draggable");if(snippetEl){this.hideSnippetToolTip?.();this.hideSnippetToolTip=this.popover.add(snippetEl,Tooltip,{tooltip:_t("Drag and drop the building block"),});setTimeout(this.hideSnippetToolTip,1500);}}
makeSnippetDraggable(){let dropzoneEls=[];let dragAndDropResolve;let snippet,snippetEl,isSnippetGroup;const iframeWindow=this.document.defaultView!==window?this.document.defaultView:false;const scrollingElement=()=>{let scrollingElement=this.shared.dropzone.getDropRootElement()||getScrollingElement(this.document)||this.editable.querySelector(".o_editable");if(!isScrollableY(scrollingElement)){scrollingElement=closestScrollableY(this.document.defaultView.frameElement)??scrollingElement;}
return scrollingElement;};const dragAndDropOptions={ref:{el:this.blockTabRef.el},iframeWindow,cursor:"move",el:this.blockTabRef.el,elements:".o_snippet.o_draggable",scrollingElement,handle:".o_snippet_thumbnail:not(.o_we_ongoing_insertion .o_snippet_thumbnail)",dropzones:()=>dropzoneEls,helper:({element,helperOffset})=>{snippet=element;const draggedEl=element.cloneNode(true);draggedEl.querySelectorAll(".o_snippet_thumbnail_title, .o_snippet_thumbnail_area, .rename-delete-buttons").forEach((el)=>el.remove());draggedEl.style.position="fixed";document.body.append(draggedEl);const thumbnailImgEl=element.querySelector(".o_snippet_thumbnail_img");helperOffset.x=thumbnailImgEl.offsetWidth/2;helperOffset.y=thumbnailImgEl.offsetHeight/2;return draggedEl;},onDragStart:({element})=>{const dragAndDropProm=new Promise((resolve)=>(dragAndDropResolve=()=>resolve()));this.shared.operation.next(async()=>await dragAndDropProm,{withLoadingEffect:false,canTimeout:false,});const restoreDragSavePoint=this.shared.history.makeSavePoint();this.cancelDragAndDrop=()=>{this.shared.dropzone.removeDropzones();this.dragState.restoreCallbacks?.forEach((restore)=>restore());restoreDragSavePoint();};this.hideSnippetToolTip?.();this.document.body.classList.add("oe_dropzone_active");this.state.ongoingInsertion=true;this.dragState={};dropzoneEls=[];const restoreCallbacks=[];for(const prepareDrag of this.env.editor.getResource("on_prepare_drag_handlers")){const restore=prepareDrag();restoreCallbacks.unshift(restore);}
this.dragState.restoreCallbacks=restoreCallbacks;const category=element.closest(".o_snippets_container").id;const id=element.dataset.id;snippet=this.snippetModel.getSnippet(category,id);snippetEl=snippet.content.cloneNode(true);isSnippetGroup=category==="snippet_groups";this.document.body.appendChild(snippetEl);const snippetStyle=window.getComputedStyle(snippetEl);const isInlineSnippet=snippetStyle.display.includes("inline");snippetEl.remove();const dynamicSvgEls=[...snippetEl.querySelectorAll('img[src^="/html_editor/shape/"], img[src^="/web_editor/shape/"]'),];dynamicSvgEls.forEach((dynamicSvgEl)=>{const colorCustomizedURL=new URL(dynamicSvgEl.getAttribute("src"),window.location.origin);colorCustomizedURL.searchParams.forEach((value,key)=>{const match=key.match(/^c([1-5])$/);if(match){colorCustomizedURL.searchParams.set(key,getCSSVariableValue(`o-color-${match[1]}`,this.document.defaultView.getComputedStyle(this.document.documentElement)));}});dynamicSvgEl.src=colorCustomizedURL.pathname+colorCustomizedURL.search;});Object.assign(this.dragState,{draggedEl:snippetEl,snippetEl,snippet});const withGrids=!isSnippetGroup&&(this.env.editor.config.isMobileView(this.editable)?"filterOnly":true);const selectors=this.shared.dropzone.getSelectors(snippetEl,false,withGrids);dropzoneEls=this.shared.dropzone.activateDropzones(selectors,{toInsertInline:isInlineSnippet,});this.env.editor.dispatchTo("on_snippet_dragged_handlers",{snippetEl,dragState:this.dragState,});},dropzoneOver:({dropzone})=>{const dropzoneEl=dropzone.el;if(isSnippetGroup){dropzoneEl.classList.add("o_dropzone_highlighted");this.dragState.currentDropzoneEl=dropzoneEl;return;}
dropzoneEl.after(this.dragState.draggedEl);dropzoneEl.classList.add("invisible");this.dragState.currentDropzoneEl=dropzoneEl;this.env.editor.dispatchTo("on_snippet_over_dropzone_handlers",{snippetEl,dragState:this.dragState,});},onDrag:({x,y})=>{if(!this.dragState.currentDropzoneEl){return;}
this.env.editor.dispatchTo("on_snippet_move_handlers",{snippetEl,dragState:this.dragState,x,y,});},dropzoneOut:({dropzone})=>{const dropzoneEl=dropzone.el;if(isSnippetGroup){dropzoneEl.classList.remove("o_dropzone_highlighted");this.dragState.currentDropzoneEl=null;return;}
this.env.editor.dispatchTo("on_snippet_out_dropzone_handlers",{snippetEl,dragState:this.dragState,});this.dragState.draggedEl.remove();dropzoneEl.classList.remove("invisible");this.dragState.currentDropzoneEl=null;},onDragEnd:async({x,y,helper})=>{this.document.body.classList.remove("oe_dropzone_active");let currentDropzoneEl=this.dragState.currentDropzoneEl;const isDroppedOver=!!currentDropzoneEl;if(!currentDropzoneEl){const blockTabRect=this.blockTabRef.el.getBoundingClientRect();const helperWidth=helper.getBoundingClientRect().width;const isRTL=document.body.classList.contains("o_rtl");const isOutOfBlockTab=isRTL?blockTabRect.left+blockTabRect.width<x-helperWidth/2:x+helperWidth/2<blockTabRect.left;if(y>3&&isOutOfBlockTab){const closestDropzoneEl=closest(dropzoneEls,{x,y});if(closestDropzoneEl){currentDropzoneEl=closestDropzoneEl;}}}
if(currentDropzoneEl){let draggedEl=this.dragState.draggedEl;if(isDroppedOver){this.env.editor.dispatchTo("on_snippet_dropped_over_handlers",{droppedEl:draggedEl,dragState:this.dragState,});}else{currentDropzoneEl.after(draggedEl);this.env.editor.dispatchTo("on_snippet_dropped_near_handlers",{droppedEl:draggedEl,dropzoneEl:currentDropzoneEl,dragState:this.dragState,});}
draggedEl=this.dragState.draggedEl;draggedEl.remove();this.dragState.restoreCallbacks.forEach((restore)=>restore());this.dragState.restoreCallbacks=null;currentDropzoneEl.after(draggedEl);this.shared.dropzone.removeDropzones();if(!isSnippetGroup){await this.processDroppedSnippet(snippetEl);delete this.cancelDragAndDrop;}else{this.shared.operation.next(async()=>{await this.onSnippetGroupDrop(snippet,snippetEl);},{withLoadingEffect:false,shouldInterceptClick:true,canTimeout:false,});}}else{this.cancelDragAndDrop();delete this.cancelDragAndDrop;}
this.state.ongoingInsertion=false;dragAndDropResolve();},};this.draggableComponent=useDragAndDrop(dragAndDropOptions);}
async processDroppedSnippet(snippetEl){this.updateDroppedSnippet(snippetEl);for(const onSnippetDropped of this.env.editor.getResource("on_snippet_dropped_handlers")){const cancel=await onSnippetDropped({snippetEl,dragState:this.dragState});if(cancel){this.cancelDragAndDrop();return;}
if(this.dragState.replacedSnippetEl){if(this.dragState.draggedEl===snippetEl){this.dragState.draggedEl=this.dragState.replacedSnippetEl;}
snippetEl=this.dragState.replacedSnippetEl;delete this.dragState.replacedSnippetEl;}}
this.env.editor.config.updateInvisibleElementsPanel();this.shared.disableSnippets.disableUndroppableSnippets();this.shared.history.addStep();}
updateDroppedSnippet(snippetEl){if(snippetEl.classList.contains("o_snippet_drop_in_only")){snippetEl.classList.remove("o_snippet_drop_in_only");if(snippetEl.classList.length===0){snippetEl.removeAttribute("class");}
delete snippetEl.dataset.snippet;delete snippetEl.dataset.name;}}}
return __exports;});;

/* /html_builder/static/src/sidebar/custom_inner_snippet.js */
odoo.define('@html_builder/sidebar/custom_inner_snippet',['@html_builder/core/img','@odoo/owl','@web/core/l10n/translation','@web/core/utils/hooks'],function(require){'use strict';let __exports={};const{Img}=require("@html_builder/core/img");const{Component,useState,useRef}=require("@odoo/owl");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{useAutofocus}=require("@web/core/utils/hooks");const CustomInnerSnippet=__exports.CustomInnerSnippet=class CustomInnerSnippet extends Component{static template="html_builder.CustomInnerSnippet";static props={snippetModel:{type:Object},snippet:{type:Object},onClickHandler:{type:Function},disabledTooltip:{type:String},};static components={Img};setup(){this.renameInputRef=useRef("rename-input");useAutofocus({refName:"rename-input"});this.state=useState({isRenaming:false});this.renameButtonTooltip=_t("Rename %(snippetTitle)s",{snippetTitle:this.snippet.title,});this.deleteButtonTooltip=_t("Delete %(snippetTitle)s",{snippetTitle:this.snippet.title,});}
get snippet(){return this.props.snippet;}
toggleRenamingState(){this.state.isRenaming=!this.state.isRenaming;}
onConfirmRename(){this.props.snippetModel.renameCustomSnippet(this.snippet,this.renameInputRef.el.value);this.toggleRenamingState();}}
return __exports;});;

/* /html_builder/static/src/sidebar/customize_component.js */
odoo.define('@html_builder/sidebar/customize_component',['@odoo/owl','@html_builder/utils/utils','@html_builder/core/img'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const{useOptionsSubEnv}=require("@html_builder/utils/utils");const{Img}=require("@html_builder/core/img");const CustomizeComponent=__exports.CustomizeComponent=class CustomizeComponent extends Component{static template="html_builder.CustomizeComponent";static components={Img};static props={editingElements:{type:Array},comp:{type:Function},compProps:{type:Object},};setup(){useOptionsSubEnv(()=>this.props.editingElements);}}
return __exports;});;

/* /html_builder/static/src/sidebar/customize_tab.js */
odoo.define('@html_builder/sidebar/customize_tab',['@odoo/owl','@html_builder/sidebar/option_container','@html_builder/core/utils','@html_builder/sidebar/customize_component'],function(require){'use strict';let __exports={};const{Component,onWillUpdateProps,useState}=require("@odoo/owl");const{OptionsContainer}=require("@html_builder/sidebar/option_container");const{useVisibilityObserver}=require("@html_builder/core/utils");const{CustomizeComponent}=require("@html_builder/sidebar/customize_component");const CustomizeTab=__exports.CustomizeTab=class CustomizeTab extends Component{static template="html_builder.CustomizeTab";static components={CustomizeComponent,OptionsContainer};static props={currentOptionsContainers:{type:Array,optional:true},snippetModel:{type:Object},};static defaultProps={currentOptionsContainers:[],};setup(){this.state=useState({hasContent:true,});this.customizeComponent=useState(this.env.editor.shared.customizeTab.getCustomizeComponent());useVisibilityObserver("content",(hasContent)=>{this.state.hasContent=hasContent;});onWillUpdateProps((nextProps)=>{if(!this.state.hasContent&&nextProps.currentOptionsContainers.length>0&&nextProps.currentOptionsContainers!==this.props.currentOptionsContainers){this.state.hasContent=true;}});}
getCurrentOptionsContainers(){const currentOptionsContainers=this.props.currentOptionsContainers;if(!currentOptionsContainers.length){return this.env.editor.shared.builderOptions.getPageContainers();}
return currentOptionsContainers;}}
return __exports;});;

/* /html_builder/static/src/sidebar/invisible_elements_panel.js */
odoo.define('@html_builder/sidebar/invisible_elements_panel',['@odoo/owl','@html_builder/utils/utils'],function(require){'use strict';let __exports={};const{Component,onWillStart,onWillUpdateProps,useState}=require("@odoo/owl");const{getSnippetName,isElementInViewport}=require("@html_builder/utils/utils");const InvisibleElementsPanel=__exports.InvisibleElementsPanel=class InvisibleElementsPanel extends Component{static template="html_builder.InvisibleElementsPanel";static props={invisibleEls:{type:Array},invisibleSelector:{type:String},};setup(){this.state=useState({invisibleEntries:null});onWillStart(()=>this.updateInvisibleElementsPanel(this.props.invisibleEls));onWillUpdateProps((nextProps)=>{const{invisibleEls,invisibleSelector}=nextProps;this.updateInvisibleElementsPanel(invisibleEls,invisibleSelector);});}
get shared(){return this.env.editor.shared;}
updateInvisibleElementsPanel(invisibleEls,invisibleSelector=this.props.invisibleSelector){const descendantPerSnippet=new Map();const rootInvisibleSnippetEls=invisibleEls.filter((invisibleSnippetEl)=>{const ancestorInvisibleEl=invisibleSnippetEl.parentElement.closest(invisibleSelector);if(!ancestorInvisibleEl){return true;}
const descendantSnippets=descendantPerSnippet.get(ancestorInvisibleEl)||[];descendantPerSnippet.set(ancestorInvisibleEl,[...descendantSnippets,invisibleSnippetEl,]);return false;});const createInvisibleEntries=(snippetEls,parentEl=null)=>snippetEls.map((snippetEl)=>{const descendantSnippetEls=descendantPerSnippet.get(snippetEl);const invisibleElement={snippetEl:snippetEl,name:getSnippetName(snippetEl),isRootParent:!parentEl&&!!descendantSnippetEls,isDescendant:!!parentEl,isVisible:snippetEl.dataset.invisible!=="1",children:[],parentEl,};if(descendantSnippetEls){invisibleElement.children=createInvisibleEntries(descendantSnippetEls,invisibleElement);}
return invisibleElement;});this.state.invisibleEntries=createInvisibleEntries(rootInvisibleSnippetEls);}
toggleElementVisibility(invisibleEntry){const snippetEl=invisibleEntry.snippetEl;if(invisibleEntry.isVisible){invisibleEntry.isVisible=false;this.shared.visibility.toggleTargetVisibility(snippetEl,false);this.shared.builderOptions.deactivateContainers();}else{invisibleEntry.isVisible=true;this.shared.visibility.toggleTargetVisibility(snippetEl,true);this.env.editor.dispatchTo("on_reveal_target_handlers",snippetEl);this.shared.builderOptions.updateContainers(snippetEl);if(!isElementInViewport(snippetEl)&&!snippetEl.matches(".s_popup")){snippetEl.scrollIntoView({behavior:"smooth",block:"start"});}}
this.shared.disableSnippets.disableUndroppableSnippets();}}
return __exports;});;

/* /html_builder/static/src/sidebar/option_container.js */
odoo.define('@html_builder/sidebar/option_container',['@html_builder/plugins/border_configurator_option','@html_builder/plugins/shadow_option','@html_builder/utils/utils','@odoo/owl','@web/core/user','@web/core/utils/hooks','@html_builder/core/operation_plugin','@html_builder/core/utils','@html_builder/core/remove_plugin','@html_builder/core/clone_plugin'],function(require){'use strict';let __exports={};const{BorderConfigurator}=require("@html_builder/plugins/border_configurator_option");const{ShadowOption}=require("@html_builder/plugins/shadow_option");const{getSnippetName,useOptionsSubEnv}=require("@html_builder/utils/utils");const{onWillStart,onWillUpdateProps}=require("@odoo/owl");const{user}=require("@web/core/user");const{useService}=require("@web/core/utils/hooks");const{useOperation}=require("@html_builder/core/operation_plugin");const{BaseOptionComponent,useApplyVisibility,useDomState,useGetItemValue,useVisibilityObserver,}=require("@html_builder/core/utils");const{isRemovable}=require("@html_builder/core/remove_plugin");const{isClonable}=require("@html_builder/core/clone_plugin");const OptionsContainer=__exports.OptionsContainer=class OptionsContainer extends BaseOptionComponent{static template="html_builder.OptionsContainer";static dependencies=["builderOptions","overlayButtons","builderOverlay","remove","clone"];static components={BorderConfigurator,ShadowOption,};static props={snippetModel:{type:Object},options:{type:Array},editingElement:true,isRemovable:false,removeDisabledReason:{type:String,optional:true},isClonable:false,cloneDisabledReason:{type:String,optional:true},optionTitleComponents:{type:Array,optional:true},containerTopButtons:{type:Array},containerTitle:{type:Object,optional:true},headerMiddleButtons:{type:Array,optional:true},};static defaultProps={containerTitle:{},headerMiddleButtons:[],optionTitleComponents:[],};setup(){useOptionsSubEnv(()=>[this.props.editingElement]);super.setup();this.notification=useService("notification");this.getItemValue=useGetItemValue();useVisibilityObserver("content",useApplyVisibility("root"));this.callOperation=useOperation();this.domState=useDomState((editingElement)=>({isRemovable:isRemovable(editingElement),removeDisabledReason:this.dependencies.builderOptions.getRemoveDisabledReason(editingElement),isClonable:isClonable(editingElement),cloneDisabledReason:this.dependencies.builderOptions.getCloneDisabledReason(editingElement),}));this.hasGroup={};onWillStart(async()=>{await this.updateAccessGroup(this.props.options);});onWillUpdateProps(async(nextProps)=>{await this.updateAccessGroup(nextProps.options);});}
async updateAccessGroup(options){const proms=[];const groups=[...new Set(options.flatMap((o)=>o.groups||[]))];for(const group of groups){proms.push(user.hasGroup(group).then((result)=>{this.hasGroup[group]=result;}));}
await Promise.all(proms);}
hasAccess(groups){if(!groups){return true;}
return groups.every((group)=>this.hasGroup[group]);}
get title(){let title;for(const option of this.props.options){if(option.getSnippetTitle){title=option.getSnippetTitle.call(this);continue;}
title=option.title||title;}
const titleExtraInfo=this.props.containerTitle.getTitleExtraInfo?this.props.containerTitle.getTitleExtraInfo(this.props.editingElement):"";return(title||getSnippetName(this.env.getEditingElement()))+titleExtraInfo;}
selectElement(){this.dependencies.builderOptions.updateContainers(this.props.editingElement);}
toggleOverlayPreview(el,show){if(show){this.dependencies.overlayButtons.hideOverlayButtons();this.dependencies.builderOverlay.showOverlayPreview(el);}else{this.dependencies.overlayButtons.showOverlayButtons();this.dependencies.builderOverlay.hideOverlayPreview(el);}}
onPointerEnter(){this.toggleOverlayPreview(this.props.editingElement,true);}
onPointerLeave(){this.toggleOverlayPreview(this.props.editingElement,false);}
removeElement(){this.callOperation(()=>{this.dependencies.remove.removeElement(this.props.editingElement);});}
cloneElement(){this.callOperation(async()=>{await this.dependencies.clone.cloneElement(this.props.editingElement,{activateClone:false,});});}
isLegacyOption(option){return typeof option==="object";}}
return __exports;});;

/* /html_builder/static/src/sidebar/snippet.js */
odoo.define('@html_builder/sidebar/snippet',['@html_builder/core/img','@odoo/owl'],function(require){'use strict';let __exports={};const{Img}=require("@html_builder/core/img");const{Component}=require("@odoo/owl");const Snippet=__exports.Snippet=class Snippet extends Component{static template="html_builder.Snippet";static components={Img};static props={snippetModel:{type:Object},snippet:{type:Object},onClickHandler:{type:Function},disabledTooltip:{type:String},};get snippet(){return this.props.snippet;}
onInstallableHover(ev){if(this.snippet.isInstallable){ev.currentTarget.querySelector(".o_install_btn").classList.toggle("visually-hidden-focusable",ev.type!=="mouseover");}}
onClickInstall(){this.props.snippetModel.installSnippetModule(this.props.snippet,this.env.editor.config.installSnippetModule);}}
return __exports;});;

/* /html_builder/static/src/snippets/add_snippet_dialog.js */
odoo.define('@html_builder/snippets/add_snippet_dialog',['@odoo/owl','@web/core/assets','@web/core/browser/feature_detection','@web/core/dialog/dialog','@web/core/hotkeys/hotkey_service','@web/core/l10n/localization','@web/core/ui/ui_service','@web/core/browser/cookie','@web/core/utils/hooks','@html_builder/snippets/snippet_viewer'],function(require){'use strict';let __exports={};const{Component,onMounted,onWillUnmount,onWillRender,useRef,useState}=require("@odoo/owl");const{loadBundle,loadCSS}=require("@web/core/assets");const{isBrowserFirefox}=require("@web/core/browser/feature_detection");const{Dialog}=require("@web/core/dialog/dialog");const{getActiveHotkey}=require("@web/core/hotkeys/hotkey_service");const{localization}=require("@web/core/l10n/localization");const{getFirstAndLastTabableElements}=require("@web/core/ui/ui_service");const{cookie}=require("@web/core/browser/cookie");const{useChildRef}=require("@web/core/utils/hooks");const{SnippetViewer}=require("@html_builder/snippets/snippet_viewer");const AddSnippetDialog=__exports.AddSnippetDialog=class AddSnippetDialog extends Component{static template="html_builder.AddSnippetDialog";static components={Dialog};static props={selectedSnippet:{type:Object},selectSnippet:{type:Function},snippetModel:{type:Object},close:{type:Function},installSnippetModule:{type:Function},editor:{type:Object},};setup(){this.iframeRef=useRef("iframe");this.modalRef=useChildRef();this.state=useState({search:"",groupSelected:this.props.selectedSnippet.groupName,showIframe:false,hasNoSearchResults:false,});this.snippetViewerProps={state:this.state,hasSearchResults:(has)=>{this.state.hasNoSearchResults=!has;},selectSnippet:(...args)=>{this.props.selectSnippet(...args);this.props.close();},snippetModel:this.props.snippetModel,installSnippetModule:this.props.installSnippetModule,frontendDirection:this.props.editor.editable.classList.contains("o_rtl")?"rtl":"ltr",};let root;onMounted(async()=>{const isFirefox=isBrowserFirefox();if(isFirefox&&!(this.iframeRef.el?.contentDocument.readyState==="complete")){await new Promise((resolve)=>{this.iframeRef.el.addEventListener("load",resolve,{once:true});});}
await this.insertStyle();const iframeDocument=this.iframeRef.el.contentDocument;iframeDocument.body.parentElement.classList.add("o_add_snippets_preview");iframeDocument.body.style.setProperty("direction",localization.direction);iframeDocument.body.tabIndex="-1";iframeDocument.addEventListener("keydown",this.onIframeDocumentKeydown.bind(this));root=this.__owl__.app.createRoot(SnippetViewer,{props:this.snippetViewerProps,});root.mount(iframeDocument.body);this.insertColorScheme();this.state.showIframe=true;});onWillRender(()=>{if(!this.props.snippetModel.hasCustomGroup&&this.state.groupSelected==="custom"){this.state.groupSelected=this.props.snippetModel.snippetGroups[0].groupName;}});onWillUnmount(()=>{root.destroy();});}
async insertStyle(){const loadCSSBundleFromEditor=(bundleName,loadOptions)=>{const cssLinkEl=this.props.editor.document.head.querySelector(`link[type="text/css"][href*="/${bundleName}."]`);if(cssLinkEl){return loadCSS(cssLinkEl.getAttribute("href"),loadOptions);}
return loadBundle(bundleName,loadOptions);};this.props.editor.dispatchTo("snippet_preview_dialog_stylesheets_handlers",{iframe:this.iframeRef.el,});const editorPreviewAssetsBundles=this.props.editor.getResource("snippet_preview_dialog_bundles");const loadOptions={targetDoc:this.iframeRef.el.contentDocument,js:false};await Promise.all([...editorPreviewAssetsBundles.map((assetsBundle)=>loadCSSBundleFromEditor(assetsBundle,loadOptions)),loadBundle("html_builder.iframe_add_dialog",loadOptions),]);}
get snippetGroups(){return this.props.snippetModel.snippetGroups.filter((snippetGroup)=>!snippetGroup.moduleId);}
selectGroup(snippetGroup){this.state.groupSelected=snippetGroup.groupName;const iframeDocument=this.iframeRef.el.contentDocument;iframeDocument.body.scrollTop=0;}
insertColorScheme(){const colorScheme=cookie.get("color_scheme")||"light";const metaElement=document.createElement("meta");const iframeDocument=this.iframeRef.el.contentDocument;metaElement.setAttribute("name","color-scheme");metaElement.content=colorScheme;iframeDocument.head.appendChild(metaElement);iframeDocument.body.parentElement.classList.add("o_add_snippets_preview--"+colorScheme);}
onTabKeydown(ev){const hotkey=getActiveHotkey(ev);if(!["arrowleft","arrowright","arrowdown","arrowup"].includes(hotkey)){return;}
if(["arrowleft","arrowup"].includes(hotkey)){ev.currentTarget.previousElementSibling?.focus();}else{ev.currentTarget.nextElementSibling?.focus();}}
onIframeDocumentKeydown(ev){const hotkey=getActiveHotkey(ev);if(!["tab","shift+tab"].includes(hotkey)){return;}
const[,lastTabableElInIframe]=getFirstAndLastTabableElements(ev.currentTarget);if(hotkey==="tab"&&lastTabableElInIframe===ev.target){const[firstTabableElInDialog]=getFirstAndLastTabableElements(this.modalRef.el);firstTabableElInDialog.focus();ev.preventDefault();ev.stopPropagation();}else if(hotkey==="shift+tab"&&ev.target.tagName==="BODY"){lastTabableElInIframe.focus();ev.preventDefault();ev.stopPropagation();}}}
return __exports;});;

/* /html_builder/static/src/snippets/input_confirmation_dialog.js */
odoo.define('@html_builder/snippets/input_confirmation_dialog',['@odoo/owl','@web/core/confirmation_dialog/confirmation_dialog'],function(require){'use strict';let __exports={};const{useState}=require("@odoo/owl");const{ConfirmationDialog}=require("@web/core/confirmation_dialog/confirmation_dialog");const InputConfirmationDialog=__exports.InputConfirmationDialog=class InputConfirmationDialog extends ConfirmationDialog{static template="html_builder.InputConfirmationDialog";static props={...ConfirmationDialog.props,inputLabel:{type:String,optional:true},defaultValue:{type:String,optional:true},};setup(){super.setup();this.inputState=useState({value:this.props.defaultValue,});}
execButton(callback){return super.execButton((...args)=>callback?.(...args,this.inputState.value));}}
return __exports;});;

/* /html_builder/static/src/snippets/snippet_service.js */
odoo.define('@html_builder/snippets/snippet_service',['@web/core/confirmation_dialog/confirmation_dialog','@web/core/l10n/translation','@web/core/utils/functions','@web/core/utils/reactive','@html_builder/snippets/add_snippet_dialog','@web/core/registry','@web/core/user','@odoo/owl','@web/core/utils/hooks'],function(require){'use strict';let __exports={};const{ConfirmationDialog}=require("@web/core/confirmation_dialog/confirmation_dialog");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{uniqueId}=require("@web/core/utils/functions");const{Reactive}=require("@web/core/utils/reactive");const{AddSnippetDialog}=require("@html_builder/snippets/add_snippet_dialog");const{registry}=require("@web/core/registry");const{user}=require("@web/core/user");const{markup,useState}=require("@odoo/owl");const{useService}=require("@web/core/utils/hooks");const SnippetModel=__exports.SnippetModel=class SnippetModel extends Reactive{constructor(services,{snippetsName,context}){super();this.orm=services.orm;this.dialog=services.dialog;this.snippetsName=snippetsName;this.context=context;this.loadProm=null;this.snippetsByCategory={snippet_groups:[],snippet_custom:[],snippet_structure:[],snippet_content:[],snippet_custom_content:[],};this.originalSnippets={};}
get hasCustomGroup(){return!!this.snippetsByCategory.snippet_custom.length;}
get snippetGroups(){const snippetGroups=this.snippetsByCategory.snippet_groups;if(this.hasCustomGroup){return snippetGroups;}
return snippetGroups.filter((snippet)=>snippet.groupName!=="custom");}
get snippetStructures(){return[...this.snippetsByCategory.snippet_structure,...this.snippetsByCategory.snippet_custom,];}
get snippetInnerContents(){return this.snippetsByCategory.snippet_content;}
get hasCustomInnerContents(){return!!this.snippetsByCategory.snippet_custom_content.length;}
get snippetCustomInnerContents(){return this.snippetsByCategory.snippet_custom_content;}
isCustomInnerContent(customSnippetName){return!!this.snippetsByCategory.snippet_content.find((snippet)=>snippet.name===customSnippetName);}
isCustomStructure(customSnippetName){return!!this.snippetsByCategory.snippet_structure.find((snippet)=>snippet.name===customSnippetName);}
isInnerContent(el){const snippetName=el.dataset.snippet;if(!snippetName){return false;}
return!!this.snippetsByCategory.snippet_content.find((snippet)=>snippet.name===snippetName);}
getSnippet(category,id){return this.snippetsByCategory[category].find((snippet)=>snippet.id===id);}
getSnippetByName(category,name){return this.snippetsByCategory[category].find((snippet)=>snippet.name===name);}
installSnippetModule(snippet,installSnippetModule){const bodyText=_t("Do you want to install %s App?",snippet.moduleDisplayName);const linkText=_t("More info about this app.");const linkUrl="/odoo/action-base.open_module_tree/"+encodeURIComponent(snippet.moduleId);this.dialog.add(ConfirmationDialog,{title:_t("Install %s",snippet.moduleDisplayName),body:markup`${bodyText}\n<a href="${linkUrl}" target="_blank"><i class="oi oi-arrow-right me-1"></i>${linkText}</a>`,confirm:async()=>installSnippetModule(snippet),confirmLabel:_t("Save and Install"),cancel:()=>{},});}
openSnippetDialog(snippet,{onSelect,onClose},editor){this.dialog.add(AddSnippetDialog,{selectedSnippet:snippet,snippetModel:this,selectSnippet:(...args)=>{const newSnippetEl=onSelect(...args);this.updateSnippetContent(newSnippetEl);},installSnippetModule:editor.config.installSnippetModule,editor,},{onClose});}
load(){if(!this.loadProm){this.loadProm=(async()=>{const context={...this.context,rendering_bundle:true};if(context.user_lang){context.lang=this.context.user_lang;context.snippet_lang=this.context.lang;}
const html=await this.orm.silent.call("ir.ui.view","render_public_asset",[this.snippetsName,{}],{context});this.snippetsDocument=new DOMParser().parseFromString(html,"text/html");const processors=registry.category("html_builder.snippetsPreprocessor").getAll();for(const processor of Object.values(processors)){processor(this.snippetsName,this.snippetsDocument);}
this.computeSnippetTemplates(this.snippetsDocument);this.setSnippetName(this.snippetsDocument);})();}
return this.loadProm;}
reload(context={}){this.loadProm=null;this.context={...this.context,...context,};return this.load();}
computeSnippetTemplates(snippetsDocument){const snippetsBody=snippetsDocument.body;this.snippetsByCategory={};this.originalSnippets={};for(const snippetCategory of snippetsBody.querySelectorAll("snippets")){const snippets=[];for(const snippetEl of snippetCategory.children){const snippet={id:uniqueId(),title:snippetEl.getAttribute("name"),name:snippetEl.children[0].dataset.snippet,content:snippetEl.children[0],viewId:parseInt(snippetEl.dataset.oeSnippetId),key:snippetEl.dataset.oeSnippetKey,thumbnailSrc:snippetEl.dataset.oeThumbnail,imagePreviewSrc:snippetEl.dataset.oImagePreview,isCustom:false,label:"",isDisabled:false,forbidSanitize:false,gridColumnSpan:0,};const moduleId=snippetEl.dataset.moduleId;if(moduleId){Object.assign(snippet,{moduleId,isInstallable:!!moduleId,moduleDisplayName:snippetEl.dataset.moduleDisplayName,});}
if(snippetEl.dataset.oeForbidSanitize){Object.assign(snippet,{forbidSanitize:snippetEl.dataset.oeForbidSanitize});}
if(snippetEl.dataset.oGridColumnSpan){snippet.gridColumnSpan=parseInt(snippetEl.dataset.oGridColumnSpan);}
switch(snippetCategory.id){case"snippet_groups":snippet.groupName=snippetEl.dataset.oSnippetGroup;break;case"snippet_structure":snippet.groupName=snippetEl.dataset.oGroup;snippet.keyWords=snippetEl.dataset.oeKeywords;break;case"snippet_custom":snippet.groupName="custom";snippet.isCustom=true;break;}
snippet.label=this.getSnippetLabel(snippetEl,snippet.isCustom);if(["snippet_structure","snippet_content"].includes(snippetCategory.id)){this.originalSnippets[snippet.name]??=snippet;}
snippets.push(snippet);}
this.snippetsByCategory[snippetCategory.id]=snippets;}
const customInnerContent=[];const customSnippets=this.snippetsByCategory.snippet_custom;for(let i=customSnippets.length-1;i>=0;i--){const snippet=customSnippets[i];const customSnippetName=snippet.name.startsWith("s_button_")?"s_button":snippet.name;if(this.isCustomInnerContent(customSnippetName)){customInnerContent.unshift(snippet);}
if(!this.isCustomStructure(customSnippetName)){customSnippets.splice(i,1);}}
this.snippetsByCategory["snippet_custom_content"]=customInnerContent;}
async deleteCustomSnippet(snippet){return new Promise((resolve)=>{const message=_t("Are you sure you want to delete the block %s?",snippet.title);this.dialog.add(ConfirmationDialog,{body:message,confirm:async()=>{for(const categoryKey of["snippet_custom","snippet_custom_content"]){const snippetList=this.snippetsByCategory[categoryKey]||[];const snippetIndex=snippetList.findIndex((item)=>item.id===snippet.id);if(snippetIndex>-1){snippetList.splice(snippetIndex,1);}}
await this.orm.call("ir.ui.view","delete_snippet",[],{view_id:snippet.viewId,template_key:this.snippetsName,});},cancel:()=>{},confirmLabel:_t("Yes"),cancelLabel:_t("No"),},{onClose:resolve,});});}
async renameCustomSnippet(snippet,newName){if(newName===snippet.title){return;}
snippet.title=newName;for(const snippetEl of this.snippetsDocument.body.querySelectorAll(`snippets#snippet_custom > [data-oe-snippet-key = ${snippet.key}]`)){snippetEl.setAttribute("name",newName);snippetEl.children[0].dataset["name"]=newName;}
await this.orm.call("ir.ui.view","rename_snippet",[],{name:newName,view_id:snippet.viewId,template_key:this.snippetsName,});}
setSnippetName(snippetsDocument){for(const snippetEl of snippetsDocument.body.querySelectorAll("snippets > *")){snippetEl.children[0].dataset["name"]=snippetEl.getAttribute("name");}}
getOriginalSnippet(snippetKey){if(!snippetKey){return;}
return this.originalSnippets[snippetKey];}
getSnippetThumbnailURL(snippetKey){const originalSnippet=this.getOriginalSnippet(snippetKey);return originalSnippet.thumbnailSrc;}
updateSnippetContent(snippetEl){snippetEl.querySelectorAll(".s_dialog_preview").forEach((el)=>el.remove());}
saveSnippet(snippetEl,cleanForSaveHandlers,wrapWithSaveSnippetHandlers=(_,callback)=>callback()){return new Promise((resolve)=>{this.dialog.add(ConfirmationDialog,{title:_t("Create a custom snippet"),body:_t("Do you want to save this snippet as a custom one?"),confirmLabel:_t("Save"),cancel:()=>resolve(false),confirm:async()=>{const isButton=snippetEl.matches("a.btn");const snippetKey=isButton?"s_button":snippetEl.dataset.snippet;const thumbnailURL=this.getSnippetThumbnailURL(snippetKey);const snippetCopyEl=await wrapWithSaveSnippetHandlers(snippetEl,()=>snippetEl.cloneNode(true));const rootEl=snippetEl.matches(".s_popup")?snippetCopyEl.firstElementChild:snippetCopyEl;cleanForSaveHandlers.forEach((handler)=>handler({root:rootEl}));const defaultSnippetName=isButton?_t("Custom Button"):_t("Custom %s",snippetEl.dataset.name);snippetCopyEl.classList.add("s_custom_snippet");delete snippetCopyEl.dataset.name;if(isButton){snippetCopyEl.classList.remove("mb-2");snippetCopyEl.classList.add("o_snippet_drop_in_only","s_custom_button");}
const editableParentEl=snippetEl.closest("[data-oe-model][data-oe-field][data-oe-id]");const context={...this.context,model:editableParentEl.dataset.oeModel,field:editableParentEl.dataset.oeField,resId:editableParentEl.dataset.oeId,};const savedName=await this.orm.call("ir.ui.view","save_snippet",[],{name:defaultSnippetName,arch:snippetCopyEl.outerHTML,template_key:this.snippetsName,snippet_key:snippetKey,thumbnail_url:thumbnailURL,context,});await this.reload();resolve(savedName);},},{onClose:()=>resolve(false)});});}
getSnippetLabel(snippetEl,isCustom=false){return snippetEl.dataset.oLabel;}}
const snippetService=__exports.snippetService={dependencies:["orm","dialog"],start(env,{orm,dialog}){const services={orm,dialog};const context={lang:user.context.lang,user_lang:user.context.lang,};const snippetModelsMap=new Map();const getSnippetModel=(snippetsName)=>{if(snippetModelsMap.has(snippetsName)){return snippetModelsMap.get(snippetsName);}
snippetModelsMap.set(snippetsName,new SnippetModel(services,{snippetsName,context,}));return snippetModelsMap.get(snippetsName);};return{getSnippetModel};},};registry.category("services").add("html_builder.snippets",snippetService);__exports.useSnippets=useSnippets;function useSnippets(snippetsName){const snippetsService=useService("html_builder.snippets");return useState(snippetsService.getSnippetModel(snippetsName));}
return __exports;});;

/* /html_builder/static/src/snippets/snippet_viewer.js */
odoo.define('@html_builder/snippets/snippet_viewer',['@odoo/owl','@web/core/hotkeys/hotkey_service','@web/core/l10n/localization','@web/core/l10n/translation','@web/core/utils/hooks','@html_builder/snippets/input_confirmation_dialog','@web/core/utils/search','@html_builder/core/img'],function(require){'use strict';let __exports={};const{Component,markup,useRef}=require("@odoo/owl");const{getActiveHotkey}=require("@web/core/hotkeys/hotkey_service");const{localization}=require("@web/core/l10n/localization");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);const{useService}=require("@web/core/utils/hooks");const{InputConfirmationDialog}=require("@html_builder/snippets/input_confirmation_dialog");const{fuzzyLookup}=require("@web/core/utils/search");const{Img}=require("@html_builder/core/img");const SnippetViewer=__exports.SnippetViewer=class SnippetViewer extends Component{static template="html_builder.SnippetViewer";static props={state:{type:Object},selectSnippet:{type:Function},hasSearchResults:Function,snippetModel:{type:Object},installSnippetModule:{type:Function},frontendDirection:{type:String},};setup(){this.dialog=useService("dialog");this.content=useRef("content");this.backendDirection=localization.direction;}
getPrefixIcons(snippetContentEl){const icons=[];const styleProps={style:"height: 1em",attrs:{fill:"var(--body-color)"}};if(snippetContentEl.matches(".o_snippet_desktop_invisible")){icons.push({keyClass:"o_prefix_desktop_invisible",title:"Invisible on desktop",Component:Img,props:{src:"/html_builder/static/img/options/desktop_invisible.svg",...styleProps,},});}
if(snippetContentEl.matches(".o_snippet_mobile_invisible")){icons.push({keyClass:"o_prefix_mobile_invisible",title:"Invisible on mobile",Component:Img,props:{src:"/html_builder/static/img/options/mobile_invisible.svg",...styleProps,},});}
if(snippetContentEl.matches(".o_conditional_hidden")){icons.push({keyClass:"o_prefix_conditional",title:"Conditionally visible",content:markup`<span class="fa fa-eye-slash"/>`,});}
return icons;}
getRenameBtnLabel(snippetName){return _t("Rename %(snippetName)s",{snippetName});}
getDeleteBtnLabel(snippetName){return _t("Delete %(snippetName)s",{snippetName});}
onClickRename(snippet){this.dialog.add(InputConfirmationDialog,{title:_t("Rename the block"),inputLabel:_t("Name"),defaultValue:snippet.title,confirmLabel:_t("Save"),confirm:(inputValue)=>{this.props.snippetModel.renameCustomSnippet(snippet,inputValue);},cancelLabel:_t("Discard"),cancel:()=>{},});}
onClickDelete(snippet){this.props.snippetModel.deleteCustomSnippet(snippet);}
getSnippetColumns(){const snippets=this.getSelectedSnippets();const columns=[[],[]];for(const index in snippets){if(index%2===0){columns[0].push(snippets[index]);}else{columns[1].push(snippets[index]);}}
let numResults=0;for(const column of columns){numResults+=column.length;}
this.props.hasSearchResults(numResults>0);return columns;}
onClick(snippet){if(snippet.moduleId){this.props.snippetModel.installSnippetModule(snippet,this.props.installSnippetModule);}else{this.props.selectSnippet(snippet);}}
onPreviewKeydown(ev,snippet){const hotkey=getActiveHotkey(ev);if(hotkey==="enter"||hotkey==="space"){this.onClick(snippet);}}
getContent(elem){return markup(elem.outerHTML);}
getButtonInstallName(snippet){return _t("Install %s",snippet.title);}
getSelectedSnippets(){const snippetStructures=this.props.snippetModel.snippetStructures.filter((snippet)=>!snippet.isExcluded&&!snippet.isDisabled);if(this.previousSearch!==this.props.state.search){this.previousSearch=this.props.state.search;if(this.content.el){this.content.el.ownerDocument.body.scrollTop=0;}}
const getClasses=(snippet)=>{const classes=new Set();const elements=[snippet.content,...snippet.content.querySelectorAll("*")];for(const el of elements){for(const className of el.classList){if(className.startsWith("s_")){classes.add(className);}}}
return Array.from(classes);};if(this.props.state.search){return fuzzyLookup(this.props.state.search,snippetStructures,(snippet)=>[snippet.title||"",snippet.name||"",...(snippet.keyWords?.split(",")||""),...getClasses(snippet),]);}
return snippetStructures.filter((snippet)=>snippet.groupName===this.props.state.groupSelected);}}
return __exports;});;

/* /html_builder/static/src/utils/column_layout_utils.js */
odoo.define('@html_builder/utils/column_layout_utils',[],function(require){'use strict';let __exports={};__exports.getNbColumns=getNbColumns;function getNbColumns(columnEls,isMobile,mobileBreakpoint){if(!columnEls?.length){return 0;}
if(areColsCustomized(columnEls,isMobile,mobileBreakpoint)){return"custom";}
const resolutionModifier=isMobile?"":`${mobileBreakpoint}-`;const colRegex=new RegExp(`(?:^|\\s+)col-${resolutionModifier}(\\d{1,2})(?!\\S)`);const colSize=parseInt(columnEls[0].className.match(colRegex)?.[1]||12);const offsetSize=getFirstItem(columnEls,isMobile).classList.contains(`offset-${resolutionModifier}1`)?1:0;return Math.floor((12-offsetSize)/colSize);}
const getRow=__exports.getRow=(el)=>el.querySelector(":scope > .row");__exports.getFirstItem=getFirstItem;function getFirstItem(columnEls,isMobile){return(isMobile&&[...columnEls].find((el)=>el.style.order==="0"))||columnEls[0];}
__exports.addMobileOrders=addMobileOrders;function addMobileOrders(columnEls,mobileBreakpoint){for(let i=0;i<columnEls.length;i++){columnEls[i].style.order=i;columnEls[i].classList.add(`order-${mobileBreakpoint}-0`);}}
__exports.removeMobileOrders=removeMobileOrders;function removeMobileOrders(columnEls,mobileBreakpoint){for(const el of columnEls){el.style.order="";el.classList.remove(`order-${mobileBreakpoint}-0`);}}
__exports.areColsCustomized=areColsCustomized;function areColsCustomized(columnEls,isMobile,mobileBreakpoint){if(!columnEls?.length){return false;}
const resolutionModifier=isMobile?"":`${mobileBreakpoint}-`;const colRegex=new RegExp(`(?:^|\\s+)col-${resolutionModifier}(\\d{1,2})(?!\\S)`);const colSize=parseInt(columnEls[0].className.match(colRegex)?.[1]||12);const allColsSizesEqual=[...columnEls].every((columnEl)=>parseInt(columnEl.className.match(colRegex)?.[1]||12)===colSize);if(!allColsSizesEqual){return true;}
const offsetRegex=new RegExp(`(?:^|\\s+)offset-${resolutionModifier}[1-9][0-1]?(?!\\S)`);const nbOffsets=[...columnEls].filter((columnEl)=>columnEl.className.match(offsetRegex)).length;if(nbOffsets===0){return false;}
if(nbOffsets===1&&colSize===2&&getFirstItem(columnEls,isMobile).className.match(`offset-${resolutionModifier}1`)){return false;}
return true;}
__exports.fillRemovedItemGap=fillRemovedItemGap;function fillRemovedItemGap(parentEl,itemOrder){[...parentEl.children].forEach((el)=>{const elOrder=parseInt(el.style.order);if(elOrder>itemOrder){el.style.order=elOrder-1;}});}
return __exports;});;

/* /html_builder/static/src/utils/escaping.js */
odoo.define('@html_builder/utils/escaping',[],function(require){'use strict';let __exports={};__exports.escapeTextNodes=escapeTextNodes;function escapeTextNodes(el){const nodeFilter=(node)=>{if(node.nodeType===Node.ELEMENT_NODE&&(node.matches("object,iframe,script,style")||(node.hasAttribute("data-oe-model")&&node.getAttribute("data-oe-model")!=="ir.ui.view"))){return NodeFilter.FILTER_REJECT;}
if(node.nodeType===Node.TEXT_NODE){return NodeFilter.FILTER_ACCEPT;}
return NodeFilter.FILTER_SKIP;};if(nodeFilter(el)===NodeFilter.FILTER_REJECT){return;}
const walker=document.createTreeWalker(el,NodeFilter.SHOW_ALL,nodeFilter);const escaper=document.createElement("div");let node;while((node=walker.nextNode())){escaper.textContent=node.nodeValue;node.nodeValue=escaper.innerHTML;}}
return __exports;});;

/* /html_builder/static/src/utils/grid_layout_utils.js */
odoo.define('@html_builder/utils/grid_layout_utils',['@web/core/utils/render'],function(require){'use strict';let __exports={};const{renderToElement}=require("@web/core/utils/render");const rowSize=__exports.rowSize=50;const additionalRowLimit=__exports.additionalRowLimit=10;const defaultGridPadding=10;__exports.getGridProperties=getGridProperties;function getGridProperties(rowEl){const style=window.getComputedStyle(rowEl);const rowGap=parseFloat(style.rowGap);const columnGap=parseFloat(style.columnGap);const columnSize=(rowEl.clientWidth-11*columnGap)/12;return{rowGap,rowSize,columnGap,columnSize};}
__exports.getGridItemProperties=getGridItemProperties;function getGridItemProperties(gridItemEl){const style=gridItemEl.style;const rowStart=parseInt(style.gridRowStart);const rowEnd=parseInt(style.gridRowEnd);const columnStart=parseInt(style.gridColumnStart);const columnEnd=parseInt(style.gridColumnEnd);const gridArea=style.gridArea;const zIndex=style.zIndex;return{rowStart,rowEnd,columnStart,columnEnd,gridArea,zIndex};}
__exports.setElementToMaxZindex=setElementToMaxZindex;function setElementToMaxZindex(element,rowEl){const childrenEls=[...rowEl.children].filter((el)=>el!==element&&!el.classList.contains("o_we_grid_preview"));element.style.zIndex=Math.max(...childrenEls.map((el)=>el.style.zIndex))+1;}
__exports.addBackgroundGrid=addBackgroundGrid;function addBackgroundGrid(rowEl,gridHeight){const gridProp=getGridProperties(rowEl);const rowCount=Math.max(rowEl.dataset.rowCount,gridHeight);const backgroundGrid=renderToElement("html_builder.background_grid",{rowCount:rowCount+1,rowGap:gridProp.rowGap,rowSize:gridProp.rowSize,columnGap:gridProp.columnGap,columnSize:gridProp.columnSize,});rowEl.prepend(backgroundGrid);return rowEl.firstElementChild;}
__exports.resizeGrid=resizeGrid;function resizeGrid(rowEl){const columnEls=[...rowEl.children].filter((c)=>c.classList.contains("o_grid_item"));rowEl.dataset.rowCount=Math.max(...columnEls.map((el)=>el.style.gridRowEnd))-1;}
__exports.cleanUpGrid=cleanUpGrid;function cleanUpGrid(rowEl,columnEl,dragHelperEl,backgroundGridEl){const columnStyleProps=["position","top","right","left","height","width"];columnStyleProps.forEach((prop)=>columnEl.style.removeProperty(prop));rowEl.style.removeProperty("position");dragHelperEl.remove();backgroundGridEl.remove();}
__exports.toggleGridMode=toggleGridMode;function toggleGridMode(containerEl,preserveSelection,mobileBreakpoint){let rowEl=containerEl.querySelector(":scope > .row");const outOfRowEls=[...containerEl.children].filter((el)=>!el.classList.contains("row"));const restoreSelection=!rowEl||outOfRowEls.length>0?preserveSelection().restore:()=>{};if(rowEl&&outOfRowEls.length>0){const columnEl=document.createElement("div");columnEl.classList.add(`col-${mobileBreakpoint}-12`);for(let i=outOfRowEls.length-1;i>=0;i--){columnEl.prepend(outOfRowEls[i]);}
rowEl.prepend(columnEl);}
if(!rowEl){rowEl=document.createElement("div");rowEl.classList.add("row");const columnEl=document.createElement("div");columnEl.classList.add(`col-${mobileBreakpoint}-12`);const containerChildren=containerEl.children;for(let i=containerChildren.length-1;i>=0;i--){columnEl.prepend(containerChildren[i]);}
rowEl.appendChild(columnEl);containerEl.appendChild(rowEl);}
restoreSelection();const columnEls=rowEl.children;const columnSize=rowEl.clientWidth/12;rowEl.style.position="relative";const rowCount=placeColumns(columnEls,rowSize,0,columnSize,0,mobileBreakpoint)-1;rowEl.style.removeProperty("position");rowEl.dataset.rowCount=rowCount;const classesToRemove=[...rowEl.classList].filter((c)=>/^align-items/.test(c));rowEl.classList.remove(...classesToRemove);rowEl.classList.add("o_grid_mode");}
function placeColumns(columnEls,rowSize,rowGap,columnSize,columnGap,mobileBreakpoint){let maxRowEnd=0;const columnSpans=[];let zIndex=1;const imageColumns=[];const isRtl=!!columnEls[0]?.closest(".o_rtl, [dir='rtl']");for(const columnEl of columnEls){const isImageColumn=checkIfImageColumn(columnEl);const imageEl=columnEl.querySelector("img");const hasBackground=columnEl.matches(".o_cc, .oe_img_bg");const isImageWithoutPadding=isImageColumn&&!hasBackground;const style=window.getComputedStyle(columnEl);const borderLeft=parseFloat(style.borderLeft);let columnLeft=isImageWithoutPadding&&!borderLeft?imageEl.offsetLeft:columnEl.offsetLeft;if(isRtl){const parentWidth=columnEl.offsetParent.clientWidth;columnLeft=isImageWithoutPadding&&!borderLeft?parentWidth-imageEl.offsetLeft-imageEl.offsetWidth:parentWidth-columnEl.offsetLeft-columnEl.offsetWidth;}
const paddingLeft=parseFloat(style.paddingLeft);let width=isImageWithoutPadding?parseFloat(imageEl.scrollWidth):parseFloat(columnEl.scrollWidth)-(hasBackground?0:2*paddingLeft);const borderX=borderLeft+parseFloat(style.borderRight);width+=borderX+(hasBackground||isImageColumn?0:2*defaultGridPadding);let columnSpan=Math.round((width+columnGap)/(columnSize+columnGap));if(columnSpan<1){columnSpan=1;}
const columnStart=Math.round(columnLeft/(columnSize+columnGap))+1;const columnEnd=columnStart+columnSpan;const borderTop=parseFloat(style.borderTop);const columnTop=isImageWithoutPadding&&!borderTop?imageEl.offsetTop:columnEl.offsetTop;const paddingTop=parseFloat(style.paddingTop);const paddingBottom=parseFloat(style.paddingBottom);const rowOffsetTop=Math.floor((paddingTop+rowGap)/(rowSize+rowGap));let height=isImageWithoutPadding?parseFloat(imageEl.scrollHeight):parseFloat(columnEl.scrollHeight)-(hasBackground?0:paddingTop+paddingBottom);const borderY=borderTop+parseFloat(style.borderBottom);height+=borderY+(hasBackground||isImageColumn?0:2*defaultGridPadding);const rowSpan=Math.ceil((height+rowGap)/(rowSize+rowGap));const rowStart=Math.round(columnTop/(rowSize+rowGap))+
1+
(hasBackground||isImageWithoutPadding?0:rowOffsetTop);const rowEnd=rowStart+rowSpan;columnEl.style.gridArea=`${rowStart} / ${columnStart} / ${rowEnd} / ${columnEnd}`;columnEl.classList.add("o_grid_item");columnEl.classList.add(`g-col-${mobileBreakpoint}-${columnSpan}`,`g-height-${rowSpan}`);columnEl.style.zIndex=zIndex++;if(hasBackground){columnEl.style.setProperty("--grid-item-padding-y",`${paddingTop}px`);columnEl.style.setProperty("--grid-item-padding-x",`${paddingLeft}px`);}
reloadLazyImages(columnEl);maxRowEnd=Math.max(rowEnd,maxRowEnd);columnSpans.push(columnSpan);imageColumns.push(isImageColumn);}
for(const[i,columnEl]of[...columnEls].entries()){const regex=new RegExp(`^(((pt|pb)\\d{1,3}$)|col-${mobileBreakpoint}-|offset-${mobileBreakpoint}-)`);const toRemove=[...columnEl.classList].filter((c)=>regex.test(c));columnEl.classList.remove(...toRemove);columnEl.classList.add(`col-${mobileBreakpoint}-`+columnSpans[i]);if(imageColumns[i]){convertImageColumn(columnEl);}}
return maxRowEnd;}
__exports.reloadLazyImages=reloadLazyImages;function reloadLazyImages(columnEl){const imageEls=columnEl.querySelectorAll("img");for(const imageEl of imageEls){const src=imageEl.getAttribute("src");imageEl.src="";imageEl.src=src;}}
__exports.convertColumnToGrid=convertColumnToGrid;function convertColumnToGrid(rowEl,columnEl,columnWidth,columnHeight,mobileBreakpoint){if(checkIfImageColumn(columnEl)){convertImageColumn(columnEl);}
const paddingX=parseFloat(rowEl.style.getPropertyValue("--grid-item-padding-x"))||defaultGridPadding;const paddingY=parseFloat(rowEl.style.getPropertyValue("--grid-item-padding-y"))||defaultGridPadding;columnWidth+=2*paddingX;columnHeight+=2*paddingY;const{rowGap,rowSize,columnGap,columnSize}=getGridProperties(rowEl);const columnSpan=Math.round((columnWidth+columnGap)/(columnSize+columnGap));const rowSpan=Math.ceil((columnHeight+rowGap)/(rowSize+rowGap));const regex=/^(pt|pb|col-|offset-)/;const toRemove=[...columnEl.classList].filter((c)=>regex.test(c));columnEl.classList.remove(...toRemove);columnEl.classList.add(`g-col-${mobileBreakpoint}-${columnSpan}`,`g-height-${rowSpan}`,`col-${mobileBreakpoint}-${columnSpan}`);columnEl.classList.add("o_grid_item");return{columnSpan,rowSpan};}
__exports.convertToNormalColumn=convertToNormalColumn;function convertToNormalColumn(columnEl,mobileBreakpoint){const gridSizeClasses=columnEl.className.match(new RegExp(`(g-col-${mobileBreakpoint}|g-height)-[0-9]+`,"g"));columnEl.classList.remove("o_grid_item","o_grid_item_image","o_grid_item_image_contain",...gridSizeClasses);columnEl.style.removeProperty("z-index");columnEl.style.removeProperty("--grid-item-padding-x");columnEl.style.removeProperty("--grid-item-padding-y");columnEl.style.removeProperty("grid-area");}
__exports.checkIfImageColumn=checkIfImageColumn;function checkIfImageColumn(columnEl){let isImageColumn=false;const imageEls=columnEl.querySelectorAll(":scope > img, :scope > a > img");const columnChildrenEls=[...columnEl.children].filter((el)=>el.nodeName!=="BR");if(imageEls.length===1&&columnChildrenEls.length===1){const textNodeEls=[...columnEl.childNodes].filter((el)=>el.nodeType===Node.TEXT_NODE);const areTextNodesEmpty=[...textNodeEls].every((textNodeEl)=>textNodeEl.nodeValue.trim()==="");isImageColumn=areTextNodesEmpty;}
return isImageColumn;}
function convertImageColumn(columnEl){columnEl.querySelectorAll("br").forEach((el)=>el.remove());const textNodeEls=[...columnEl.childNodes].filter((el)=>el.nodeType===Node.TEXT_NODE);textNodeEls.forEach((el)=>el.remove());const imageEl=columnEl.querySelector("img");columnEl.classList.add("o_grid_item_image");imageEl.style.removeProperty("width");}
return __exports;});;

/* /html_builder/static/src/utils/image.js */
odoo.define('@html_builder/utils/image',['@html_editor/utils/image_processing','@html_editor/utils/image'],function(require){'use strict';let __exports={};const{loadImageInfo}=require("@html_editor/utils/image_processing");const{getFetchedMimetype}=require("@html_editor/utils/image");__exports.getMimetypeBeforeShape=getMimetypeBeforeShape;async function getMimetypeBeforeShape(imageEl){const data=imageEl.dataset;const{formatMimetype,mimetypeBeforeConversion}=data.mimetypeBeforeConversion?data:await loadImageInfo(imageEl);return formatMimetype||mimetypeBeforeConversion||getFetchedMimetype(imageEl,data);}
__exports.handleImagesIfDataset=handleImagesIfDataset;async function handleImagesIfDataset(toProcessEls,nodeEl,dataInfo,callback){if(!nodeEl||!nodeEl.dataset[dataInfo]){return;}
for(const toProcessEl of toProcessEls){if(!toProcessEl||!toProcessEl.tagName==="IMG"){continue;}
await callback(toProcessEl,nodeEl);}}
return __exports;});;

/* /html_builder/static/src/utils/option_sequence.js */
odoo.define('@html_builder/utils/option_sequence',[],function(require){'use strict';let __exports={};const BEGIN=1;const END=100;const ALL=[BEGIN,END];const DEFAULT=__exports.DEFAULT=track(10);function track(position){if(!(position in ALL)){const index=ALL.findIndex((value)=>value>position);if(index===-1){ALL.push(position);}else{ALL.splice(index,0,position);}}
return position;}
__exports.splitBetween=splitBetween;function splitBetween(beginPosition,endPosition,count){const result=[];const delta=(endPosition-beginPosition)/(count+1);for(let index=1;index<=count;index++){result.push(track(beginPosition+delta*index));}
return result;}
__exports.between=between;function between(previousPosition,nextPosition){return splitBetween(previousPosition,nextPosition,1)[0];}
__exports.after=after;function after(position){const index=ALL.findIndex((value)=>value===position);if(index===-1){throw new Error("Position "+position+" does not exist. Do not use arbitrary numbers.");}
if(index===ALL.length-1){throw new Error("Cannot place something after END position.");}
const nextPosition=ALL[index+1];return between(position,nextPosition);}
__exports.before=before;function before(position){const index=ALL.findIndex((value)=>value===position);if(index===-1){throw new Error("Position "+position+" does not exist. Do not use arbitrary numbers.");}
if(index===0){throw new Error("Cannot place something before BEGIN position.");}
const previousPosition=ALL[index-1];return between(previousPosition,position);}
const SNIPPET_SPECIFIC=DEFAULT;const[REPLACE_MEDIA,FONT_AWESOME,IMAGE_TOOL,ALIGNMENT_STYLE_PADDING,DYNAMIC_SVG,AFTER_HTML_BUILDER,SNIPPET_SPECIFIC_BEFORE,...__DETECT_ERROR_1__]=splitBetween(BEGIN,SNIPPET_SPECIFIC,7);if(__DETECT_ERROR_1__.length>0){console.error("Wrong count in split before default");}
const[SNIPPET_SPECIFIC_AFTER,LAYOUT_COLUMN,VERTICAL_ALIGNMENT,SNIPPET_SPECIFIC_NEXT,SNIPPET_SPECIFIC_END,ANIMATE,...__DETECT_ERROR_2__]=splitBetween(SNIPPET_SPECIFIC,END,6);if(__DETECT_ERROR_2__.length>0){console.error("Wrong count in split after default");}
const[TEXT_ALIGNMENT,TITLE_LAYOUT_SIZE,WIDTH,BLOCK_ALIGN,...__DETECT_ERROR_3__]=splitBetween(AFTER_HTML_BUILDER,SNIPPET_SPECIFIC_BEFORE,4);if(__DETECT_ERROR_3__.length>0){console.error("Wrong count in website split before specific");}
Object.assign(__exports,{TEXT_ALIGNMENT,TITLE_LAYOUT_SIZE,WIDTH,BLOCK_ALIGN});Object.assign(__exports,{BEGIN,REPLACE_MEDIA,FONT_AWESOME,IMAGE_TOOL,ALIGNMENT_STYLE_PADDING,DYNAMIC_SVG,AFTER_HTML_BUILDER,SNIPPET_SPECIFIC_BEFORE,SNIPPET_SPECIFIC,SNIPPET_SPECIFIC_AFTER,LAYOUT_COLUMN,VERTICAL_ALIGNMENT,SNIPPET_SPECIFIC_NEXT,SNIPPET_SPECIFIC_END,ANIMATE,END,});return __exports;});;

/* /html_builder/static/src/utils/scrolling.js */
odoo.define('@html_builder/utils/scrolling',['@web/core/utils/scrolling'],function(require){'use strict';let __exports={};const{getScrollingElement}=require("@web/core/utils/scrolling");function isScrollable(element){if(!element){return false;}
const overflowY=window.getComputedStyle(element).overflowY;return(overflowY==="auto"||overflowY==="scroll"||(overflowY==="visible"&&element===element.ownerDocument.scrollingElement));}
__exports.closestScrollable=closestScrollable;function closestScrollable(element){const document=element.ownerDocument||window.document;while(element&&element!==document.scrollingElement){if(element instanceof Document){return null;}
if(isScrollable(element)){return element;}
element=element.parentElement;}
return element||document.scrollingElement;}
function scrollFixedOffset(doc=document){let size=0;const elements=doc.querySelectorAll(".o_top_fixed_element");elements.forEach((el)=>{size+=el.offsetHeight;});return size;}
__exports.scrollTo=scrollTo;function scrollTo(el,options={}){if(!el){throw new Error("The scrollTo function was called without any given element");}
if(typeof el==="string"){el=document.querySelector(el);}
const isTopOrBottomHidden=el==="top"||el==="bottom";const scrollable=isTopOrBottomHidden?document.scrollingElement:options.scrollable||closestScrollable(el.parentElement);const scrollDocument=scrollable.ownerDocument;const isInOneDocument=isTopOrBottomHidden||scrollDocument===el.ownerDocument;const iframe=!isInOneDocument&&Array.from(scrollable.querySelectorAll("iframe")).find((node)=>node.contentDocument.contains(el));const topLevelScrollable=getScrollingElement(scrollDocument);function _computeScrollTop(){if(el==="#top"||el.id==="top"){return 0;}
if(el==="#bottom"||el.id==="bottom"){return scrollable.scrollHeight-scrollable.clientHeight;}
el.classList.add("o_check_scroll_position");let offsetTop=el.getBoundingClientRect().top+window.scrollY;el.classList.remove("o_check_scroll_position");if(el.classList.contains("d-none")){el.classList.remove("d-none");offsetTop=el.getBoundingClientRect().top+window.scrollY;el.classList.add("d-none");}
const isDocScrollingEl=scrollable===el.ownerDocument.scrollingElement;let elPosition=offsetTop-
(scrollable.getBoundingClientRect().top+
window.scrollY-
(isDocScrollingEl?0:scrollable.scrollTop));if(!isInOneDocument&&iframe){elPosition+=iframe.getBoundingClientRect().top+window.scrollY;}
let offset=options.forcedOffset;if(offset===undefined){offset=(scrollable===topLevelScrollable?scrollFixedOffset(scrollDocument):0)+
(options.extraOffset||0);}
return Math.max(0,elPosition-offset);}
return new Promise((resolve)=>{const start=scrollable.scrollTop;const duration=options.duration||600;const startTime=performance.now();function animateScroll(currentTime){const elapsedTime=currentTime-startTime;const progress=Math.min(elapsedTime/duration,1);const easeInOutQuad=progress<0.5?2*progress*progress:1-Math.pow(-2*progress+2,2)/2;const change=_computeScrollTop()-start;const newScrollTop=start+change*easeInOutQuad;scrollable.scrollTop=newScrollTop;if(elapsedTime<duration){requestAnimationFrame(animateScroll);}else{resolve();}}
requestAnimationFrame(animateScroll);});}
return __exports;});;

/* /html_builder/static/src/utils/sync_cache.js */
odoo.define('@html_builder/utils/sync_cache',['@web/core/utils/cache'],function(require){'use strict';let __exports={};const{Cache}=require("@web/core/utils/cache");const SyncCache=__exports.SyncCache=class SyncCache{constructor(fn){this.asyncCache=new Cache(fn,JSON.stringify);this.syncCache=new Map();}
async preload(params){const result=await this.asyncCache.read(params);this.syncCache.set(JSON.stringify(params),result);return result;}
get(params){return this.syncCache.get(JSON.stringify(params));}
invalidate(){this.asyncCache.invalidate();this.syncCache.clear();}}
return __exports;});;

/* /html_builder/static/src/utils/utils.js */
odoo.define('@html_builder/utils/utils',['@html_builder/core/dependency_manager','@odoo/owl','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{DependencyManager}=require("@html_builder/core/dependency_manager");const{useSubEnv}=require("@odoo/owl");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"html_builder",...args);__exports.getSnippetName=getSnippetName;function getSnippetName(snippetEl){if(snippetEl.dataset.name){return snippetEl.dataset.name;}
if(snippetEl.matches("img")){return _t("Image");}
if(snippetEl.matches(".fa")){return _t("Icon");}
if(snippetEl.matches(".media_iframe_video")){return _t("Video");}
if(snippetEl.parentNode?.matches(".row")){return _t("Column");}
if(snippetEl.matches("#wrapwrap > main")){return _t("Page Options");}
if(snippetEl.matches(".btn")){return _t("Button");}
return _t("Block");}
__exports.isElementInViewport=isElementInViewport;function isElementInViewport(el){const rect=el.getBoundingClientRect();const viewportWidth=window.innerWidth||document.documentElement.clientWidth;const viewportHeight=window.innerHeight||document.documentElement.clientHeight;return(Math.round(rect.top)>=0&&Math.round(rect.left)>=0&&Math.round(rect.right)<=viewportWidth&&Math.round(rect.bottom)<=viewportHeight);}
__exports.isVisible=isVisible;function isVisible(el){if(el.offsetHeight>0||el.offsetWidth>0){return true;}
return false;}
__exports.getElementsWithOption=getElementsWithOption;function getElementsWithOption(rootEl,selector,exclude=false,applyTo=false){let matchingEls=[...rootEl.querySelectorAll(selector)];if(rootEl.matches(selector)){matchingEls.unshift(rootEl);}
if(exclude){matchingEls=matchingEls.filter((editingEl)=>!editingEl.matches(exclude));}
if(applyTo){matchingEls=matchingEls.flatMap((editingEl)=>[...editingEl.querySelectorAll(applyTo)]);}
return matchingEls;}
__exports.useOptionsSubEnv=useOptionsSubEnv;function useOptionsSubEnv(getEditingElements){useSubEnv({dependencyManager:new DependencyManager(),getEditingElement:()=>getEditingElements()[0],getEditingElements:getEditingElements,weContext:{},});}
__exports.getValueFromVar=getValueFromVar;function getValueFromVar(value){const match=value.match(/var\(--([a-zA-Z0-9-_]+)\)/);if(match){return match[1];}
return value;}
__exports.toRatio=toRatio;function toRatio(value){const inputValueAsNumber=Number(value);const ratio=inputValueAsNumber>=0?1+inputValueAsNumber:1/(1-inputValueAsNumber);return`${ratio.toFixed(2)}x`;}
__exports.filterExtends=filterExtends;function filterExtends(arr,PotentialSuperClass){return arr.filter((PotentialSubClass)=>doesExtendsClass(PotentialSubClass,PotentialSuperClass));}
__exports.doesExtendsClass=doesExtendsClass;function doesExtendsClass(PotentialSubClass,PotentialSuperClass){if(PotentialSubClass===PotentialSuperClass){return false;}
return PotentialSubClass.prototype instanceof PotentialSuperClass;}
__exports.isEditable=isEditable;function isEditable(node){let currentNode=node;while(currentNode){if(currentNode.className&&typeof currentNode.className==="string"){if(currentNode.className.includes("o_not_editable")){return false;}
if(currentNode.className.includes("o_editable")){return true;}}
currentNode=currentNode.parentNode;}
return false;}
__exports.removePlugins=removePlugins;function removePlugins(plugins,pluginsToRemove){return plugins.filter((p)=>!pluginsToRemove.includes(p.name));}
__exports.isSmallInteger=isSmallInteger;function isSmallInteger(value){return/^-?[0-9]{1,15}$/.test(value);}
return __exports;});;

/* /html_builder/static/src/utils/utils_css.js */
odoo.define('@html_builder/utils/utils_css',['@html_editor/utils/color','@html_editor/utils/dom_traversal','@html_editor/utils/image','@web/core/utils/colors','@html_editor/utils/formatting'],function(require){'use strict';let __exports={};const{EDITOR_COLOR_CSS_VARIABLES,isColorCombinationName}=require("@html_editor/utils/color");const{selectElements}=require("@html_editor/utils/dom_traversal");const{backgroundImageCssToParts,getBgImageURLFromURL}=require("@html_editor/utils/image");const{normalizeCSSColor,isCSSColor,isColorGradient,rgbaToHex}=require("@web/core/utils/colors");const{convertNumericToUnit,getCSSVariableValue}=require("@html_editor/utils/formatting");const CSS_SHORTHANDS=__exports.CSS_SHORTHANDS={"border-width":["border-top-width","border-right-width","border-bottom-width","border-left-width",],"border-radius":["border-top-left-radius","border-top-right-radius","border-bottom-right-radius","border-bottom-left-radius",],"--box-border-width":["--box-border-top-width","--box-border-right-width","--box-border-bottom-width","--box-border-left-width",],"--box-border-radius":["--box-border-top-left-radius","--box-border-top-right-radius","--box-border-bottom-right-radius","--box-border-bottom-left-radius",],"border-color":["border-top-color","border-right-color","border-bottom-color","border-left-color",],"border-style":["border-top-style","border-right-style","border-bottom-style","border-left-style",],padding:["padding-top","padding-right","padding-bottom","padding-left"],};const BACKGROUND_IMAGE_ATTRIBUTES=new Set(["originalId","originalSrc","mimetype","resizeWidth","glFilter","quality","filterOptions","mimetypeBeforeConversion",]);__exports.convertValueToUnit=convertValueToUnit;function convertValueToUnit(value,unitTo,htmlStyle){const m=getNumericAndUnit(value);if(!m){return NaN;}
const numValue=parseFloat(m[0]);const valueUnit=m[1];return convertNumericToUnit(numValue,valueUnit,unitTo,htmlStyle);}
__exports.getNumericAndUnit=getNumericAndUnit;function getNumericAndUnit(value){const m=value.trim().match(/^(-?[0-9.]+(?:e[+|-]?[0-9]+)?)\s*([^\s]*)$/);if(!m){return null;}
return[m[1].trim(),m[2].trim()];}
__exports.areCssValuesEqual=areCssValuesEqual;function areCssValuesEqual(value1,value2,cssProp,htmlStyle){if(value1===value2){return true;}
if(cssProp&&cssProp.endsWith("-size")&&!cssProp.startsWith("--")){const pseudoPartProp=cssProp+"-part";const re=/-?[0-9.]+(?:e[+|-]?[0-9]+)?\s*[A-Za-z%-]+|auto/g;const parts1=value1.match(re);const parts2=value2.match(re);for(const index of[0,1]){const part1=parts1&&parts1.length>index?parts1[index]:"auto";const part2=parts2&&parts2.length>index?parts2[index]:"auto";if(!areCssValuesEqual(part1,part2,pseudoPartProp,htmlStyle)){return false;}}
return true;}
if(isCSSVariable(value1)){value1=getCSSVariableValue(value1.substring(6,value1.length-1),htmlStyle);}
if(isCSSVariable(value2)){value2=getCSSVariableValue(value2.substring(6,value2.length-1),htmlStyle);}
if(value1===value2){return true;}
const color1=normalizeCSSColor(value1);const color2=normalizeCSSColor(value2);if(color1===color2){return true;}
const value1IsGradient=isColorGradient(value1);const value2IsGradient=isColorGradient(value2);if(value1IsGradient!==value2IsGradient){return false;}
if(value1IsGradient){const temp1El=document.createElement("div");temp1El.style.backgroundImage=value1;document.body.appendChild(temp1El);value1=getComputedStyle(temp1El).backgroundImage;document.body.removeChild(temp1El);const temp2El=document.createElement("div");temp2El.style.backgroundImage=value2;document.body.appendChild(temp2El);value2=getComputedStyle(temp2El).backgroundImage;document.body.removeChild(temp2El);return value1===value2;}
if(cssProp==="box-shadow"){const temp1El=document.createElement("div");temp1El.style.boxShadow=value1;document.body.appendChild(temp1El);value1=getComputedStyle(temp1El).boxShadow;document.body.removeChild(temp1El);const temp2El=document.createElement("div");temp2El.style.boxShadow=value2;document.body.appendChild(temp2El);value2=getComputedStyle(temp2El).boxShadow;document.body.removeChild(temp2El);return value1===value2;}
const data=getNumericAndUnit(value1);if(!data){return false;}
const numValue1=data[0];const numValue2=parseFloat(numValue1)===0?getNumericAndUnit(value2)[0]:convertValueToUnit(value2,data[1],htmlStyle);return Math.abs(numValue1-numValue2)<Number.EPSILON;}
__exports.isCSSVariable=isCSSVariable;function isCSSVariable(value){value=value.replace(/^'|'$/g,"");return/^var\(--.+?\)$/.test(value);}
__exports.computeColorClasses=computeColorClasses;function computeColorClasses(colorNames,prefix="bg-"){let hasCCClasses=false;const isBgPrefix=prefix==="bg-";const classes=colorNames.map((c)=>{if(isBgPrefix&&isColorCombinationName(c)){hasCCClasses=true;return`o_cc${c}`;}
return prefix+c;});if(hasCCClasses){classes.push("o_cc");}
return classes;}
__exports.normalizeColor=normalizeColor;function normalizeColor(color,htmlStyle){if(isCSSColor(color)){return color;}
return getCSSVariableValue(color,htmlStyle);}
__exports.getBgImageURLFromEl=getBgImageURLFromEl;function getBgImageURLFromEl(el){const style=el.ownerDocument.defaultView.getComputedStyle(el);const parts=backgroundImageCssToParts(style.backgroundImage);const string=parts.url||"";return getBgImageURLFromURL(string);}
__exports.generateHTMLId=generateHTMLId;function generateHTMLId(){return`o${Math.random().toString(36).substring(2, 15)}`;}
__exports.getColorClass=getColorClass;function getColorClass(el,colorNames,prefix){const prefixedColorNames=computeColorClasses(colorNames,prefix);return el.classList.value.split(" ").filter((cl)=>prefixedColorNames.includes(cl)).join(" ");}
__exports.addBackgroundImageAttributes=addBackgroundImageAttributes;function addBackgroundImageAttributes(...newAttributes){BACKGROUND_IMAGE_ATTRIBUTES.add(...newAttributes);}
__exports.isBackgroundImageAttribute=isBackgroundImageAttribute;function isBackgroundImageAttribute(attribute){return BACKGROUND_IMAGE_ATTRIBUTES.has(attribute);}
__exports.shouldEditableMediaBeEditable=shouldEditableMediaBeEditable;function shouldEditableMediaBeEditable(mediaEl){return mediaEl.parentElement&&mediaEl.parentElement.closest(".o_editable");}
__exports.getLinkLabel=getLinkLabel;function getLinkLabel(linkEl){return linkEl.textContent.replaceAll("\u200B","").replaceAll("\uFEFF","");}
__exports.forwardToThumbnail=forwardToThumbnail;function forwardToThumbnail(imgEl){const carouselEl=imgEl.closest(".carousel");if(carouselEl){const carouselInnerEl=imgEl.closest(".carousel-inner");const carouselItemEl=imgEl.closest(".carousel-item");if(carouselInnerEl&&carouselItemEl){const imageIndex=[...carouselInnerEl.children].indexOf(carouselItemEl);const miniatureEl=carouselEl.querySelector(`.carousel-indicators [data-bs-slide-to="${imageIndex}"]`);if(miniatureEl&&miniatureEl.style.backgroundImage){miniatureEl.style.backgroundImage=`url(${imgEl.getAttribute("src")})`;}}}}
__exports.isImageCorsProtected=isImageCorsProtected;async function isImageCorsProtected(img){const src=img.getAttribute("src");if(!src){return false;}
let isCorsProtected=false;if(!src.startsWith("/")||/\/web\/image\/\d+-redirect\//.test(src)){isCorsProtected=await fetch(src,{method:"HEAD"}).then(()=>false).catch(()=>true);}
return isCorsProtected;}
__exports.applyNeededCss=applyNeededCss;function applyNeededCss(el,cssProp,cssValue,computedStyle=el.ownerDocument.defaultView.getComputedStyle(el),{force=false,allowImportant=true}={}){if(force){el.style.setProperty(cssProp,cssValue,allowImportant?"important":"");return true;}
el.style.removeProperty(cssProp);if(!areCssValuesEqual(computedStyle.getPropertyValue(cssProp),cssValue,cssProp,computedStyle)){el.style.setProperty(cssProp,cssValue);if(allowImportant&&!areCssValuesEqual(computedStyle.getPropertyValue(cssProp),cssValue,cssProp,computedStyle)){el.style.setProperty(cssProp,cssValue,"important");}
return true;}
return false;}
const builderStylesheet=new CSSStyleSheet();__exports.setBuilderCSSVariables=setBuilderCSSVariables;function setBuilderCSSVariables(htmlStyle){const styles=[];for(const style of EDITOR_COLOR_CSS_VARIABLES){let value=getCSSVariableValue(style,htmlStyle);if(value.startsWith("'")&&value.endsWith("'")){value=value.substring(1,value.length-1);}
styles.push(`--hb-cp-${style}: ${value};`);}
builderStylesheet.replaceSync(`html { ${styles.join(" ")} }`);if(!window.top.document.adoptedStyleSheets.find((style)=>style===builderStylesheet)){window.top.document.adoptedStyleSheets.push(builderStylesheet);}}
__exports.parseBoxShadow=parseBoxShadow;function parseBoxShadow(value){const regex=/(?<color>(rgb(a)?\([^)]*\))|(var\([^)]+\)))\s+(?<offsetX>-?\d+\.?\d*px)\s+(?<offsetY>-?\d+\.?\d*px)\s+(?<blur>-?\d+\.?\d*px)\s+(?<spread>-?\d+\.?\d*px)(?:\s+(?<mode>\w+))?/;return value.match(regex)?.groups??{};}
__exports.getAllUsedColors=getAllUsedColors;function getAllUsedColors(el){const usedCustomColors=new Set();const collectColor=(colorValue)=>{if(isCSSColor(colorValue)){usedCustomColors.add(rgbaToHex(colorValue));}};for(const coloredEl of selectElements(el,'[style*="color"]')){for(const colorProperty of["color","background-color","border-color"]){collectColor(coloredEl.style[colorProperty]);}}
for(const shadowEl of selectElements(el,'[style*="box-shadow"]')){const shadowValue=shadowEl.style["box-shadow"];if(shadowValue){collectColor(parseBoxShadow(shadowValue).color);}}
for(const dataColoredEl of selectElements(el,"*")){for(const attributeName of Object.keys(dataColoredEl.dataset)){if(attributeName.endsWith("olor")){collectColor(dataColoredEl.dataset[attributeName]);}}}
const collectUrlColors=(urlString)=>{const url=new URL(urlString,window.location);for(const colorKey of[...url.searchParams.keys()].filter((key)=>/c\d/.test(key))){collectColor(url.searchParams.get(colorKey));}};for(const imgEl of selectElements(el,'img[src^="/html_editor/shape/"], img[src^="/web_editor/shape/"]')){collectUrlColors(imgEl.src);}
for(const bgEl of selectElements(el,`[style*="background-image: url(\\"/html_editor/shape/"], [style*="background-image: url(\\"/web_editor/shape/"]`)){collectUrlColors(getBgImageURLFromEl(bgEl));}
return usedCustomColors;}
return __exports;});;

/* /mass_mailing/static/src/builder/builder_overlay_patch.js */
odoo.define('@mass_mailing/builder/builder_overlay_patch',['@html_builder/core/builder_overlay/builder_overlay','@web/core/utils/patch'],function(require){'use strict';let __exports={};const{sizingGrid,sizingX,sizingY}=require("@html_builder/core/builder_overlay/builder_overlay");const{patch}=require("@web/core/utils/patch");patch(sizingX,{selector:sizingX.selector+", .row > div",exclude:sizingX.exclude+", .o_mail_no_options, .s_col_no_resize.row > div, .s_col_no_resize",});patch(sizingY,{selector:sizingY.selector+", .o_mail_snippet_general, .o_mail_snippet_general .row > div",exclude:sizingY.exclude+", .o_mail_no_options, .s_col_no_resize.row > div, .s_col_no_resize",});patch(sizingGrid,{exclude:sizingY.exclude+", .o_mail_no_options, .s_col_no_resize.row > div, .s_col_no_resize",});return __exports;});;

/* /mass_mailing/static/src/builder/fontfamily_picker.js */
odoo.define('@mass_mailing/builder/fontfamily_picker',['@html_builder/core/utils'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const FONT_FAMILIES=__exports.FONT_FAMILIES={Arial:"Arial,Helvetica Neue,Helvetica,sans-serif","Courier New":"Courier New,Courier,Lucida Sans Typewriter,Lucida Typewriter,monospace",Georgia:"Georgia,Times,Times New Roman,serif","Helvetica Neue":"Helvetica Neue,Helvetica,Arial,sans-serif","Lucida Grande":"Lucida Grande,Lucida Sans Unicode,Lucida Sans,Geneva,Verdana,sans-serif",Tahoma:"Tahoma,Verdana,Segoe,sans-serif","Times New Roman":"TimesNewRoman,Times New Roman,Times,Baskerville,Georgia,serif","Trebuchet MS":"Trebuchet MS,Lucida Grande,Lucida Sans Unicode,Lucida Sans,Tahoma,sans-serif",Verdana:"Verdana,Geneva,sans-serif",};const FontFamilyPicker=__exports.FontFamilyPicker=class FontFamilyPicker extends BaseOptionComponent{static template="mass_mailing.FontFamilyPicker";static props={action:String,actionParam:Object,extraClass:{type:String,optional:true},};FONT_FAMILIES=FONT_FAMILIES;}
return __exports;});;

/* /mass_mailing/static/src/builder/mass_mailing_builder.js */
odoo.define('@mass_mailing/builder/mass_mailing_builder',['@odoo/owl','@html_builder/builder','@html_builder/core/core_plugins','@html_builder/utils/utils','@html_editor/backend/plugin_sets','@web/core/registry','@html_builder/sidebar/customize_tab','@mass_mailing/builder/options/options_container','@html_editor/main/power_buttons_plugin'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const{Builder}=require("@html_builder/builder");const{CORE_PLUGINS}=require("@html_builder/core/core_plugins");const{removePlugins}=require("@html_builder/utils/utils");const{DYNAMIC_PLACEHOLDER_PLUGINS}=require("@html_editor/backend/plugin_sets");const{registry}=require("@web/core/registry");const{CustomizeTab}=require("@html_builder/sidebar/customize_tab");const{OptionsContainerWithSnippetVersionControl}=require("@mass_mailing/builder/options/options_container");const{PowerButtonsPlugin}=require("@html_editor/main/power_buttons_plugin");class CustomizeTabWithSnippetVersionControl extends CustomizeTab{static components={...CustomizeTab.components,OptionsContainer:OptionsContainerWithSnippetVersionControl,};}
class BuilderWithSnippetVersionControl extends Builder{static components={...Builder.components,CustomizeTab:CustomizeTabWithSnippetVersionControl,};}
const MassMailingBuilder=__exports.MassMailingBuilder=class MassMailingBuilder extends Component{static template="mass_mailing.MassMailingBuilder";static components={Builder:BuilderWithSnippetVersionControl};static props={builderProps:{type:Object},toggleCodeView:{type:Function,optional:true},toggleFullScreen:{type:Function},};get builderProps(){const builderProps=Object.assign({},this.props.builderProps);const pluginsToRemove=["BuilderFontPlugin","SavePlugin","SaveSnippetPlugin","AnchorPlugin","ColorUIPlugin","EmbeddedFilePlugin","FilePlugin","AddDocumentsAttachmentPlugin","BannerPlugin","CTABadgeOptionPlugin","OperationPlugin",];const massMailingPlugins=removePlugins([...registry.category("builder-plugins").getAll(),...registry.category("mass_mailing-plugins").getAll(),],pluginsToRemove);const builderEditorPlugins=removePlugins([...CORE_PLUGINS,PowerButtonsPlugin],pluginsToRemove);const optionalPlugins=[...(this.props.builderProps.config.dynamicPlaceholder?removePlugins(DYNAMIC_PLACEHOLDER_PLUGINS,["PromptPlugin"]):[]),];builderProps.Plugins=[...builderEditorPlugins,...massMailingPlugins,...optionalPlugins];return builderProps;}}
registry.category("lazy_components").add("mass_mailing.MassMailingBuilder",MassMailingBuilder);return __exports;});;

/* /mass_mailing/static/src/builder/options/image_tool_option.js */
odoo.define('@mass_mailing/builder/options/image_tool_option',['@html_builder/core/utils','@html_builder/plugins/image/image_tool_option'],function(require){'use strict';let __exports={};const{useDomState}=require("@html_builder/core/utils");const{ImageToolOption}=require("@html_builder/plugins/image/image_tool_option");const MassMailingImageToolOption=__exports.MassMailingImageToolOption=class MassMailingImageToolOption extends ImageToolOption{static template="mass_mailing.ImageToolOption";setup(){super.setup();this.massMailingState=useDomState((editingElement)=>({isImgFluid:editingElement.classList.contains("img-fluid"),}));}}
return __exports;});;

/* /mass_mailing/static/src/builder/options/options_container.js */
odoo.define('@mass_mailing/builder/options/options_container',['@html_builder/sidebar/option_container','@odoo/owl'],function(require){'use strict';let __exports={};const{OptionsContainer}=require("@html_builder/sidebar/option_container");const{useState}=require("@odoo/owl");const OptionsContainerWithSnippetVersionControl=__exports.OptionsContainerWithSnippetVersionControl=class OptionsContainerWithSnippetVersionControl extends OptionsContainer{static template="mass_mailing.OptionsContainer";setup(){super.setup();this.versionState=useState({isUpToDate:this.env.editor.shared.versionControl.hasAccessToOutdatedEl(this.props.editingElement),});}
replaceElementWithNewVersion(){this.callOperation(()=>{this.env.editor.shared.versionControl.replaceWithNewVersion(this.props.editingElement);});}
accessOutdated(){this.env.editor.shared.versionControl.giveAccessToOutdatedEl(this.props.editingElement);this.versionState.isUpToDate=true;}}
return __exports;});;

/* /mass_mailing/static/src/builder/options/snippet_visibility_option.js */
odoo.define('@mass_mailing/builder/options/snippet_visibility_option',['@html_builder/core/utils','@web/core/domain','@web/core/domain_selector_dialog/domain_selector_dialog','@web/core/utils/hooks'],function(require){'use strict';let __exports={};const{BaseOptionComponent,useDomState}=require("@html_builder/core/utils");const{Domain}=require("@web/core/domain");const{DomainSelectorDialog}=require("@web/core/domain_selector_dialog/domain_selector_dialog");const{useService}=require("@web/core/utils/hooks");const SnippetVisibilityOption=__exports.SnippetVisibilityOption=class SnippetVisibilityOption extends BaseOptionComponent{static template="mass_mailing.VisibilityOption";static selector="section";static dependencies=["mass_mailing.SnippetVisibility"];setup(){super.setup();this.getModel=this.dependencies["mass_mailing.SnippetVisibility"].getModel;this.treeProcessor=useService("tree_processor");this.dialog=useService("dialog");this.historyPlugin=this.env.editor.shared.history;this.overlayButtonsPlugin=this.env.editor.shared.overlayButtons;this.state=useDomState((editingElement)=>{const currentDomain=new Domain(JSON.parse(editingElement.dataset.filterDomain||"[]"));this.parseTree(currentDomain);return{domain:currentDomain,};});}
get stringifiedDomain(){return JSON.stringify(this.state.domain.toJson());}
async parseTree(domain){const resModel=this.getModel();const tree=await this.treeProcessor.treeFromDomain(resModel,domain,!this.env.debug);const trees=!tree.negate&&tree.value==="&"?tree.children:[tree];this.state.facets=await Promise.all(trees.map((tree)=>this.treeProcessor.getDomainTreeDescription(resModel,tree,false,2,1)));}
onClickEditDomain(){this.overlayButtonsPlugin.hideOverlayButtonsUi();this.dialog.add(DomainSelectorDialog,{resModel:this.getModel(),domain:this.state.domain.toString(),isDebugMode:!!this.env.debug,onConfirm:(domain)=>{const newDomain=new Domain(domain);this.state.domain=newDomain;this.env.getEditingElement().dataset.filterDomain=JSON.stringify(this.state.domain.toJson());this.parseTree(newDomain);this.config.onChange?.({isPreviewing:false});},},{onClose:()=>{this.overlayButtonsPlugin.showOverlayButtonsUi();},});}}
return __exports;});;

/* /mass_mailing/static/src/builder/plugins/alert_option_plugin.js */
odoo.define('@mass_mailing/builder/plugins/alert_option_plugin',['@html_builder/core/utils','@html_builder/plugins/border_configurator_option','@html_builder/utils/option_sequence','@html_editor/plugin','@html_editor/utils/resource','@web/core/registry'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const{BorderConfigurator}=require("@html_builder/plugins/border_configurator_option");const{after,WIDTH}=require("@html_builder/utils/option_sequence");const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{registry}=require("@web/core/registry");const AlertOption=__exports.AlertOption=class AlertOption extends BaseOptionComponent{static template="mass_mailing.AlertOption";static selector=".s_mail_alert .s_alert";}
const BorderOption=__exports.BorderOption=class BorderOption extends BaseOptionComponent{static template="mass_mailing.BorderOption";static selector=".s_mail_alert .s_alert";static components={BorderConfigurator};}
class AlertOptionPlugin extends Plugin{static id="mass_mailing.AlertOption";resources={builder_options:[withSequence(after(WIDTH),AlertOption),withSequence(after(WIDTH),BorderOption),],patch_builder_options:[{target_name:"alertTypeOption",target_element:"exclude",method:"replace",value:".s_mail_alert .s_alert",},],};}
registry.category("mass_mailing-plugins").add(AlertOptionPlugin.id,AlertOptionPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/background_option_plugin.js */
odoo.define('@mass_mailing/builder/plugins/background_option_plugin',['@html_builder/plugins/background_option/background_option','@html_editor/plugin','@web/core/registry'],function(require){'use strict';let __exports={};const{BackgroundOption}=require("@html_builder/plugins/background_option/background_option");const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const MailingBackgroundOption=__exports.MailingBackgroundOption=class MailingBackgroundOption extends BackgroundOption{static selector=".s_masonry_block > .container > .row > div:not(:has(.row)), .s_cover > .container > .row > div, .s_reviews_wall";static props={...BackgroundOption.props,withColors:{type:Boolean,optional:true},withImages:{type:Boolean,optional:true},withColorCombinations:{type:Boolean,optional:true},};static defaultProps={withImages:true,withColors:false,withColorCombinations:false,};}
class BackgroundOptionPlugin extends Plugin{static id="mass_mailing.BackgroundOption";resources={builder_options:MailingBackgroundOption,};}
registry.category("mass_mailing-plugins").add(BackgroundOptionPlugin.id,BackgroundOptionPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/border_option_plugin.js */
odoo.define('@mass_mailing/builder/plugins/border_option_plugin',['@html_builder/core/utils','@html_builder/plugins/border_configurator_option','@html_builder/utils/option_sequence','@html_editor/plugin','@html_editor/utils/resource','@web/core/registry'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const{BorderConfigurator}=require("@html_builder/plugins/border_configurator_option");const{before,VERTICAL_ALIGNMENT,WIDTH}=require("@html_builder/utils/option_sequence");const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{registry}=require("@web/core/registry");class MassMailingBorderOption extends BaseOptionComponent{static template="mass_mailing.BorderOption";static components={BorderConfigurator};withRoundCorner=true;}
const BorderOption1=__exports.BorderOption1=class BorderOption1 extends MassMailingBorderOption{static selector=".s_three_columns .row > div, .s_comparisons .row > div, .s_mail_block_event .row > div";static applyTo=".card";}
const BorderOption2=__exports.BorderOption2=class BorderOption2 extends MassMailingBorderOption{static selector=".s_text_block, .o_mail_block_discount2";}
const BorderOption3=__exports.BorderOption3=class BorderOption3 extends MassMailingBorderOption{static selector="table, table td, table tr";withRoundCorner=false;}
const BorderOption4=__exports.BorderOption4=class BorderOption4 extends MassMailingBorderOption{static selector=".row > div";static exclude=[".o_mail_wrapper_td, .s_image_gallery .row > div",BorderOption1.selector,BorderOption2.selector,BorderOption3.selector,].join(",");}
const BorderOptionPlugin=__exports.BorderOptionPlugin=class BorderOptionPlugin extends Plugin{static id="mass_mailing.BorderOption";resources={builder_options:[withSequence(before(WIDTH),BorderOption1),withSequence(before(WIDTH),BorderOption2),withSequence(before(WIDTH),BorderOption3),withSequence(VERTICAL_ALIGNMENT,BorderOption4),],};}
registry.category("mass_mailing-plugins").add(BorderOptionPlugin.id,BorderOptionPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/color_ui_plugin.js */
odoo.define('@mass_mailing/builder/plugins/color_ui_plugin',['@html_builder/core/color_ui_plugin','@web/core/registry'],function(require){'use strict';let __exports={};const{ColorUIPlugin}=require("@html_builder/core/color_ui_plugin");const{registry}=require("@web/core/registry");const MassMailingColorUIPlugin=__exports.MassMailingColorUIPlugin=class MassMailingColorUIPlugin extends ColorUIPlugin{getPropsForColorSelector(type){const props={...super.getPropsForColorSelector(type)};props.enabledTabs=["solid","custom"];return props;}}
registry.category("mass_mailing-plugins").add(MassMailingColorUIPlugin.id,MassMailingColorUIPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/colorpicker_option_plugin.js */
odoo.define('@mass_mailing/builder/plugins/colorpicker_option_plugin',['@html_builder/core/utils','@html_builder/utils/option_sequence','@html_editor/plugin','@html_editor/utils/resource','@web/core/registry'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const{before,VERTICAL_ALIGNMENT}=require("@html_builder/utils/option_sequence");const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{registry}=require("@web/core/registry");const ColorPickerOption=__exports.ColorPickerOption=class ColorPickerOption extends BaseOptionComponent{static template="mass_mailing.ColorPickerOption";static selector=`.note-editable .oe_structure > div:not(:has(> .o_mail_snippet_general)),
        .note-editable .oe_structure > .o_mail_snippet_general,
        .note-editable .oe_structure > .o_mail_snippet_general .o_cc,
        .s_mail_color_blocks_2 .row > div, table td, .s_cta_badge`;static exclude=".o_mail_no_colorpicker, .o_mail_no_options, .s_mail_color_blocks_2";}
const ColorPickerOption2=__exports.ColorPickerOption2=class ColorPickerOption2 extends BaseOptionComponent{static template="mass_mailing.ColorPickerOption";static selector=".s_three_columns .row > div, .s_comparisons .row > div, .s_mail_block_event .row > div";static applyTo=".card-body, .card-footer";}
class ColorPickerOptionPlugin extends Plugin{static id="mass_mailing.ColorPicker";colorPickerSelector=ColorPickerOption.selector;resources={builder_options:[withSequence(before(VERTICAL_ALIGNMENT),ColorPickerOption),ColorPickerOption2,],};}
registry.category("mass_mailing-plugins").add(ColorPickerOptionPlugin.id,ColorPickerOptionPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/company_teams_option_plugin.js */
odoo.define('@mass_mailing/builder/plugins/company_teams_option_plugin',['@html_builder/core/utils','@html_editor/plugin','@html_editor/utils/resource','@web/core/registry'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{registry}=require("@web/core/registry");class CompanyTeamShapesWidthOption extends BaseOptionComponent{static selector=".s_company_team_shapes";static template="mass_mailing.CompanyTeamShapesWidth";}
const CompanyTeamOptionPlugin=__exports.CompanyTeamOptionPlugin=class CompanyTeamOptionPlugin extends Plugin{static id="mass_mailing.CompanyTeamOption";resources={builder_options:[withSequence(1,CompanyTeamShapesWidthOption)],};}
registry.category("mass_mailing-plugins").add(CompanyTeamOptionPlugin.id,CompanyTeamOptionPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/cta_badge_plugin.js */
odoo.define('@mass_mailing/builder/plugins/cta_badge_plugin',['@html_builder/plugins/cta_badge_option_plugin','@html_builder/utils/option_sequence','@html_editor/plugin','@html_editor/utils/resource','@web/core/registry'],function(require){'use strict';let __exports={};const{CTABadgeOption}=require("@html_builder/plugins/cta_badge_option_plugin");const{BLOCK_ALIGN}=require("@html_builder/utils/option_sequence");const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{registry}=require("@web/core/registry");const MassMailingCTABadgeOption=__exports.MassMailingCTABadgeOption=class MassMailingCTABadgeOption extends CTABadgeOption{static selector=".s_cta_badge";static template="mass_mailing.CTABadgeOption";}
const CTABadgePlugin=__exports.CTABadgePlugin=class CTABadgePlugin extends Plugin{static id="mass_mailing.CTABadgePlugin";resources={builder_options:[withSequence(BLOCK_ALIGN,MassMailingCTABadgeOption)],so_content_addition_selector:[".s_cta_badge"],};}
registry.category("mass_mailing-plugins").add(CTABadgePlugin.id,CTABadgePlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/customize_mailing_plugin.js */
odoo.define('@mass_mailing/builder/plugins/customize_mailing_plugin',['@html_builder/core/builder_action','@html_editor/plugin','@web/core/registry','@web/core/utils/functions','@mass_mailing/builder/plugins/customize_mailing_variables','@mail/views/web/fields/html_mail_field/convert_inline','@html_editor/utils/formatting'],function(require){'use strict';let __exports={};const{BuilderAction}=require("@html_builder/core/builder_action");const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{memoize}=require("@web/core/utils/functions");const{CUSTOMIZE_MAILING_VARIABLES}=require("@mass_mailing/builder/plugins/customize_mailing_variables");const{CUSTOMIZE_MAILING_VARIABLES_DEFAULTS}=require("@mass_mailing/builder/plugins/customize_mailing_variables");const{splitSelectorAroundCommasOutsideParentheses}=require("@mail/views/web/fields/html_mail_field/convert_inline");const{getCSSVariableValue}=require("@html_editor/utils/formatting");const RE_SELECTOR_ENDS_WITH_GT_STAR=/>\s*\*\s*$/;const PRIORITY_STYLES=__exports.PRIORITY_STYLES={h1:new Set(["font-family"]),h2:new Set(["font-family"]),h3:new Set(["font-family"]),p:new Set(["font-family"]),hr:new Set(["border-top-width","border-top-style","border-top-color"]),};const CustomizeMailingPlugin=__exports.CustomizeMailingPlugin=class CustomizeMailingPlugin extends Plugin{static id="mass_mailing.CustomizeMailingPlugin";static dependencies=[];static shared=["getVariableValue","setVariable"];resources={builder_actions:{CustomizeMailingVariable,},clean_for_save_handlers:({root})=>this.cleanForSave(root),snippet_preview_dialog_stylesheets_handlers:({iframe})=>{const styleSheet=this.extractStylesheetForPreview(iframe.contentDocument);iframe.contentDocument.adoptedStyleSheets.push(styleSheet);},};getRule=memoize((selector)=>this._getRule(selector));setup(){this.iframeWindow=this.document.defaultView;this.cssPrefix=".o_layout .o_mail_wrapper .o_mail_wrapper_td";this.styleSheet=new this.iframeWindow.CSSStyleSheet();const styleEl=this.editable.querySelector("#design-element");if(styleEl){this.parseDesignElement(styleEl);styleEl.remove();}
this.setupMailingVariables();this.document.adoptedStyleSheets=[...this.document.adoptedStyleSheets,this.styleSheet];}
cleanForSave(clone){const layoutEl=clone.querySelector(".o_layout");if(!layoutEl){return;}
const styleEl=this.document.createElement("STYLE");styleEl.id="design-element";const cssTextArray=[];for(const rule of Array.from(this.styleSheet.cssRules)){if(!rule.style.length){continue;}
cssTextArray.push(rule.cssText);}
styleEl.textContent=cssTextArray.join("\n");layoutEl.prepend(styleEl);}
extractStylesheetForPreview(contentDocument){const cssRules=this.styleSheet.cssRules;const newStyleSheet=new contentDocument.defaultView.CSSStyleSheet();for(const cssRule of cssRules){let previewRule=cssRule.cssText.replace(this.cssPrefix,".o_add_snippets_preview");if(previewRule.includes("> [data-snippet]")){previewRule=previewRule.replace("> [data-snippet]",".o_snippet_preview_wrap [data-snippet]");}
newStyleSheet.insertRule(previewRule);}
return newStyleSheet;}
setupMailingVariables(){const varRule=this.getRule(this.cssPrefix);for(const variable of Object.keys(CUSTOMIZE_MAILING_VARIABLES)){const currentValue=this.getVariableValue(variable);const defaultValue=Object.values(CUSTOMIZE_MAILING_VARIABLES_DEFAULTS[variable]??{})[0]??"";if(currentValue===""&&defaultValue!==""){varRule.style.setProperty(variable,defaultValue);}
this.refreshMailingVariableSelector(variable);}}
refreshMailingVariableSelector(variable){const options=CUSTOMIZE_MAILING_VARIABLES[variable];const currentValue=this.getVariableValue(variable);let value="";if(currentValue!==""){value=`var(${variable})`;}
for(const selector of options.selectors){const rule=this.getRule(selector);for(const property of options.properties){const important=PRIORITY_STYLES[selector]?.has(property)?"important":"";rule.style.setProperty(property,value,important);}}}
parseDesignElement(styleEl){const rules=[...styleEl.sheet.cssRules];for(const rule of rules){for(const selector of splitSelectorAroundCommasOutsideParentheses(rule.selectorText)){for(const property of rule.style){const selectors=property!=="font-family"?[selector]:this.transformFontFamilySelector(selector);for(const selector of selectors){this.addCSSRule(selector,rule.style,property);}}}}}
addSelectorPrefix(selector){if(!selector.trim().startsWith(this.cssPrefix)){return`${this.cssPrefix} ${selector}`;}
return selector;}
_getRule(selector){selector=this.addSelectorPrefix(selector);for(const rule of this.styleSheet.cssRules){if(rule.selectorText===selector){return rule;}}
return this.styleSheet.cssRules.item(this.styleSheet.insertRule(`${selector} { }`));}
getVariableValue(variable){return this.getRule(this.cssPrefix).style.getPropertyValue(variable);}
setVariable(variable,value){const currentValue=this.getVariableValue(variable);this.getRule(this.cssPrefix).style.setProperty(variable,value);if(Boolean(currentValue)!==Boolean(value)){this.refreshMailingVariableSelector(variable);}}
transformFontFamilySelector(selector){if(selector.trim().endsWith(":not(.fa)")){return[selector];}
if(!selector.endsWith("*")){return[`${selector.trim()}:not(.fa)`,`${selector.trim()} :not(.fa)`];}else if(RE_SELECTOR_ENDS_WITH_GT_STAR.test(selector)){return[`${selector.replace(RE_SELECTOR_ENDS_WITH_GT_STAR, "").trim()} :not(.fa)`];}}
addCSSRule(selector,ruleStyle,property){selector=selector.trim();const rule=this.getRule(selector);rule.style.setProperty(property,ruleStyle.getPropertyValue(property),ruleStyle.getPropertyPriority(property));}}
const CustomizeMailingVariable=__exports.CustomizeMailingVariable=class CustomizeMailingVariable extends BuilderAction{static id="mass_mailing.CustomizeMailingVariable";static dependencies=["builderActions","color","mass_mailing.CustomizeMailingPlugin","history",];isApplied({value}){return this.getValue(...arguments)===value;}
getValue({params}){const variable=this.dependencies["mass_mailing.CustomizeMailingPlugin"].getVariableValue(params.variable);if(!params.variable.includes("color")||!/var\(/g.test(variable)){return variable;}
const match=variable.match(/var\(--([\w-]+)\)/)[1];return getCSSVariableValue(match,this.window.getComputedStyle(this.document.documentElement));}
apply({params,value}){const oldValue=this.getValue(...arguments);this.dependencies.history.applyCustomMutation({apply:()=>{this.dependencies["mass_mailing.CustomizeMailingPlugin"].setVariable(params.variable,value);},revert:()=>{this.dependencies["mass_mailing.CustomizeMailingPlugin"].setVariable(params.variable,oldValue);},});}
clean({params}){const oldValue=this.getValue(...arguments);this.dependencies.history.applyCustomMutation({apply:()=>{this.dependencies["mass_mailing.CustomizeMailingPlugin"].setVariable(params.variable,params.clean??"");},revert:()=>{this.dependencies["mass_mailing.CustomizeMailingPlugin"].setVariable(params.variable,oldValue);},});}}
registry.category("mass_mailing-plugins").add(CustomizeMailingPlugin.id,CustomizeMailingPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/customize_mailing_variables.js */
odoo.define('@mass_mailing/builder/plugins/customize_mailing_variables',['@html_editor/utils/base_container'],function(require){'use strict';let __exports={};const{BASE_CONTAINER_CLASS}=require("@html_editor/utils/base_container");function getProperties(propertyDescription){switch(propertyDescription){case"padding-y":return["padding-top","padding-bottom"];case"padding-x":return["padding-left","padding-right"];default:return[propertyDescription];}}
function generateSimpleMailingVariables(prefix,selectors,properties){const variables={};for(const propertyDescription of properties){variables[`--${prefix}-${propertyDescription}`]={properties:getProperties(propertyDescription),selectors:selectors,};}
return variables;}
const wrapperProperties=["background-color",];const textProperties=["font-size","font-weight","font-style","font-family","text-decoration-line","color",];const textContainerProperties=["margin-bottom",];const buttonProperties=[...textProperties,"background-color","padding-x","padding-y","border-style","border-width","border-color",];const sizedButtonProperties=["font-size","padding-x","padding-y",];const outlinedButtonProperties=["background-color","color","border-color",];const separatorProperties=["border-top-width","border-style","border-color","width",];const CUSTOMIZE_MAILING_VARIABLES=__exports.CUSTOMIZE_MAILING_VARIABLES=Object.assign(generateSimpleMailingVariables("wrapper",["> [data-snippet]"],wrapperProperties),(()=>{const variables={};for(const depth of[1,2,3]){const prefix=`h${depth}`;Object.assign(variables,generateSimpleMailingVariables(prefix,[prefix],[...textProperties,...textContainerProperties]));}
return variables;})(),generateSimpleMailingVariables("text",[`.${BASE_CONTAINER_CLASS}`,"p","li"],textProperties),generateSimpleMailingVariables("text-container",["p","ul"],textContainerProperties),generateSimpleMailingVariables("link",["a:not(.btn):not(:has(.fa, img))","a.btn.btn-link"],textProperties),generateSimpleMailingVariables("btn-primary",["a.btn.btn-fill-primary","a.btn.btn-outline-primary","a.btn.btn-primary"],buttonProperties),generateSimpleMailingVariables("btn-secondary",["a.btn.btn-fill-secondary","a.btn.btn-outline-secondary","a.btn.btn-secondary"],buttonProperties),generateSimpleMailingVariables("btn-primary-lg",["a.btn.btn-fill-primary.btn-lg","a.btn.btn-outline-primary.btn-lg","a.btn.btn-primary.btn-lg"],sizedButtonProperties),generateSimpleMailingVariables("btn-primary-sm",["a.btn.btn-fill-primary.btn-sm","a.btn.btn-outline-primary.btn-sm","a.btn.btn-primary.btn-sm"],sizedButtonProperties),generateSimpleMailingVariables("btn-secondary-lg",["a.btn.btn-fill-secondary.btn-lg","a.btn.btn-outline-secondary.btn-lg","a.btn.btn-secondary.btn-lg"],sizedButtonProperties),generateSimpleMailingVariables("btn-secondary-sm",["a.btn.btn-fill-secondary.btn-sm","a.btn.btn-outline-secondary.btn-sm","a.btn.btn-secondary.btn-sm"],sizedButtonProperties),generateSimpleMailingVariables("btn-primary-outline",["a.btn.btn-outline-primary"],outlinedButtonProperties),generateSimpleMailingVariables("btn-secondary-outline",["a.btn.btn-outline-secondary"],outlinedButtonProperties),generateSimpleMailingVariables("separator",["hr"],separatorProperties));const CUSTOMIZE_MAILING_VARIABLES_DEFAULTS=__exports.CUSTOMIZE_MAILING_VARIABLES_DEFAULTS={"--wrapper-background-color":{"background-color":"#FFFFFF",},"--h1-font-size":{"font-size":"28px",},"--h1-font-weight":{"font-weight":"500",},"--h1-font-style":{"font-style":"",},"--h1-font-family":{"font-family":"Arial,Helvetica Neue,Helvetica,sans-serif",},"--h1-text-decoration-line":{"text-decoration-line":"",},"--h1-color":{color:"rgb(0, 0, 0)",},"--h1-margin-bottom":{"margin-bottom":"7px",},"--h2-font-size":{"font-size":"23px",},"--h2-font-weight":{"font-weight":"500",},"--h2-font-style":{"font-style":"",},"--h2-font-family":{"font-family":"Arial,Helvetica Neue,Helvetica,sans-serif",},"--h2-text-decoration-line":{"text-decoration-line":"",},"--h2-color":{color:"rgb(0, 0, 0)",},"--h2-margin-bottom":{"margin-bottom":"7px",},"--h3-font-size":{"font-size":"20px",},"--h3-font-weight":{"font-weight":"500",},"--h3-font-style":{"font-style":"",},"--h3-font-family":{"font-family":"Arial,Helvetica Neue,Helvetica,sans-serif",},"--h3-text-decoration-line":{"text-decoration-line":"",},"--h3-color":{color:"rgb(0, 0, 0)",},"--h3-margin-bottom":{"margin-bottom":"7px",},"--text-font-size":{"font-size":"16px",},"--text-font-weight":{"font-weight":"400",},"--text-font-style":{"font-style":"",},"--text-font-family":{"font-family":"Arial,Helvetica Neue,Helvetica,sans-serif",},"--text-text-decoration-line":{"text-decoration-line":"",},"--text-color":{color:"rgb(0, 0, 0)",},"--text-container-margin-bottom":{"margin-bottom":"16px",},"--link-font-size":{"font-size":"16px",},"--link-font-weight":{"font-weight":"400",},"--link-font-style":{"font-style":"",},"--link-font-family":{"font-family":"Arial,Helvetica Neue,Helvetica,sans-serif",},"--link-text-decoration-line":{"text-decoration-line":"",},"--link-color":{color:"rgb(113, 75, 103)",},"--btn-primary-font-size":{"font-size":"12px",},"--btn-primary-color":{color:"rgb(255, 255, 255)",},"--btn-primary-background-color":{"background-color":"rgb(53, 151, 156)",},"--btn-primary-padding-x":{"padding-left":"10px","padding-right":"10px",},"--btn-primary-padding-y":{"padding-top":"5px","padding-bottom":"5px",},"--btn-primary-font-family":{"font-family":"Arial,Helvetica Neue,Helvetica,sans-serif",},"--btn-primary-border-style":{"border-style":"solid",},"--btn-primary-border-width":{"border-width":"1px",},"--btn-primary-border-color":{"border-color":"rgb(53, 151, 156)",},"--btn-primary-lg-font-size":{"font-size":"calc(var(--btn-primary-font-size) * 1.5)",},"--btn-primary-lg-padding-x":{"padding-left":"calc(var(--btn-primary-padding-x) * 2.5)","padding-right":"calc(var(--btn-primary-padding-x) * 2.5)",},"--btn-primary-lg-padding-y":{"padding-top":"calc(var(--btn-primary-padding-y) * 1.5)","padding-bottom":"calc(var(--btn-primary-padding-y) * 1.5)",},"--btn-primary-sm-font-size":{"font-size":"calc(var(--btn-primary-font-size) * 0.875)",},"--btn-primary-sm-padding-x":{"padding-left":"calc(var(--btn-primary-padding-x) * 0.3)","padding-right":"calc(var(--btn-primary-padding-x) * 0.3)",},"--btn-primary-sm-padding-y":{"padding-top":"calc(var(--btn-primary-padding-y) * 0.20)","padding-bottom":"calc(var(--btn-primary-padding-y) * 0.20)",},"--btn-primary-outline-color":{color:"var(--btn-primary-background-color)",},"--btn-primary-outline-background-color":{"background-color":"transparent",},"--btn-primary-outline-border-color":{"border-color":"var(--btn-primary-background-color)",},"--btn-secondary-font-size":{"font-size":"12px",},"--btn-secondary-color":{color:"rgb(255, 255, 255)",},"--btn-secondary-background-color":{"background-color":"rgb(104, 85, 99)",},"--btn-secondary-padding-x":{"padding-left":"10px","padding-right":"10px",},"--btn-secondary-padding-y":{"padding-top":"5px","padding-bottom":"5px",},"--btn-secondary-font-family":{"font-family":"Arial,Helvetica Neue,Helvetica,sans-serif",},"--btn-secondary-border-style":{"border-style":"solid",},"--btn-secondary-border-width":{"border-width":"1px",},"--btn-secondary-border-color":{"border-color":"rgb(104, 85, 99)",},"--btn-secondary-lg-font-size":{"font-size":"calc(var(--btn-secondary-font-size) * 1.5)",},"--btn-secondary-lg-padding-x":{"padding-left":"calc(var(--btn-secondary-padding-x) * 2.5)","padding-right":"calc(var(--btn-secondary-padding-x) * 2.5)",},"--btn-secondary-lg-padding-y":{"padding-top":"calc(var(--btn-secondary-padding-y) * 1.5)","padding-bottom":"calc(var(--btn-secondary-padding-y) * 1.5)",},"--btn-secondary-sm-font-size":{"font-size":"calc(var(--btn-secondary-font-size) * 0.875)",},"--btn-secondary-sm-padding-x":{"padding-left":"calc(var(--btn-secondary-padding-x) * 0.3)","padding-right":"calc(var(--btn-secondary-padding-x) * 0.3)",},"--btn-secondary-sm-padding-y":{"padding-top":"calc(var(--btn-secondary-padding-y) * 0.20)","padding-bottom":"calc(var(--btn-secondary-padding-y) * 0.20)",},"--btn-secondary-outline-color":{color:"var(--btn-secondary-background-color)",},"--btn-secondary-outline-background-color":{"background-color":"transparent",},"--btn-secondary-outline-border-color":{"border-color":"var(--btn-secondary-background-color)",},"--separator-border-top-width":{"border-top-width":"1px",},"--separator-border-style":{"border-style":"solid",},"--separator-border-color":{"border-color":"rgb(33, 37, 41)",},"--separator-width":{width:"100%",},};return __exports;});;

/* /mass_mailing/static/src/builder/plugins/design_tab_plugin.js */
odoo.define('@mass_mailing/builder/plugins/design_tab_plugin',['@html_editor/plugin','@html_editor/utils/resource','@web/core/l10n/translation','@web/core/registry','@mass_mailing/builder/fontfamily_picker','@html_builder/core/utils'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"mass_mailing",...args);const{registry}=require("@web/core/registry");const{FontFamilyPicker}=require("@mass_mailing/builder/fontfamily_picker");const{BaseOptionComponent}=require("@html_builder/core/utils");const OPTION_POSITIONS=__exports.OPTION_POSITIONS={BODY:10,SETTINGS:20,HEADINGS:30,PARAGRAPH:40,BUTTON:50,LINK:60,SEPARATORS:70,};class DesignTabPlugin extends Plugin{static id="mass_mailing.DesignTab";static dependencies=["builderActions"];resources={builder_components:{FontFamilyPicker,},design_options:[withSequence(OPTION_POSITIONS.BODY,this.getDesignOptionBlock("design-body",{template:"mass_mailing.DesignBodyOption",title:_t("Body"),})),withSequence(OPTION_POSITIONS.HEADINGS,this.getDesignOptionBlock("design-headings",{template:"mass_mailing.DesignHeadingsOption",title:_t("Heading"),})),withSequence(OPTION_POSITIONS.PARAGRAPH,this.getDesignOptionBlock("design-paragraph",{template:"mass_mailing.DesignParagraphOption",title:_t("Paragraph"),})),withSequence(OPTION_POSITIONS.BUTTON,this.getDesignOptionBlock("design-button",{template:"mass_mailing.DesignButtonOption",title:_t("Button"),})),withSequence(OPTION_POSITIONS.LINK,this.getDesignOptionBlock("design-link",{template:"mass_mailing.DesignLinkOption",title:_t("Link"),})),withSequence(OPTION_POSITIONS.SEPARATORS,this.getDesignOptionBlock("design-separators",{template:"mass_mailing.DesignSeparatorOption",title:_t("Separator"),})),],};getDesignOptionBlock(id,options){const Option=class extends BaseOptionComponent{static selector="*";};Object.assign(Option,options);return{id:id,element:this.editable,hasOverlayOptions:false,headerMiddleButton:false,isClonable:false,isRemovable:false,options:[Option],optionsContainerTopButtons:[],snippetModel:{},};}}
registry.category("mass_mailing-plugins").add(DesignTabPlugin.id,DesignTabPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/dropzone_plugin.js */
odoo.define('@mass_mailing/builder/plugins/dropzone_plugin',['@html_editor/plugin','@html_editor/utils/dom_info','@web/core/registry'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{isPhrasingContent}=require("@html_editor/utils/dom_info");const{registry}=require("@web/core/registry");class DropzonePlugin extends Plugin{static id="mass_mailing.DropzonePlugin";resources={dropzone_selector:[{selector:".s_mail_blockquote, .s_mail_alert, .s_rating, .s_hr, .s_mail_text_highlight",dropNear:"p, h1, h2, h3, ul, ol, .row > div > img, .s_mail_blockquote, .s_mail_alert, .s_rating, .s_hr, .s_mail_text_highlight",dropIn:".content, nav",},{selector:"blockquote",dropNear:"section",dropIn:".o_mail_wrapper_td",},{selector:".col>td, .col>th",exclude:this.noOptionsSelector,dropNear:".col>td, .col>th",},{selector:".col_mv, td, th",exclude:this.noOptionsSelector,dropNear:".col_mv, td, th",},{selector:"tr:has(> .row), tr:has(> .col_mv)",exclude:this.noOptionsSelector,dropNear:"tr:has(> .row), tr:has(> .col_mv)",},{selector:".note-editable > div:not(.o_layout), .note-editable .oe_structure > *, .oe_snippet_body",exclude:this.noOptionsSelector,dropNear:"[data-oe-field='body_html']:not(:has(.o_layout)) > *, .oe_structure > *",dropIn:"[data-oe-field='body_html']:not(:has(.o_layout)), .oe_structure",},{selector:".row > div",exclude:".o_mail_no_options, .s_col_no_resize.row > div, .s_col_no_resize",dropNear:".row:not(.s_col_no_resize) > div",},],filter_for_sibling_dropzone_predicates:(el)=>isPhrasingContent(el),};get noOptionsSelector(){return".o_mail_no_options";}}
registry.category("mass_mailing-plugins").add(DropzonePlugin.id,DropzonePlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/empty_mailing_plugin.js */
odoo.define('@mass_mailing/builder/plugins/empty_mailing_plugin',['@html_editor/plugin','@html_editor/utils/resource','@web/core/registry'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{registry}=require("@web/core/registry");const EmptyMailingPlugin=__exports.EmptyMailingPlugin=class EmptyMailingPlugin extends Plugin{static id="EmptyMailing";static dependencies=["baseContainer","builderOptions","disableSnippets","history","selection",];resources={beforeinput_handlers:withSequence(1,this.ensureTextBlock.bind(this)),};ensureTextBlock(){const wrapperTd=this.editable.querySelector(".o_mail_wrapper_td");if(!wrapperTd){return;}
const{anchorNode}=this.dependencies.selection.getEditableSelection();if(anchorNode===wrapperTd&&!wrapperTd.firstChild){const textSnippet=this.config.snippetModel.getSnippetByName("snippet_structure","s_text_block").content.cloneNode(true);const baseContainer=this.dependencies.baseContainer.createBaseContainer();baseContainer.append(this.document.createElement("br"));const container=textSnippet.querySelector(".container");container.replaceChildren(baseContainer);wrapperTd.replaceChildren(textSnippet);this.dependencies.selection.setSelection({anchorNode:baseContainer,anchorOffset:0,});this.dependencies.history.addStep();this.dependencies.builderOptions.updateContainers(textSnippet);this.dependencies.disableSnippets.disableUndroppableSnippets();}}}
registry.category("mass_mailing-plugins").add(EmptyMailingPlugin.id,EmptyMailingPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/empty_not_editable_plugin.js */
odoo.define('@mass_mailing/builder/plugins/empty_not_editable_plugin',['@html_editor/plugin','@html_editor/utils/dom_info','@html_editor/utils/dom_traversal','@web/core/registry'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{isEmptyBlock}=require("@html_editor/utils/dom_info");const{closestElement}=require("@html_editor/utils/dom_traversal");const{registry}=require("@web/core/registry");const EmptyNotEditableElementsPlugin=__exports.EmptyNotEditableElementsPlugin=class EmptyNotEditableElementsPlugin extends Plugin{static id="mass_mailing.EmptyNotEditableElements";static dependencies=["selection"];resources={normalize_handlers:this.normalize.bind(this),};normalize(element){const potentiallyEmptyElements=element.querySelectorAll(".o_not_editable [data-oe-zws-empty-inline]");potentiallyEmptyElements.forEach((emptyElement)=>{const emptyNonEditableBlock=closestElement(emptyElement,".o_not_editable");if(isEmptyBlock(emptyNonEditableBlock)){emptyNonEditableBlock.remove();}});const selection=this.document.getSelection()??undefined;if(!this.dependencies.selection.isSelectionInEditable(selection)){this.dependencies.selection.resetSelection();}}}
registry.category("mass_mailing-plugins").add(EmptyNotEditableElementsPlugin.id,EmptyNotEditableElementsPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/icon_snippet_option_plugin.js */
odoo.define('@mass_mailing/builder/plugins/icon_snippet_option_plugin',['@html_editor/plugin','@html_editor/utils/dom','@web/core/registry'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{wrapInlinesInBlocks}=require("@html_editor/utils/dom");const{registry}=require("@web/core/registry");const MassMailingIconSnippetOptionPlugin=__exports.MassMailingIconSnippetOptionPlugin=class MassMailingIconSnippetOptionPlugin extends Plugin{static id="mass_mailing.iconSnippetOption";static dependencies=["media"];resources={on_snippet_dropped_handlers:this.onSnippetDropped.bind(this),};async onSnippetDropped({snippetEl}){if(!snippetEl.matches("p:has(> .s_icon)")){return;}
let iconInserted=false;await this.dependencies.media.openMediaDialog({activeTab:"ICONS",save:async(selectedIconEl)=>{iconInserted=true;snippetEl.insertAdjacentElement("afterend",selectedIconEl);snippetEl.remove();wrapInlinesInBlocks(selectedIconEl.parentElement);},});return!iconInserted;}}
registry.category("mass_mailing-plugins").add(MassMailingIconSnippetOptionPlugin.id,MassMailingIconSnippetOptionPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/image_snippet_option_plugin.js */
odoo.define('@mass_mailing/builder/plugins/image_snippet_option_plugin',['@html_editor/plugin','@web/core/registry'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");class MassMailingImageSnippetOptionPlugin extends Plugin{static id="mass_mailing.imageSnippetOption";static dependencies=["imageSnippetOption"];resources={on_snippet_dropped_handlers:this.onSnippetDropped.bind(this),};async onSnippetDropped({snippetEl,dragState}){if(!snippetEl.matches("p:has(> .s_image)")){return;}
const imageEl=snippetEl.querySelector(".s_image");return this.dependencies.imageSnippetOption.onSnippetDropped({snippetEl:imageEl,dragState,});}}
registry.category("mass_mailing-plugins").add(MassMailingImageSnippetOptionPlugin.id,MassMailingImageSnippetOptionPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/image_tool_options_plugin.js */
odoo.define('@mass_mailing/builder/plugins/image_tool_options_plugin',['@html_builder/core/utils','@html_builder/plugins/border_configurator_option','@html_builder/plugins/image/image_tool_option_plugin','@html_builder/utils/option_sequence','@html_editor/plugin','@html_editor/utils/dom_traversal','@html_editor/utils/resource','@mass_mailing/builder/options/image_tool_option','@web/core/registry','@web/core/utils/patch'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const{BorderConfigurator}=require("@html_builder/plugins/border_configurator_option");const{CropImageAction,ImageAndFaOption,}=require("@html_builder/plugins/image/image_tool_option_plugin");const{IMAGE_TOOL}=require("@html_builder/utils/option_sequence");const{Plugin}=require("@html_editor/plugin");const{closestElement}=require("@html_editor/utils/dom_traversal");const{withSequence}=require("@html_editor/utils/resource");const{MassMailingImageToolOption}=require("@mass_mailing/builder/options/image_tool_option");const{registry}=require("@web/core/registry");const{patch}=require("@web/core/utils/patch");const FontAwesomeOption=__exports.FontAwesomeOption=class FontAwesomeOption extends BaseOptionComponent{static template="mass_mailing.FontAwesomeOption";static selector="span.fa, i.fa";}
patch(ImageAndFaOption,{components:{...ImageAndFaOption.components,BorderConfigurator},});class ImageToolOptionPlugin extends Plugin{static id="mass_mailing.ImageToolOption";resources={patch_builder_options:[{target_name:"imageAndFaOption",target_element:"template",method:"replace",value:"mass_mailing.ImageAndFaOption",},{target_name:"imageAndFaOption",target_element:"exclude",method:"remove",},{target_name:"imageToolOption",target_element:"OptionComponent",method:"replace",value:MassMailingImageToolOption,},],builder_options:[withSequence(IMAGE_TOOL,FontAwesomeOption)],};}
patch(CropImageAction.prototype,{setup(){super.setup();this.withLoadingEffect=closestElement(this.editable,".o_mass_mailing_with_builder")!==null;},});registry.category("mass_mailing-plugins").add(ImageToolOptionPlugin.id,ImageToolOptionPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/layout_column_option_plugin.js */
odoo.define('@mass_mailing/builder/plugins/layout_column_option_plugin',['@html_builder/plugins/layout_column_option','@html_builder/utils/option_sequence','@html_editor/plugin','@html_editor/utils/resource','@web/core/registry','@html_editor/utils/dom_info','@html_editor/utils/dom_traversal'],function(require){'use strict';let __exports={};const{LayoutColumnOption}=require("@html_builder/plugins/layout_column_option");const{before,WIDTH}=require("@html_builder/utils/option_sequence");const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{registry}=require("@web/core/registry");const{isEmptyBlock}=require("@html_editor/utils/dom_info");const{closestElement}=require("@html_editor/utils/dom_traversal");const MassMailingLayoutColumnOption=__exports.MassMailingLayoutColumnOption=class MassMailingLayoutColumnOption extends LayoutColumnOption{static selector=".o_mail_snippet_general";static exclude=".s_reviews_wall, .s_mail_alert";static applyTo=":scope > *:has(> .row:not(.s_nb_column_fixed)), * > .s_allow_columns";}
class MassMailingLayoutColumnPlugin extends Plugin{static id="mass_mailing.LayoutColumnPlugin";resources={mark_color_level_selector_params:[{selector:".o_mail_snippet_general"}],builder_options:[withSequence(before(WIDTH),MassMailingLayoutColumnOption)],normalize_handlers:this.normalize.bind(this),};normalize(element){const emptyRowCandidates=element.querySelectorAll(".container > .row:not(:has(> *))");const emptyContainerCandidates=new Set();const emptySectionCandidates=new Set();for(const emptyRowCandidate of emptyRowCandidates){if(isEmptyBlock(emptyRowCandidate)){emptyContainerCandidates.add(emptyRowCandidate.parentElement);emptyRowCandidate.remove();}}
for(const emptyContainerCandidate of emptyContainerCandidates){if(isEmptyBlock(emptyContainerCandidate)){const section=closestElement(emptyContainerCandidate,"section");if(section){emptySectionCandidates.add(section);}
emptyContainerCandidate.remove();}}
for(const emptySectionCandidate of emptySectionCandidates){if(isEmptyBlock(emptySectionCandidate)){emptySectionCandidate.remove();}}}}
registry.category("mass_mailing-plugins").add(MassMailingLayoutColumnPlugin.id,MassMailingLayoutColumnPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/mail_blockquote_plugin.js */
odoo.define('@mass_mailing/builder/plugins/mail_blockquote_plugin',['@html_editor/plugin','@web/core/registry'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");class AlertOptionPlugin extends Plugin{static id="mass_mailing.MailBlockquotePlugin";resources={clean_for_save_handlers:this.cleanForSave.bind(this),};cleanForSave({root}){for(const quote of root.querySelectorAll("blockquote")){quote.dataset.oMailQuoteNode="1";quote.dataset.oMailQuote="1";}}}
registry.category("mass_mailing-plugins").add(AlertOptionPlugin.id,AlertOptionPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/masonry_block_option_plugin.js */
odoo.define('@mass_mailing/builder/plugins/masonry_block_option_plugin',['@html_builder/core/builder_action','@html_builder/core/utils','@html_editor/plugin','@web/core/registry','@web/core/utils/render'],function(require){'use strict';let __exports={};const{BuilderAction}=require("@html_builder/core/builder_action");const{BaseOptionComponent}=require("@html_builder/core/utils");const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{renderToElement}=require("@web/core/utils/render");class MasonryBlockTemplateOptionPlugin extends Plugin{static id="mass_mailing.MasonryBlock";resources={builder_options:[MasonryBlockTemplateOption],builder_actions:{ChangeMasonryTemplate,},};}
class MasonryBlockTemplateOption extends BaseOptionComponent{static template="mass_mailing.MasonryBlockTemplateOption";static selector=".s_masonry_block";static groups=["base.group_user"];}
class ChangeMasonryTemplate extends BuilderAction{static id="changeMasonryTemplate";apply({editingElement,value}){editingElement.dataset.templateName=value;const templateName=`mass_mailing.s_masonry_block_${value}`;const newTemplate=renderToElement(templateName);newTemplate.dataset.templateName=value;const target=editingElement.querySelector(".container");target.replaceChildren(newTemplate);}
isApplied({editingElement,value}){return editingElement.dataset.templateName===value;}}
registry.category("mass_mailing-plugins").add(MasonryBlockTemplateOptionPlugin.id,MasonryBlockTemplateOptionPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/mass_mailing_setup_plugin.js */
odoo.define('@mass_mailing/builder/plugins/mass_mailing_setup_plugin',['@html_editor/plugin','@web/core/l10n/translation','@web/core/registry'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"mass_mailing",...args);const{registry}=require("@web/core/registry");const MassMailingSetupPlugin=__exports.MassMailingSetupPlugin=class MassMailingSetupPlugin extends Plugin{static id="mass_mailing_setup_plugin";resources={o_editable_selectors:".o_mail_wrapper_td",snippet_preview_dialog_bundles:["mass_mailing.assets_iframe_style","mass_mailing.iframe_add_dialog",],clean_for_save_handlers:this.cleanForSave.bind(this),powerbox_blacklist_selectors:".o_mail_wrapper_td",};setup(){const wrapperTd=this.editable.querySelector(".o_mail_wrapper_td");wrapperTd?.classList.add("oe_empty");wrapperTd?.setAttribute("data-editor-message-default",true);wrapperTd?.setAttribute("data-editor-message",_t("DRAG BUILDING BLOCKS HERE"));}
cleanForSave({root}){const wrapperTd=root.querySelector(".o_mail_wrapper_td.oe_empty");wrapperTd?.classList.remove("oe_empty");wrapperTd?.removeAttribute("data-editor-message-default");wrapperTd?.removeAttribute("data-editor-message");}}
registry.category("mass_mailing-plugins").add(MassMailingSetupPlugin.id,MassMailingSetupPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/move_plugin.js */
odoo.define('@mass_mailing/builder/plugins/move_plugin',['@html_editor/plugin','@web/core/registry'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");class MovePlugin extends Plugin{static id="mass_mailing.MovePlugin";static dependencies=["move"];resources={is_movable_selector:[{selector:".o_mail_snippet_general",direction:"vertical",},{selector:".row:not(.s_col_no_resize) > div",direction:"horizontal",exclude:".s_showcase .row > div",},],};}
registry.category("mass_mailing-plugins").add(MovePlugin.id,MovePlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/operation_plugin.js */
odoo.define('@mass_mailing/builder/plugins/operation_plugin',['@html_builder/core/operation_plugin','@web/core/registry'],function(require){'use strict';let __exports={};const{OperationPlugin}=require("@html_builder/core/operation_plugin");const{registry}=require("@web/core/registry");const MassMailingOperationPlugin=__exports.MassMailingOperationPlugin=class MassMailingOperationPlugin extends OperationPlugin{static shared=[...OperationPlugin.shared,"getUnlockedDef"];async next(){return super.next(...arguments).catch((error)=>{if(!this.isDestroyed){throw error;}});}
getUnlockedDef(){return this.operation.mutex.getUnlockedDef();}}
registry.category("mass_mailing-plugins").add(MassMailingOperationPlugin.id,MassMailingOperationPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/padding_option_plugin.js */
odoo.define('@mass_mailing/builder/plugins/padding_option_plugin',['@html_builder/core/utils','@html_builder/utils/option_sequence','@html_editor/plugin','@html_editor/utils/resource','@web/core/registry'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const{after,VERTICAL_ALIGNMENT}=require("@html_builder/utils/option_sequence");const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{registry}=require("@web/core/registry");const HorizontalPaddingOption=__exports.HorizontalPaddingOption=class HorizontalPaddingOption extends BaseOptionComponent{static template="mass_mailing.HorizontalPaddingOption";static selector="[class*='col-md-'], .s_discount2, .s_text_block, .s_media_list, .s_picture, .s_rating, .s_title, .o_mail_block_footer_social, .s_header_logo, .s_header_social";static exclude=".s_col_no_resize.row > div, .s_col_no_resize, img";}
const VerticalPaddingOption=__exports.VerticalPaddingOption=class VerticalPaddingOption extends BaseOptionComponent{static template="mass_mailing.VerticalPaddingOption";static selector=".o_mail_block_footer_social, .s_header_logo, .s_header_social";static exclude=".s_col_no_resize.row > div, .s_col_no_resize";}
class PaddingOptionPlugin extends Plugin{static id="horizontalPaddingOption";selector=HorizontalPaddingOption.selector;resources={mark_color_level_selector_params:[{selector:HorizontalPaddingOption.selector}],builder_options:[withSequence(after(VERTICAL_ALIGNMENT),HorizontalPaddingOption),withSequence(after(VERTICAL_ALIGNMENT),VerticalPaddingOption),],};}
registry.category("mass_mailing-plugins").add(PaddingOptionPlugin.id,PaddingOptionPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/pricelist_boxed_option_plugin.js */
odoo.define('@mass_mailing/builder/plugins/pricelist_boxed_option_plugin',['@html_builder/plugins/add_product_option','@html_editor/plugin','@html_editor/utils/resource','@html_builder/utils/option_sequence','@web/core/registry'],function(require){'use strict';let __exports={};const{BaseAddProductOption}=require("@html_builder/plugins/add_product_option");const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{BEGIN}=require("@html_builder/utils/option_sequence");const{registry}=require("@web/core/registry");const MassMailingAddProductOption=__exports.MassMailingAddProductOption=class MassMailingAddProductOption extends BaseAddProductOption{static selector=".s_pricelist_boxed_section:has(> .container)";productSelector=".container";}
const PricelistBoxedOptionPlugin=__exports.PricelistBoxedOptionPlugin=class PricelistBoxedOptionPlugin extends Plugin{static id="mass_mailing.PricelistBoxedOptionPlugin";resources={builder_options:[withSequence(BEGIN,MassMailingAddProductOption)],};}
registry.category("mass_mailing-plugins").add(PricelistBoxedOptionPlugin.id,PricelistBoxedOptionPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/reviews_wall_option_plugin.js */
odoo.define('@mass_mailing/builder/plugins/reviews_wall_option_plugin',['@html_builder/core/utils','@html_builder/plugins/border_configurator_option','@html_builder/plugins/layout_column_option','@html_editor/plugin','@web/core/registry'],function(require){'use strict';let __exports={};const{BaseOptionComponent}=require("@html_builder/core/utils");const{BorderConfigurator}=require("@html_builder/plugins/border_configurator_option");const{LayoutColumnOption}=require("@html_builder/plugins/layout_column_option");const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const CustomerTestimonialsBlockquote=__exports.CustomerTestimonialsBlockquote=class CustomerTestimonialsBlockquote extends BaseOptionComponent{static template="mass_mailing.CustomerTestimonialsBlockquote";static selector=".s_reviews_wall .s_mail_blockquote";static components={BorderConfigurator};}
const MassMailingLayoutColumnOption=__exports.MassMailingLayoutColumnOption=class MassMailingLayoutColumnOption extends LayoutColumnOption{static selector=".s_reviews_wall .container";static applyTo=":scope > .row:has(> .s_mail_blockquote), :scope > .row > .s_allow_columns";}
class ReviewsWallOptionPlugin extends Plugin{static id="mass_mailing.ReviewsWallOptionPlugin";resources={builder_options:[CustomerTestimonialsBlockquote,MassMailingLayoutColumnOption],};}
registry.category("mass_mailing-plugins").add(ReviewsWallOptionPlugin.id,ReviewsWallOptionPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/schedule_option_plugin.js */
odoo.define('@mass_mailing/builder/plugins/schedule_option_plugin',['@html_builder/plugins/add_product_option','@html_editor/plugin','@html_editor/utils/resource','@html_builder/utils/option_sequence','@web/core/registry','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{BaseAddProductOption}=require("@html_builder/plugins/add_product_option");const{Plugin}=require("@html_editor/plugin");const{withSequence}=require("@html_editor/utils/resource");const{BEGIN}=require("@html_builder/utils/option_sequence");const{registry}=require("@web/core/registry");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"mass_mailing",...args);const MassMailingScheduleAddProductOption=__exports.MassMailingScheduleAddProductOption=class MassMailingScheduleAddProductOption extends BaseAddProductOption{static selector=".s_schedule:has(table)";productSelector="tr";buttonLabel=_t("Add Activity");}
const ScheduleOptionPlugin=__exports.ScheduleOptionPlugin=class ScheduleOptionPlugin extends Plugin{static id="mass_mailing.ScheduleOptionPlugin";resources={builder_options:[withSequence(BEGIN,MassMailingScheduleAddProductOption)],};}
registry.category("mass_mailing-plugins").add(ScheduleOptionPlugin.id,ScheduleOptionPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/signature_snippet_plugin.js */
odoo.define('@mass_mailing/builder/plugins/signature_snippet_plugin',['@web/core/registry','@web/core/user','@html_editor/plugin','@web/core/signature/signature_dialog'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{user}=require("@web/core/user");const{Plugin}=require("@html_editor/plugin");const{SignatureDialog}=require("@web/core/signature/signature_dialog");const MassMailingSignatureSnippetPlugin=__exports.MassMailingSignatureSnippetPlugin=class MassMailingSignatureSnippetPlugin extends Plugin{static id="mass_mailing.signatureSnippet";resources={on_snippet_dropped_handlers:this.onSnippetDropped.bind(this),};async onSnippetDropped({snippetEl}){const images=snippetEl.querySelectorAll(".o_mail_signature_image");if(!images.length){return;}
this.services.dialog.add(SignatureDialog,{defaultName:user.name,nameAndSignatureProps:{displaySignatureRatio:3,},uploadSignature:(signature)=>{for(const image of images){image.src=signature.signatureImage;}},},{onClose:()=>{snippetEl.remove();},});}}
registry.category("mass_mailing-plugins").add(MassMailingSignatureSnippetPlugin.id,MassMailingSignatureSnippetPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/snippet_visibility_option_plugin.js */
odoo.define('@mass_mailing/builder/plugins/snippet_visibility_option_plugin',['@html_editor/plugin','@web/core/registry','@mass_mailing/builder/options/snippet_visibility_option','@html_editor/utils/resource','@web/core/utils/reactive','@html_builder/core/core_builder_action_plugin'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const{SnippetVisibilityOption}=require("@mass_mailing/builder/options/snippet_visibility_option");const{withSequence}=require("@html_editor/utils/resource");const{effect}=require("@web/core/utils/reactive");const{DataAttributeAction}=require("@html_builder/core/core_builder_action_plugin");class DataAttributeChangeAction extends DataAttributeAction{static id="dataAttributeChangeAction";apply(context){super.apply(context);this.config.onChange?.(context);}
isApplied({editingElement,params:{mainParam:attributeName}={},value}){if(value){return Boolean(editingElement.dataset[attributeName])===Boolean(value);}else{return super.isApplied(...arguments);}}}
class SnippetVisibilityPlugin extends Plugin{static id="mass_mailing.SnippetVisibility";static shared=["getModel"];resources={builder_actions:{DataAttributeChangeAction},builder_options:[withSequence(Infinity,SnippetVisibilityOption)],system_attributes:"data-filter-domain",};setup(){this.mailingModelId=this.config.record.data.mailing_model_id.id;effect((record)=>{if(this.isDestroyed){return;}
if(record.data.mailing_model_id.id!==this.mailingModelId){this.mailingModelId=record.data.mailing_model_id.id;this.resetFilterDomains();}},[this.config.record]);}
getModel(){return this.config.record.data.mailing_model_real;}
resetFilterDomains(){const filteredElements=this.editable.querySelectorAll("[data-filter-domain]");filteredElements.forEach((el)=>el.removeAttribute("data-filter-domain"));this.config.onChange?.({isPreviewing:false});}}
registry.category("mass_mailing-plugins").add(SnippetVisibilityPlugin.id,SnippetVisibilityPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/version_control_plugin.js */
odoo.define('@mass_mailing/builder/plugins/version_control_plugin',['@html_editor/plugin','@web/core/registry'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");const VersionControlPlugin=__exports.VersionControlPlugin=class VersionControlPlugin extends Plugin{static id="versionControl";static dependencies=["builderOptions"];accessPerOutdatedEl=new WeakMap();static shared=["hasAccessToOutdatedEl","giveAccessToOutdatedEl","replaceWithNewVersion"];hasAccessToOutdatedEl(el){if(!el.dataset.snippet){return true;}
if(this.accessPerOutdatedEl.has(el)){return this.accessPerOutdatedEl.get(el);}
const snippetKey=el.dataset.snippet;const snippet=this.config.snippetModel.getOriginalSnippet(snippetKey);let isUpToDate=true;if(snippet){const{vxml:originalVxml}=snippet.content.dataset;const{vxml:elVxml}=el.dataset;isUpToDate=originalVxml===elVxml;}
this.accessPerOutdatedEl.set(el,isUpToDate);return isUpToDate;}
giveAccessToOutdatedEl(el){this.accessPerOutdatedEl.set(el,true);}
replaceWithNewVersion(el){const snippetKey=el.dataset.snippet;const snippet=this.config.snippetModel.getOriginalSnippet(snippetKey);const cloneEl=snippet.content.cloneNode(true);el.after(cloneEl);el.remove();this.dependencies.builderOptions.setNextTarget(cloneEl);}}
registry.category("mass_mailing-plugins").add(VersionControlPlugin.id,VersionControlPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/vertical_alignment_option_plugin.js */
odoo.define('@mass_mailing/builder/plugins/vertical_alignment_option_plugin',['@html_editor/plugin','@web/core/registry'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");class VerticalAlignmentOptionPlugin extends Plugin{static id="mass_mailing.VerticalAlignmentOption";resources={patch_builder_options:[{target_name:"verticalAlignmentOption",target_element:"selector",method:"add",value:".s_mail_block_event",},],};}
registry.category("mass_mailing-plugins").add(VerticalAlignmentOptionPlugin.id,VerticalAlignmentOptionPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/plugins/width_option_plugin.js */
odoo.define('@mass_mailing/builder/plugins/width_option_plugin',['@html_editor/plugin','@web/core/registry'],function(require){'use strict';let __exports={};const{Plugin}=require("@html_editor/plugin");const{registry}=require("@web/core/registry");class WidthOptionPlugin extends Plugin{static id="mass_mailing.WidthOption";resources={patch_builder_options:[{target_name:"widthOption",target_element:"selector",method:"add",value:".s_mail_alert .s_alert, .s_mail_blockquote, .s_mail_text_highlight",},],};}
registry.category("mass_mailing-plugins").add(WidthOptionPlugin.id,WidthOptionPlugin);return __exports;});;

/* /mass_mailing/static/src/builder/tabs/design_tab.js */
odoo.define('@mass_mailing/builder/tabs/design_tab',['@odoo/owl','@html_builder/utils/utils','@html_builder/sidebar/option_container'],function(require){'use strict';let __exports={};const{Component,useState}=require("@odoo/owl");const{useOptionsSubEnv}=require("@html_builder/utils/utils");const{OptionsContainer}=require("@html_builder/sidebar/option_container");const DesignTab=__exports.DesignTab=class DesignTab extends Component{static template="mass_mailing.DesignTab";static components={OptionsContainer};static props={colorPresetToShow:{optional:true},};setup(){useOptionsSubEnv(()=>[this.env.editor.document.body]);this.state=useState({fontsData:{},});this.optionsContainers=this.env.editor.resources["design_options"];}}
return __exports;});

                    /*******************************************
                    *  Templates                               *
                    *******************************************/

                    odoo.define("mass_mailing.assets_builder.bundle.xml", ["@web/core/templates"], function(require) {
                        "use strict";
                        const { checkPrimaryTemplateParents, registerTemplate, registerTemplateExtension } = require("@web/core/templates");
                        /* mass_mailing.assets_builder */
                        registerTemplate("html_builder.Builder", `/html_builder/static/src/builder.xml`, `<t t-name="html_builder.Builder" xml:space="preserve">
    <div class="h-100 o-snippets-menu d-flex flex-column" t-ref="builder_sidebar">
        <div class="o-snippets-top-actions d-flex justify-content-between flex-shrink-0 p-2">
            <div class="d-flex gap-1">
                <button type="button" t-on-click="() =&gt; this.undo()" class="o-hb-btn btn fa fa-undo" t-att-disabled="!state.canUndo"/>
                <button type="button" t-on-click="() =&gt; this.redo()" class="o-hb-btn btn fa fa-repeat" t-att-disabled="!state.canRedo"/>
            </div>
            <div class="d-flex gap-1">
                <button t-on-click="onMobilePreviewClick" type="button" class="o-hb-btn btn btn-success-color-active d-flex align-items-center" t-att-class="{ active: props.isMobile }" data-action="mobile" title="Mobile Preview" accesskey="m" style="--btn-font-size: 20px"><span class="fa fa-mobile" role="img"/></button>
                <t t-if="props.slots?.extraActions" t-slot="extraActions"/>
            </div>
        </div>
        <div t-if="!props.config.isTranslationMode" class="o-snippets-tabs position-relative">
            <div class="o-snippets-tabs-highlighter position-absolute start-50 h-100 pe-none" t-att-class="{                     'o-highlight-blocks': state.activeTab === 'blocks',                     'o-highlight-theme': state.activeTab === 'theme',                 }"/>
            <ul class="nav nav-underline" role="tablist">
                <li class="nav-item" role="presentation">
                    <button id="blocks-tab" data-name="blocks" data-hotkey="1" class="o-hb-tab nav-link position-relative w-100" t-att-class="{'active cursor-default': state.activeTab === 'blocks'}" t-on-click="() =&gt; this.onTabClick('blocks')" t-att-disabled="displayOnlyCustomizeTab" role="tab" t-att-aria-selected="state.activeTab === 'blocks' ? 'true' : 'false'">
                        <i class="fa fa-plus me-2" role="none"/>Blocks
                    </button>
                </li>
                <li class="nav-item" role="presentation">
                    <button id="customize-tab" data-name="customize" class="o-hb-tab nav-link position-relative w-100" t-att-class="{'active cursor-default': state.activeTab === 'customize'}" t-on-click="() =&gt; this.onTabClick('customize')" role="tab" t-att-aria-selected="state.activeTab === 'customize' ? 'true' : 'false'">
                        <i class="fa fa-pencil me-2" role="none"/>Style
                    </button>
                </li>
                <li class="nav-item" role="presentation">
                    <button id="theme-tab" data-name="theme" data-hotkey="2" t-if="ThemeTab" class="o-hb-tab nav-link position-relative w-100" t-att-class="{'active cursor-default': state.activeTab === 'theme'}" t-on-click="() =&gt; this.onTabClick('theme')" t-att-disabled="displayOnlyCustomizeTab" role="tab" t-att-aria-selected="state.activeTab === 'theme' ? 'true' : 'false'">
                        <i class="fa fa-cog me-2" role="none"/><t t-out="props.themeTabDisplayName"/>
                    </button>
                </li>
            </ul>
        </div>
        <div class="o-tab-content overflow-y-auto overflow-x-hidden flex-grow-1">
            <t t-if="state.activeTab === 'blocks'">
                <BlockTab snippetsName="props.snippetsName"/>
            </t>
            <t t-if="state.activeTab === 'customize'">
                <t t-if="props.config.isTranslationMode" t-component="CustomizeTranslationTab"/>
                <CustomizeTab t-else="" currentOptionsContainers="state.currentOptionsContainers" snippetModel="snippetModel"/>
            </t>
            <t t-if="state.activeTab === 'theme'">
                <t t-component="ThemeTab" colorPresetToShow="colorPresetToShow"/>
            </t>
        </div>
        <div class="o_we_lower_panel mt-auto flex-grow-0 flex-shrink-0">
            <t t-foreach="lowerPanelEntries()" t-as="entry" t-key="entry_index">
                <t t-component="entry.Component" t-props="entry.props"/>
            </t>
        </div>
    </div>
</t>

`);
registerTemplate("html_builder.AnchorDialog", `/html_builder/static/src/core/anchor/anchor_dialog.xml`, `<t t-name="html_builder.AnchorDialog" xml:space="preserve">
    <Dialog title="this.title" size="'lg'">
        <div class="mb-3 row">
            <label class="col-form-label col-md-3" for="anchorName">Choose an anchor name</label>
            <div class="col-md-9">
                <input t-ref="anchor-input" type="text" class="form-control" id="anchorName" t-att-class="{'is-invalid': !state.isValid}" t-attf-value="#{props.currentAnchorName}" placeholder="Anchor name"/>
                <div class="invalid-feedback">
                    <p t-att-class="{'d-none': state.isValid}">The chosen name already exists</p>
                </div>
            </div>
        </div>
        <t t-set-slot="footer">
            <button class="btn btn-primary" t-on-click="onConfirmClick">Save &amp; Copy</button>
            <button class="btn btn-secondary" t-on-click="props.close">Discard</button>
            <button class="btn btn-link ms-auto" t-on-click="onRemoveClick">
                <i class="fa fa-icon fa-trash"/>
                Remove
            </button>
        </t>
    </Dialog>
</t>

`);
registerTemplate("html_builder.BuilderOverlay", `/html_builder/static/src/core/builder_overlay/builder_overlay.xml`, `<t t-name="html_builder.BuilderOverlay" xml:space="preserve">
    <div class="oe_overlay o_handlers_idle">
        <div class="o_handles">

            <div class="o_handle o_column_handle o_side o_side_y n readonly">
                <span class="o_handle_indicator"/>
            </div>
            <div class="o_handle o_column_handle o_side o_side_y s readonly">
                <span class="o_handle_indicator"/>
            </div>
            <div class="o_handle o_column_handle o_side o_side_x e readonly">
                <span class="o_handle_indicator"/>
            </div>
            <div class="o_handle o_column_handle o_side o_side_x w readonly">
                <span class="o_handle_indicator"/>
            </div>


             <div class="o_handle o_grid_handle o_side o_side_y n d-none">
                <span class="o_handle_indicator"/>
            </div>
             <div class="o_handle o_grid_handle o_side o_side_x e d-none">
                <span class="o_handle_indicator"/>
            </div>
             <div class="o_handle o_grid_handle o_side o_side_x w d-none">
                <span class="o_handle_indicator"/>
            </div>
             <div class="o_handle o_grid_handle o_side o_side_y s d-none">
                <span class="o_handle_indicator"/>
            </div>
             <div class="o_handle o_grid_handle o_corner_handle ne d-none">
                <span class="o_handle_indicator"/>
            </div>
             <div class="o_handle o_grid_handle o_corner_handle nw d-none">
                <span class="o_handle_indicator"/>
            </div>
             <div class="o_handle o_grid_handle o_corner_handle se d-none">
                <span class="o_handle_indicator"/>
            </div>
             <div class="o_handle o_grid_handle o_corner_handle sw d-none">
                <span class="o_handle_indicator"/>
            </div>
        </div>
    </div>
</t>

`);
registerTemplate("html_builder.BasicMany2Many", `/html_builder/static/src/core/building_blocks/basic_many2many.xml`, `<t t-name="html_builder.BasicMany2Many" xml:space="preserve">
    <div class="d-flex flex-column">
        <table class="o-hb-m2m-table">
            <tr t-foreach="props.selection" t-as="entry" t-key="entry.id">
                <td>
                    <input type="text" class="o-hb-input-base" disabled="" t-att-data-name="entry.display_name" t-att-value="entry.display_name"/>
                </td>
                <td>
                    <button class="mt-0 border-0 p-0 bg-transparent text-danger fa fa-fw fa-minus" t-on-click="() =&gt; this.unselect(entry.id)"/>
                </td>
            </tr>
        </table>
        <SelectMany2X model="props.model" fields="props.fields" limit="props.limit" domain="props.domain" selected="props.selection" select="select.bind(this)" create="props.create"/>
    </div>
</t>

`);
registerTemplate("html_builder.BuilderButton", `/html_builder/static/src/core/building_blocks/builder_button.xml`, `<t t-name="html_builder.BuilderButton" xml:space="preserve">
    <BuilderComponent>
        <button type="button" class="o-hb-btn btn" t-att-style="this.props.style" t-att-data-action-id="info.actionId" t-att-data-action-param="info.actionParam" t-att-data-action-value="info.actionValue" t-att-data-class-action="info.classAction" t-att-data-style-action="info.styleAction" t-att-data-style-action-value="info.styleActionValue" t-att-data-attribute-action="info.attributeAction" t-att-data-attribute-action-value="info.attributeActionValue" t-att-class="className" t-att-title="props.title" t-att-aria-label="props.title" t-on-click="() =&gt; this.onClick()" t-on-pointerenter="() =&gt; this.onPointerEnter(props.id)" t-on-pointerleave="() =&gt; this.onPointerLeave(props.id)">
            <Img t-if="props.iconImg" src="props.iconImg" attrs="{alt:props.iconImgAlt}"/>
            <i t-if="props.icon" t-att-class="iconClassName" role="img"/>
            <t t-if="props.label" t-out="props.label"/>
            <t t-slot="default"/>
        </button>
    </BuilderComponent>
</t>

`);
registerTemplate("html_builder.BuilderButtonGroup", `/html_builder/static/src/core/building_blocks/builder_button_group.xml`, `<t t-name="html_builder.BuilderButtonGroup" xml:space="preserve">
    <BuilderComponent>
        <div class="o-hb-button-group btn-group" t-ref="root">
            <t t-slot="default"/>
        </div>
    </BuilderComponent>
</t>

`);
registerTemplate("html_builder.BuilderCheckbox", `/html_builder/static/src/core/building_blocks/builder_checkbox.xml`, `<t t-name="html_builder.BuilderCheckbox" xml:space="preserve">
    <BuilderComponent>
        <div t-att-data-action-id="info.actionId" t-att-data-action-param="info.actionParam" t-att-data-action-value="info.actionValue" t-att-data-class-action="info.classAction" t-att-data-style-action="info.styleAction" t-att-data-style-action-value="info.styleActionValue" t-att-data-attribute-action="info.attributeAction" t-att-data-attribute-action-value="info.attributeActionValue" t-on-pointerenter="() =&gt; this.onPointerEnter(props.id)" t-on-pointerleave="() =&gt; this.onPointerLeave(props.id)">
            <CheckBox className="getClassName()" onChange="onChange" value="state.isActive"/>
        </div>
    </BuilderComponent>
</t>

`);
registerTemplate("html_builder.BuilderColorPicker", `/html_builder/static/src/core/building_blocks/builder_colorpicker.xml`, `<t t-name="html_builder.BuilderColorPicker" xml:space="preserve">
    <BuilderComponent>
        <button t-att-title="props.title" class="o_we_color_preview" t-ref="colorButton" t-att-style="this.getSelectedColorStyle()"/>
    </BuilderComponent>
</t>

`);
registerTemplate("html_builder.BuilderDateTimePicker", `/html_builder/static/src/core/building_blocks/builder_datetimepicker.xml`, `<t t-name="html_builder.BuilderDateTimePicker" xml:space="preserve">
    <BuilderComponent>
        <div t-ref="root" class="w-100">
            <BuilderTextInputBase t-props="textInputBaseProps" commit="commit" preview="preview" onFocus.bind="onFocus" value="displayValue"/>
        </div>
    </BuilderComponent>
</t>

`);
registerTemplate("html_builder.BuilderFontFamilyPicker", `/html_builder/static/src/core/building_blocks/builder_fontfamilypicker.xml`, `<t t-name="html_builder.BuilderFontFamilyPicker" xml:space="preserve">
    <BuilderSelect className="'o-hidden-font-family-picker'">
        <t t-foreach="fonts" t-as="font" t-key="font_index">
            <BuilderSelectItem t-props="forwardProps(font)">
                <div class="d-flex justify-content-between align-items-center">
                    <span t-attf-style="font-family: {{font.styleFontFamily}};" class="text-truncate d-flex align-items-center">
                        <i t-if="font.type === 'cloud'" role="button" class="me-2 fa fa-cloud" title="This font is hosted and served to your visitors by Google servers"/>
                        <t t-out="font.string"/>
                    </span>
                    <div class="text-end o_select_item_only ms-2">
                        <t t-if="font.indexForType &gt;= 0">
                            <t t-set="delete_font_title">Delete this font</t>
                            <i role="button" t-on-click.prevent.stop="() =&gt; this.onDeleteFontClick(font)" class="fa fa-trash-o o_we_delete_font_btn" t-att-aria-label="delete_font_title" t-att-title="delete_font_title"/>
                        </t>
                    </div>
                </div>
            </BuilderSelectItem>
        </t>
        <div class="d-flex flex-column cursor-pointer o-dropdown-item dropdown-item o-navigable o_we_add_font_btn" role="menuitem" tabindex="0" t-on-click.stop="() =&gt; this.onAddFontClick()">
            Add a Custom Font
        </div>
    </BuilderSelect>
</t>

`);
registerTemplate("html_builder.BuilderList", `/html_builder/static/src/core/building_blocks/builder_list.xml`, `<t t-name="html_builder.BuilderList" xml:space="preserve">
    <BuilderComponent>
        <div class="w-100 p-2 py-0">
            <t t-if="state.value?.length &gt; 2">
                <div class="o_we_table_wrapper">
                    <table t-ref="table">
                        <t t-set="items" t-value="formatRawValue(state.value)"/>
                        <t t-foreach="items" t-as="item" t-key="item._id">
                            <tr class="o_row_draggable" t-att-data-id="item._id">
                                <td t-if="props.sortable" class="o_handle_cell w-0">
                                    <button type="button" class="btn">
                                        <i class="fa fa-fw fa-arrows" aria-hidden="true"/>
                                        <span class="visually-hidden">Drag and sort field</span>
                                    </button>
                                </td>
                                <t t-foreach="Object.entries(props.itemShape).filter(([key,_]) =&gt; !props.hiddenProperties.includes(key))" t-as="entry" t-key="entry[0]">
                                    <td t-att-class="props.columnWidth[entry[0]] || ''">
                                        <t t-if="entry[1].endsWith('boolean')">
                                            <div class="o-hb-checkbox o-checkbox form-check o_field_boolean o_boolean_toggle form-switch">
                                                <input type="checkbox" class="form-check-input" t-att-name="entry[0]" t-att-checked="item[entry[0]]" t-att-data-id="item._id" t-on-click="onChange"/>
                                            </div>
                                        </t>
                                        <t t-else="">
                                            <input class="o-hb-input-base" t-att-type="entry[1]" t-att-name="entry[0]" t-att-value="item[entry[0]]" t-att-data-id="item._id" t-att-disabled="props.isInputDisabled" t-on-input="onInput" t-on-change="onChange"/>
                                        </t>
                                    </td>
                                </t>
                                <td>
                                    <button type="button" class="btn text-danger builder_list_remove_item" t-if="!(this.props.forbidLastItemRemoval and (items.length === 1))" t-on-click="() =&gt; this.deleteItem(item._id)">
                                        <i class="fa fa-fw fa-minus" aria-hidden="true"/>
                                        <span class="visually-hidden">Delete item</span>
                                    </button>
                                </td>
                            </tr>
                        </t>
                    </table>
                </div>
            </t>
            <div class="o-hb-select-wrapper" t-if="this.allRecords and this.allRecords.length">
                <t t-set="availableRecords" t-value="this.getAvailableRecords()"/>
                <div class="mt-1 ms-auto">
                    <Dropdown state="this.dropdown" menuClass="'o-hb-select-dropdown mt-1'">
                        <button class="bl-dropdown-toggle o-hb-select-toggle o-hb-btn btn btn-success text-start o-dropdown-caret w-100 mx-auto px-3" t-att-disabled="!availableRecords.length">
                            <t t-set="noAvailableRecordLabel">You don't have any record to add</t>
                            <span class="" t-att-title="!availableRecords.length ? noAvailableRecordLabel : ''" t-att-style="!availableRecords.length ? 'pointer-events: auto; display: inline-block;' : ''">
                                <t t-out="props.addItemTitle"/>
                            </span>
                        </button>
                        <t t-set-slot="content">
                            <t t-foreach="availableRecords" t-as="item" t-key="item.id">
                                <t t-foreach="Object.entries(props.itemShape).filter(([key, value]) =&gt; !value.endsWith('boolean'))" t-as="entry" t-key="entry[0]">
                                    <div class="o-hb-select-dropdown-item d-flex flex-column cursor-pointer o-dropdown-item dropdown-item o-navigable w-100 mx-auto" style="max-height: 50vh;" t-att-type="entry[1]" t-att-name="entry[0]" t-att-data-id="item.id" t-on-click="addItem">
                                        <t t-out="item[entry[0]]"/>
                                    </div>
                                </t>
                            </t>
                        </t>
                    </Dropdown>
                </div>
            </div>
            <t t-else="">
                <div class="text-end mt-1">
                    <button type="button" class="builder_list_add_item o-hb-btn btn btn-success px-3" t-on-click="addItem">
                        <t t-out="props.addItemTitle"/>
                    </button>
                </div>
            </t>
        </div>
    </BuilderComponent>
</t>

`);
registerTemplate("html_builder.BuilderMany2Many", `/html_builder/static/src/core/building_blocks/builder_many2many.xml`, `<t t-name="html_builder.BuilderMany2Many" xml:space="preserve">
    <BuilderComponent>
	    <BasicMany2Many model="state.searchModel" limit="props.limit" domain="props.domain" fields="props.fields" selection="domState.selection" setSelection="setSelection.bind(this)"/>
	</BuilderComponent>
</t>

`);
registerTemplate("html_builder.BuilderMany2One", `/html_builder/static/src/core/building_blocks/builder_many2one.xml`, `<t t-name="html_builder.BuilderMany2One" xml:space="preserve">
    <BuilderComponent>
        <SelectMany2X model="props.model" fields="props.fields" limit="props.limit" nullText="props.nullText" domain="props.domain" selected="domState.selected ? [domState.selected] : []" select="select.bind(this)" preview="hasPreview ? preview.bind(this) : undefined" revert.bind="revert" create="props.createAction ? create.bind(this) : undefined" message="domState.selected?.display_name || props.defaultMessage"/>
        <button type="button" t-if="domState.selected and props.allowUnselect" class="o-hb-btn o-hb-btn-has-icon btn btn-secondary" t-on-click="() =&gt; this.select()" t-on-pointerenter="hasPreview ? () =&gt; this.preview() : () =&gt; {}" t-on-pointerleave="revert" t-on-focusin="hasPreview ? () =&gt; this.preview() : () =&gt; {}" t-on-focusout="revert" aria-label="Unselect">
            <i class="oi oi-close" role="presentation"/>
        </button>
    </BuilderComponent>
</t>

`);
registerTemplate("html_builder.BuilderNumberInput", `/html_builder/static/src/core/building_blocks/builder_number_input.xml`, `<t t-name="html_builder.BuilderNumberInput" xml:space="preserve">
    <BuilderComponent>
        <BuilderTextInputBase t-props="textInputBaseProps" inputRef="inputRef" value="displayValue" classes="'o-hb-input-field-number justify-content-end'" inputClasses="props.inputClasses ? \`o-hb-input-number text-end \${props.inputClasses}\` : 'o-hb-input-number text-end'" commit="commit" preview="preview" onKeydown.bind="onKeydown">
            <span class="o-hb-input-field-unit" t-out="props.unit"/>
        </BuilderTextInputBase>
    </BuilderComponent>
</t>

`);
registerTemplate("html_builder.BuilderRange", `/html_builder/static/src/core/building_blocks/builder_range.xml`, `<t t-name="html_builder.BuilderRange" xml:space="preserve">
    <BuilderComponent>
        <div class="o-hb-range d-flex flex-row flex-nowrap align-items-center" t-att-data-action-id="info.actionId" t-att-data-action-param="info.actionParam" t-att-data-action-value="info.actionValue" t-att-data-class-action="info.classAction" t-att-data-style-action="info.styleAction" t-att-data-style-action-value="info.styleActionValue" t-att-data-attribute-action="info.attributeAction" t-att-data-attribute-action-value="info.attributeActionValue">
            <input type="range" class="o-hb-rangeInput" t-ref="inputRef" t-att-class="className" t-att-min="min" t-att-max="max" t-att-step="props.step" t-att-value="rangeInputValue" t-on-change="onChange" t-on-input="onInput" t-on-keydown="onKeydown"/>
            <output t-if="props.displayRangeValue" t-out="displayValue" class="ms-1"/>
        </div>
    </BuilderComponent>
</t>

`);
registerTemplate("html_builder.BuilderRow", `/html_builder/static/src/core/building_blocks/builder_row.xml`, `<t t-name="html_builder.BuilderRow" xml:space="preserve">
    <BuilderComponent>
        <div class="hb-row d-flex position-relative pe-2" t-att-class="this.getLevelClass()" t-ref="root" t-att-data-label="props.label" t-att-data-disabled="props.disabled" t-att-aria-disabled="props.disabled ? 'true' : undefined">

            <button t-ref="collapse" t-if="props.slots.collapse" class="o_hb_collapse_toggler btn border-0 bg-transparent" t-att-class="{ 'active fa-rotate-90': state.expanded }" title="Toggle more options" t-on-click="toggleCollapseContent" t-att-aria-expanded="state.expanded ? 'true' : 'false'" t-att-aria-controls="collapseContentId">
                <i class="fa fa-caret-right" role="img"/>
            </button>

            <t t-if="props.label">
                <div class="hb-row-label d-flex align-items-center" t-att-class="{'hb-row-label-actionable': props.slots.collapse, 'bg-transparent': !props.label.trim()}" t-attf-class="#{this.props.extraLabelClass || ''}" t-on-pointerover="openTooltip" t-on-pointerleave="closeTooltip" t-on-click="toggleCollapseContent">

                    <span class="text-nowrap text-truncate" t-out="props.label" t-ref="label"/>
                    <i t-if="props.tooltip" class="fa fa-question icon-sup" t-att-class="this.isBackendRTL ? 'fa-flip-horizontal' : ''"/>
                </div>
                <div class="hb-row-content d-flex" t-ref="content" t-on-click="onRowContentClick">
                    <t t-slot="default"/>
                </div>
            </t>
            <div t-else="" class="d-flex" style="flex-grow: 1; flex-basis: 0; min-width: 0; gap: 4px;" t-ref="content">
                <t t-slot="default" toggleCollapseContent="() =&gt; this.toggleCollapseContent()"/>
            </div>
        </div>
        <div t-if="displayCollapseContent" t-att-class="collapseContentClass" t-ref="collapse-content" t-att-id="collapseContentId">
            <t t-slot="collapse"/>
        </div>
    </BuilderComponent>
</t>

`);
registerTemplate("html_builder.BuilderSelect", `/html_builder/static/src/core/building_blocks/builder_select.xml`, `<t t-name="html_builder.BuilderSelect" xml:space="preserve">
    <BuilderComponent>

        <div t-ref="root" class="o-hb-select-wrapper">
            <div inert="" class="h-0 w-0 overflow-hidden" t-att-class="props.className" t-ref="content"><WithIgnoreItem><t t-slot="default"/></WithIgnoreItem></div>
            <Dropdown state="this.dropdown" menuClass="props.dropdownClass">
                <button class="o-hb-select-toggle o-hb-btn btn btn-secondary text-start o-dropdown-caret" t-ref="button" t-att-id="props.id" t-att-disabled="props.disabled ? 'disabled' : undefined" t-att-aria-disabled="props.disabled ? 'true' : undefined">
                    <t t-slot="fixedButton"/>
                </button>
                <t t-set-slot="content">
                    <div t-att-class="props.dropdownContainerClass" data-prevent-closing-overlay="true">
                        <t t-slot="default"/>
                    </div>
                </t>
            </Dropdown>
        </div>
    </BuilderComponent>
</t>

`);
registerTemplate("html_builder.BuilderSelectItem", `/html_builder/static/src/core/building_blocks/builder_select_item.xml`, `<t t-name="html_builder.BuilderSelectItem" xml:space="preserve">
    <BuilderComponent>
        <div t-attf-class="o-hb-select-dropdown-item d-flex flex-column cursor-pointer o-dropdown-item dropdown-item o-navigable #{ props.className }" t-att-class="{'active': this.state.isActive}" t-att-data-action-id="info.actionId" t-att-data-action-param="info.actionParam" t-att-data-action-value="info.actionValue" t-att-data-class-action="info.classAction" t-att-data-style-action="info.styleAction" t-att-data-style-action-value="info.styleActionValue" t-att-data-attribute-action="info.attributeAction" t-att-data-attribute-action-value="info.attributeActionValue" t-att-title="props.title" t-on-click="this.onClick" t-on-pointerenter="this.onPointerEnter" t-on-pointerleave="this.onPointerLeave" t-on-focusin="() =&gt; this.onFocusin()" t-on-focusout="() =&gt; this.onFocusout()" t-ref="item" role="menuitem" tabindex="0">
            <t t-slot="default"/>
        </div>
    </BuilderComponent>
</t>

`);
registerTemplate("html_builder.BuilderTextInput", `/html_builder/static/src/core/building_blocks/builder_text_input.xml`, `<t t-name="html_builder.BuilderTextInput" xml:space="preserve">
    <BuilderComponent>
        <BuilderTextInputBase t-props="textInputBaseProps" commit="commit" preview="preview" value="state.value" classes="'o-hb-input-field-text'" inputClasses="'o-hb-input-text'"/>
    </BuilderComponent>
</t>

`);
registerTemplate("html_builder.BuilderTextInputBase", `/html_builder/static/src/core/building_blocks/builder_text_input_base.xml`, `<t t-name="html_builder.BuilderTextInputBase" xml:space="preserve">
    <div class="d-flex flex-row flex-nowrap w-100 align-items-center" t-attf-class="{{ props.classes + ( props.prefix ? ' o-hb-input-base' : '' ) }}" t-att-data-action-id="info.actionId" t-att-data-action-param="info.actionParam" t-att-data-action-value="info.actionValue" t-att-data-class-action="info.classAction" t-att-data-style-action="info.styleAction" t-att-data-style-action-value="info.styleActionValue" t-att-data-attribute-action="info.attributeAction" t-att-data-attribute-action-value="info.attributeActionValue">
        <span t-if="props.prefix" class="o-hb-input-prefix" t-out="props.prefix"/>
        <input t-ref="inputRef" type="text" autocomplete="chrome-off" t-attf-class="{{ props.inputClasses + ( props.prefix ? ' o-hb-input-transparent ' : ' o-hb-input-base ' ) }}" t-att-placeholder="props.placeholder" t-att-data-tooltip="props.tooltip" t-att-aria-label="props.tooltip" t-att-title="props.title" t-on-change="onChange" t-on-input="onInput" t-on-focus="onFocus" t-on-keydown="onKeydown" t-att-value="state.value" t-att-style="props.style"/>
        <t t-slot="default"/>
    </div>
</t>

`);
registerTemplate("html_builder.BuilderUrlPicker", `/html_builder/static/src/core/building_blocks/builder_urlpicker.xml`, `<t t-name="html_builder.BuilderUrlPicker" xml:space="preserve">
    <BuilderComponent>
        <BuilderTextInputBase t-props="textInputBaseProps" inputRef="inputRef" commit="commit" preview="preview" value="state.value">
            <button class="btn" title="Preview this URL in a new tab" t-on-click="openPreviewUrl">
                <i class="fa fa-fw fa-external-link"/>
            </button>
        </BuilderTextInputBase>
    </BuilderComponent>
</t>

`);
registerTemplate("html_builder.ColorPickerThemeTab", `/html_builder/static/src/core/building_blocks/color_picker_theme_tab.xml`, `<t t-name="html_builder.ColorPickerThemeTab" xml:space="preserve">
    <div class="p-2 d-flex flex-column gap-1 o_cc_preview_wrapper" t-on-click="props.onColorClick" t-on-mouseover="props.onColorPointerOver" t-on-mouseout="props.onColorPointerOut" t-on-mouseleave="props.onColorPointerLeave" t-on-focusin="props.onFocusin" t-on-focusout="props.onFocusout">

        <t t-foreach="[1, 2, 3, 4, 5]" t-as="number" t-key="number">
            <t t-set="className" t-value="'o_cc' + number"/>
            <t t-set="activeClass" t-value="this.props.selectedColorCombination === className ? 'selected' : ''"/>
            <div class="d-flex align-items-center">
                <button type="button" class="w-100 p-0 border-0 color-combination-button" t-att-class="[className, activeClass].join(' ')" t-att-data-color="className" t-attf-title="Preset {{number}}">
                    <div inert="" class="p-2 d-flex justify-content-between align-items-center">
                        <h1 class="m-0 fs-4">Title</h1>
                        <p class="m-0 flex-grow-1">Text</p>
                        <span class="py-1 px-1 rounded-1 fs-6 btn btn-sm lh-1 btn btn-sm me-1 d-flex flex-column justify-content-center btn-primary">
                            <small>Button</small>
                        </span>
                        <span class="py-1 px-1 rounded-1 fs-6 btn btn-sm lh-1 btn btn-sm d-flex flex-column justify-content-center btn-secondary">
                            <small>Button</small>
                        </span>
                    </div>
                </button>
                <button t-on-click="() =&gt; this.props.editColorCombination(number)" class="o-hb-edit-color-combination o_colorpicker_ignore fa fa-pencil btn ms-1 px-1" title="Edit"/>
            </div>
        </t>
    </div>
</t>
`);
registerTemplate("html_builder.ModelMany2Many", `/html_builder/static/src/core/building_blocks/model_many2many.xml`, `<t t-name="html_builder.ModelMany2Many" xml:space="preserve">
    <BuilderComponent>
        <BasicMany2Many model="state.searchModel" limit="props.limit" domain="props.domain" fields="props.fields" selection="domState.selection" setSelection="setSelection.bind(this)" create="create.bind(this)"/>
    </BuilderComponent>
</t>

`);
registerTemplate("html_builder.SelectMany2X", `/html_builder/static/src/core/building_blocks/select_many2x.xml`, `<t t-name="html_builder.SelectMany2X" xml:space="preserve">
    <SelectMenu choices="this.filteredSearchResult().map(e =&gt; ({ value: e, label: e.display_name  }))" onSelect="props.select" onNavigated.bind="onNavigated" menuRef="menuRef" onOpened.bind="onOpened" onClosed.bind="onClosed" searchPlaceholder.translate="Search for records..." onInput.bind="onInput" class="'o-hb-selectMany2X-wrapper min-w-0'" menuClass="'o-hb-select-dropdown o-hb-selectMany2X-dropdown'" togglerClass="'o-hb-selectMany2X-toggle btn-secondary'">
        <t t-out="props.message"/>
        <t t-set-slot="bottomArea" t-slot-scope="select">
            <a t-if="state.hasMore" t-on-click="() =&gt; this.searchMore(select.data.searchValue)" class="'o-dropdown-item dropdown-item o-navigable o_we_m2o_search_more'" title="Search to show more records">
                Search more...
            </a>
            <SelectMany2XCreate t-if="!!state.nameToCreate" name="state.nameToCreate" create="this.props.create"/>
        </t>
    </SelectMenu>
</t>

`);
registerTemplate("html_builder.SelectMany2XCreate", `/html_builder/static/src/core/building_blocks/select_many2x.xml`, `<t t-name="html_builder.SelectMany2XCreate" xml:space="preserve">
    <a t-on-click="create" class="o-dropdown-item dropdown-item o-navigable o_we_m2o_create">
        Create "<t t-out="props.name"/>"
    </a>
</t>

`);
registerTemplate("html_builder.DragAndDropMoveHandle", `/html_builder/static/src/core/drag_and_drop_move_handle.xml`, `<t t-name="html_builder.DragAndDropMoveHandle" xml:space="preserve">
    <button class="btn o_move_handle fa fa-arrows" t-att-title="title" t-att-aria-label="title"/>
</t>

`);
registerTemplate("html_builder.background_grid", `/html_builder/static/src/core/grid_layout/grid_layout.xml`, `<t t-name="html_builder.background_grid" xml:space="preserve">
    <div t-attf-style="grid-area: 1 / 1 / #{rowCount} / -1;" class="o_we_background_grid">
        <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
            <defs>
                <pattern id="cell" t-attf-width="#{columnSize + columnGap}px" t-attf-height="#{rowSize + rowGap}px" patternUnits="userSpaceOnUse">
                    <rect class="o_we_cell" x="2" y="2" rx="4" t-attf-width="#{columnSize - 4}px" t-attf-height="#{rowSize - 4}px"/>
                </pattern>
            </defs>

            <rect fill="url(#cell)" width="100%" height="100%"/>
        </svg>
    </div>
</t>

`);
registerTemplate("html_builder.OverlayButtons", `/html_builder/static/src/core/overlay_buttons/overlay_buttons.xml`, `<t t-name="html_builder.OverlayButtons" xml:space="preserve">
    <div t-att-class="{'d-none': !state.showUi or !state.isVisible}" class="o_overlay_options">
        <t t-foreach="state.buttons" t-as="button" t-key="button_index">

            <span t-att-title="button.disabledReason" t-att-aria-label="button.disabledReason">
                <t t-if="button.Component" t-component="button.Component" t-props="button.props || {}"/>
                <t t-else="">
                    <button class="btn" t-att-class="button.class" t-att-title="button.title" t-att-aria-label="button.title" t-att-disabled="!!button.disabledReason" t-on-click="button.handler"/>
                </t>
            </span>
        </t>
    </div>
</t>

`);
registerTemplate("html_builder.SelectNumberColumn", `/html_builder/static/src/core/select_number_column.xml`, `<t t-name="html_builder.SelectNumberColumn" xml:space="preserve">
    <BuilderSelect action="'changeColumnCount'">
        <BuilderSelectItem t-if="this.state.canHaveZeroColumns" actionValue="0">None</BuilderSelectItem>
        <t t-foreach="[1, 2, 3, 4, 5, 6]" t-as="column" t-key="column_index">
            <BuilderSelectItem actionValue="column" t-esc="column"/>
        </t>
        <BuilderSelectItem t-if="this.state.isCustomColumn" actionValue="'custom'">Custom</BuilderSelectItem>
    </BuilderSelect>
</t>
`);
registerTemplate("html_builder.AddProductOption", `/html_builder/static/src/plugins/add_product_option.xml`, `<t t-name="html_builder.AddProductOption" xml:space="preserve">
    <BuilderRow label.translate="Product">
        <BuilderButton type="'success'" action="'addItem'" actionParam="\`\${this.productSelector}:last-of-type\`" preview="false" applyTo="this.buttonApplyTo">
            <t t-out="buttonLabel"/>
        </BuilderButton>
    </BuilderRow>
</t>

`);
registerTemplate("html_builder.AlertOption", `/html_builder/static/src/plugins/alert_option.xml`, `<t t-name="html_builder.AlertOption" xml:space="preserve">
    <BuilderRow label.translate="Type">
        <BuilderSelect>
            <BuilderSelectItem classAction="'alert-primary'" action="'alertIcon'" actionParam="'fa-user-circle'">Primary</BuilderSelectItem>
            <BuilderSelectItem classAction="'alert-secondary'" action="'alertIcon'" actionParam="'fa-user-circle-o'">Secondary</BuilderSelectItem>
            <BuilderSelectItem classAction="'alert-info'" action="'alertIcon'" actionParam="'fa-info-circle'">Info</BuilderSelectItem>
            <BuilderSelectItem classAction="'alert-success'" action="'alertIcon'" actionParam="'fa-check-circle'">Success</BuilderSelectItem>
            <BuilderSelectItem classAction="'alert-warning'" action="'alertIcon'" actionParam="'fa-exclamation-triangle'">Warning</BuilderSelectItem>
            <BuilderSelectItem classAction="'alert-danger'" action="'alertIcon'" actionParam="'fa-exclamation-circle'">Danger</BuilderSelectItem>
            <BuilderSelectItem classAction="'alert-light'" action="'alertIcon'" actionParam="'fa-info-circle'">Light</BuilderSelectItem>
            <BuilderSelectItem classAction="'alert-dark'" action="'alertIcon'" actionParam="'fa-info-circle'">Dark</BuilderSelectItem>
        </BuilderSelect>
    </BuilderRow>
</t>

`);
registerTemplate("html_builder.BackgroundColorWidgetOption", `/html_builder/static/src/plugins/background/background_color_option.xml`, `<t t-name="html_builder.BackgroundColorWidgetOption" xml:space="preserve">
    <BuilderColorPicker title.translate="Color" styleAction="'background-color'"/>
</t>
`);
registerTemplate("html_builder.BackgroundImageOption", `/html_builder/static/src/plugins/background_option/background_image.xml`, `<t t-name="html_builder.BackgroundImageOption" xml:space="preserve">
    <BuilderRow t-if="isActiveItem('toggle_bg_image_id')" label.translate="Image" level="1">
        <BuilderButton preview="false" title.translate="Edit image" type="'success'" action="'replaceBgImage'"> Replace </BuilderButton>
        <BuilderButton preview="false" title.translate="Remove image" icon="'oi-close'" action="'removeBgImage'"/>
        <ImageSize/>
    </BuilderRow>
    <BuilderRow t-if="showMainColorPicker()" label.translate="Main Color" level="2">
        <t t-foreach="getColorPickerColorNames()" t-as="colorName" t-key="colorName_index">
            <BuilderColorPicker action="'dynamicColor'" actionParam="colorName" enabledTabs="['solid', 'custom']"/>
        </t>
    </BuilderRow>
</t>

`);
registerTemplate("html_builder.BackgroundOption", `/html_builder/static/src/plugins/background_option/background_option.xml`, `<t t-name="html_builder.BackgroundOption" xml:space="preserve">

    <BuilderRow label.translate="Background" t-if="props.withColors or props.withImages">

        <t t-if="props.withColors" t-call="html_builder.BackgroundColorWidgetOption"/>
        <t t-if="props.withImages">
            <BuilderButton action="'toggleBgImage'" title.translate="Image" preview="false" className="'ms-auto fa fa-fw fa-camera px-2'" id="'toggle_bg_image_id'"/>
            <t t-if="props.withShapes">
                <BuilderButton action="'toggleBgShape'" preview="false" id="'toggle_bg_shape_id'" iconImg="'/html_builder/static/img/options/bg_shape.svg'" className="'px-2'" title.translate="Shape"/>
            </t>
        </t>
    </BuilderRow>
    <t t-if="props.withImages">
        <BackgroundImageOption/>
        <BackgroundPositionOption/>
        <ImageFilterOption level="2"/>
        <ImageFormatOption level="2" computeMaxDisplayWidth="this.computeMaxDisplayWidth"/>

        <BuilderRow t-if="this.showColorFilter()" label.translate="Color Filter" level="2">
            <BuilderColorPicker action="'selectFilterColor'" defaultOpacity="50" enabledTabs="['custom', 'gradient']" grayscales="{                     'transparent': [                         'black-75',                         'black-50',                         'black-25',                         'black-15',                         'white-25',                         'white-50',                         'white-75',                         'white-85'                     ],                     'solid': [],                 }" selectedTab="'gradient'"/>
        </BuilderRow>
        <BackgroundShapeOption t-if="props.withShapes"/>
    </t>
</t>
`);
registerTemplate("html_builder.BackgroundPositionOption", `/html_builder/static/src/plugins/background_option/background_position_option.xml`, `<t t-name="html_builder.BackgroundPositionOption" xml:space="preserve">
    <t t-if="isActiveItem('toggle_bg_image_id')">
        <BuilderRow label.translate="Position" level="2">
            <BuilderSelect action="'backgroundType'" preview="false">
                <BuilderSelectItem actionValue="'cover'">Cover</BuilderSelectItem>
                <BuilderSelectItem actionValue="'repeat-pattern'" id="'background_repeat_opt'">Repeat pattern</BuilderSelectItem>
            </BuilderSelect>
            <BuilderButton icon="'fa-crosshairs'" title.translate="Background Position" preview="false" action="'backgroundPositionOverlay'"/>
        </BuilderRow>
        <BuilderContext t-if="isActiveItem('background_repeat_opt')" action="'setBackgroundSize'">
            <BuilderRow label.translate="Width" level="3">
                <BuilderNumberInput actionParam="'width'" placeholder.translate="auto" unit="'px'" min="1" default="null"/>
            </BuilderRow>
            <BuilderRow label.translate="Height" level="3">
                <BuilderNumberInput actionParam="'height'" placeholder.translate="auto" unit="'px'" min="1" default="null"/>
            </BuilderRow>
        </BuilderContext>
    </t>
</t>

`);
registerTemplate("html_builder.BackgroundPositionOverlay", `/html_builder/static/src/plugins/background_option/background_position_overlay.xml`, `<t t-name="html_builder.BackgroundPositionOverlay" xml:space="preserve">
    <div class="o_we_background_position_overlay position-fixed" t-ref="backgroundOverlay" t-on-wheel="onWheel">
        <div class="o_we_overlay_mask" t-ref="overlayMask"/>
        <div class="o_we_overlay_content position-absolute" t-ref="overlayContent">
            <div class="o_we_background_dragger" t-ref="bgDragger" title="Click and drag the background to adjust its position!" t-on-mousedown.prevent.stop="onDragBackgroundStart" t-on-pointerdown.stop=""/>
            <div class="o_we_overlay_buttons position-absolute d-flex m-1" style="top: 0">
                <button class="btn btn-primary me-1 o_btn_apply" t-on-click="apply" t-on-pointerdown.stop="">Apply</button>
                <button class="btn btn-danger o_btn_discard" t-on-click="discard" t-on-pointerdown.stop="">Discard</button>
            </div>
        </div>
    </div>
</t>

`);
registerTemplate("html_builder.BackgroundShapeOption", `/html_builder/static/src/plugins/background_option/background_shape_option.xml`, `<t t-name="html_builder.BackgroundShapeOption" xml:space="preserve">
    <BuilderRow label.translate="Shape" level="1" t-if="isActiveItem('toggle_bg_shape_id')">
        <button class="o-hb-btn btn btn-secondary" t-on-click="this.showBackgroundShapes" t-out="state.shapeName"/>
        <BuilderButton title.translate="Show/Hide on Mobile" preview="false" action="'showOnMobile'" className="'o_hb_device btn-danger-color-active'">
            <Img src="'/html_builder/static/img/options/mobile_invisible.svg'" style="'width: 12px'"/>
        </BuilderButton>
        <BuilderButton action="'setBackgroundShape'" actionValue="''" preview="false" icon="'oi-close'"/>
    </BuilderRow>

    <BuilderRow label.translate="Flip" level="2" t-if="isActiveItem('toggle_bg_shape_id')">
        <BuilderButton icon="'oi-arrows-h'" preview="false" action="'flipShape'" actionParam="'x'"/>
        <BuilderButton icon="'oi-arrows-v'" preview="false" action="'flipShape'" actionParam="'y'"/>
    </BuilderRow>

    <BuilderRow label.translate="Colors" level="2">
        <t t-foreach="getDefaultColorNames()" t-as="colorName" t-key="colorName_index">
            <BuilderColorPicker action="'backgroundShapeColor'" actionParam="colorName" enabledTabs="['solid', 'custom']"/>
        </t>

        <BuilderColorPicker styleAction="'background-color'" applyTo="':scope &gt; .o_we_shape'" enabledTabs="['solid', 'custom']"/>
    </BuilderRow>
    <BuilderRow label.translate="Speed" level="2" t-if="state.isAnimated">
        <BuilderRange preview="false" displayRangeValue="true" max="2" min="-2" step="0.1" action="'setBgAnimationSpeed'" computedOutput="this.toRatio"/>
    </BuilderRow>
</t>

`);
registerTemplate("html_builder.BadgeOption", `/html_builder/static/src/plugins/badge_option.xml`, `<t t-name="html_builder.BadgeOption" xml:space="preserve">
    <BuilderRow label.translate="Style">
        <BuilderSelect>
            <BuilderSelectItem classAction="'text-bg-primary'">Primary</BuilderSelectItem>
            <BuilderSelectItem classAction="'text-bg-secondary'">Secondary</BuilderSelectItem>
            <BuilderSelectItem classAction="'text-bg-success'">Success</BuilderSelectItem>
            <BuilderSelectItem classAction="'text-bg-info'">Info</BuilderSelectItem>
            <BuilderSelectItem classAction="'text-bg-warning'">Warning</BuilderSelectItem>
            <BuilderSelectItem classAction="'text-bg-danger'">Danger</BuilderSelectItem>
            <BuilderSelectItem classAction="'text-bg-light'">Light</BuilderSelectItem>
            <BuilderSelectItem classAction="'text-bg-dark'">Dark</BuilderSelectItem>
        </BuilderSelect>
    </BuilderRow>
</t>

`);
registerTemplate("html_builder.BlockAlignmentOption", `/html_builder/static/src/plugins/block_alignment_option.xml`, `<t t-name="html_builder.BlockAlignmentOption" xml:space="preserve">
    <BuilderRow label.translate="Alignment" t-if="!this.isActiveItem('so_width_100')" level="1">
        <BuilderButtonGroup>
            <BuilderButton icon="'fa-align-left'" title.translate="Left" classAction="'me-auto'"/>
            <BuilderButton icon="'fa-align-center'" title.translate="Center" classAction="'mx-auto'"/>
            <BuilderButton icon="'fa-align-right'" title.translate="Right" classAction="'ms-auto'"/>
        </BuilderButtonGroup>
    </BuilderRow>
</t>

`);
registerTemplate("html_builder.BorderConfiguratorOption", `/html_builder/static/src/plugins/border_configurator_option.xml`, `<t t-name="html_builder.BorderConfiguratorOption" xml:space="preserve">
    <BuilderRow label="props.label">
        <BuilderNumberInput action="props.action" actionParam="{ mainParam: getStyleActionParam('width'), extraClass: props.withBSClass and 'border' }" unit="'px'" min="0" composable="true"/>
        <BuilderSelect action="props.action" actionParam="getStyleActionParam('style')" t-if="state.hasBorder">
            <BuilderSelectItem title.translate="Solid" actionValue="'solid'"><div class="o-hb-border-preview" style="border-style: solid;"/></BuilderSelectItem>
            <BuilderSelectItem title.translate="Dashed" actionValue="'dashed'"><div class="o-hb-border-preview" style="border-style: dashed;"/></BuilderSelectItem>
            <BuilderSelectItem title.translate="Dotted" actionValue="'dotted'"><div class="o-hb-border-preview" style="border-style: dotted;"/></BuilderSelectItem>
            <BuilderSelectItem title.translate="Double" actionValue="'double'"><div class="o-hb-border-preview" style="border-style: double; border-left: none; border-right: none;"/></BuilderSelectItem>
        </BuilderSelect>
        <BuilderColorPicker action="props.action" actionParam="getStyleActionParam('color')" t-if="state.hasBorder" enabledTabs="['solid', 'custom']"/>
    </BuilderRow>


    <BuilderRow t-if="props.withRoundCorner and state.hasBorder" label.translate="Round Corners">
        <BuilderNumberInput action="props.action" actionParam="{ mainParam: getStyleActionParam('radius'), extraClass: props.withBSClass and 'rounded' }" unit="'px'" min="0" composable="true"/>
    </BuilderRow>
</t>

`);
registerTemplate("html_builder.CTABadgeOption", `/html_builder/static/src/plugins/cta_badge_option.xml`, `<t t-name="html_builder.CTABadgeOption" xml:space="preserve">
    <BorderConfigurator label.translate="Border"/>
    <ShadowOption t-if="!this.excludeShadowOption"/>
</t>

`);
registerTemplate("html_builder.FontSizeSelector", `/html_builder/static/src/plugins/font/font_size_selector.xml`, `<t t-name="html_builder.FontSizeSelector" t-inherit="html_editor.FontSizeSelector" xml:space="preserve">
        <xpath expr="//DropdownItem" position="inside">
            <span class="badge o-we-font-size-item-bg ms-3 float-end"><t t-out="fontSizeTags[item.variableName]"/></span>
        </xpath>
    </t>
`);
registerTemplate("html_builder.ImageFilterOption", `/html_builder/static/src/plugins/image/image_filter_option.xml`, `<t t-name="html_builder.ImageFilterOption" xml:space="preserve">
    <BuilderRow label.translate="Filter" level="this.props.level" t-if="state.showFilter" disabled="state.disableFilter" tooltip="state.tooltip">
        <BuilderSelect disabled="state.disableFilter">
            <BuilderSelectItem action="'glFilter'" actionParam="''">None</BuilderSelectItem>
            <BuilderSelectItem action="'glFilter'" actionParam="'blur'">Blur</BuilderSelectItem>
            <BuilderSelectItem action="'glFilter'" actionParam="'1977'">1977</BuilderSelectItem>
            <BuilderSelectItem action="'glFilter'" actionParam="'aden'">Aden</BuilderSelectItem>
            <BuilderSelectItem action="'glFilter'" actionParam="'brannan'">Brannan</BuilderSelectItem>
            <BuilderSelectItem action="'glFilter'" actionParam="'earlybird'">EarlyBird</BuilderSelectItem>
            <BuilderSelectItem action="'glFilter'" actionParam="'inkwell'">Inkwell</BuilderSelectItem>
            <BuilderSelectItem action="'glFilter'" actionParam="'maven'">Maven</BuilderSelectItem>
            <BuilderSelectItem action="'glFilter'" actionParam="'toaster'">Toaster</BuilderSelectItem>
            <BuilderSelectItem action="'glFilter'" actionParam="'walden'">Walden</BuilderSelectItem>
            <BuilderSelectItem action="'glFilter'" actionParam="'valencia'">Valencia</BuilderSelectItem>
            <BuilderSelectItem action="'glFilter'" actionParam="'xpro'">Xpro</BuilderSelectItem>
            <BuilderSelectItem action="'glFilter'" actionParam="'custom'" id="custom_glfilter_opt">Custom</BuilderSelectItem>
        </BuilderSelect>
    </BuilderRow>
    <t t-if="state.isCustomFilter">
        <BuilderRow level="this.props.level + 1" label.translate="Color">
            <BuilderSelect action="'setCustomFilter'" actionParam="'blend'">
                <BuilderSelectItem actionValue="'normal'">Normal</BuilderSelectItem>
                <BuilderSelectItem actionValue="'overlay'">Overlay</BuilderSelectItem>
                <BuilderSelectItem actionValue="'screen'">Screen</BuilderSelectItem>
                <BuilderSelectItem actionValue="'multiply'">Multiply</BuilderSelectItem>
                <BuilderSelectItem actionValue="'lighter'">Add</BuilderSelectItem>
                <BuilderSelectItem actionValue="'exclusion'">Exclusion</BuilderSelectItem>
                <BuilderSelectItem actionValue="'darken'">Darken</BuilderSelectItem>
                <BuilderSelectItem actionValue="'lighten'">Lighten</BuilderSelectItem>
            </BuilderSelect>
            <BuilderColorPicker action="'setCustomFilter'" actionParam="'filterColor'" enabledTabs="['custom']"/>
        </BuilderRow>
        <BuilderRow level="this.props.level + 1" label.translate="Saturation">
            <BuilderRange action="'setCustomFilter'" actionParam="'saturation'" min="-100" max="100" step="10"/>
        </BuilderRow>
        <BuilderRow level="this.props.level + 1" label.translate="Contrast">
            <BuilderRange action="'setCustomFilter'" actionParam="'contrast'" min="-100" max="100" step="10"/>
        </BuilderRow>
        <BuilderRow level="this.props.level + 1" label.translate="Brightness">
            <BuilderRange action="'setCustomFilter'" actionParam="'brightness'" min="-100" max="100" step="10"/>
        </BuilderRow>
        <BuilderRow level="this.props.level + 1" label.translate="Sepia">
            <BuilderRange action="'setCustomFilter'" actionParam="'sepia'" min="0" max="100" step="5"/>
        </BuilderRow>
        <BuilderRow level="this.props.level + 1" label.translate="Blur">
            <BuilderRange action="'setCustomFilter'" actionParam="'blur'" min="0" max="2000" step="100"/>
        </BuilderRow>
    </t>
</t>

`);
registerTemplate("html_builder.ImageFormat", `/html_builder/static/src/plugins/image/image_format_option.xml`, `<t t-name="html_builder.ImageFormat" xml:space="preserve">
    <BuilderRow label.translate="Format" level="this.props.level" t-if="this.state.showFormat">
        <BuilderSelect>
            <t t-foreach="state.formats" t-as="format" t-key="format.id">
                <BuilderSelectItem className="'o_we_badge_at_end'" action="'setImageFormat'" actionParam="format">
                    <div class="d-flex align-items-center overflow-hidden">
                        <span class="text-truncate flex-grow-1 me-2" t-out="format.label"/>
                        <span class="badge rounded-pill me-1 top-0 align-self-center flex-shrink-0" t-out="format.mimetype.split('/')[1]"/>
                    </div>
                </BuilderSelectItem>
            </t>
        </BuilderSelect>
    </BuilderRow>
    <BuilderRow label.translate="Quality" t-if="state.showQuality and state.formats.length" level="this.props.level">
        <BuilderRange action="'setImageQuality'" min="0" max="100" t-if="!state.compressionUnsupported"/>
        <span t-if="state.compressionUnsupported" class="fst-italic">
            WebP compression not supported on this browser
        </span>
    </BuilderRow>
</t>



`);
registerTemplate("html_builder.ImageShapeOption", `/html_builder/static/src/plugins/image/image_shape_option.xml`, `<t t-name="html_builder.ImageShapeOption" xml:space="preserve">
    <BuilderRow label.translate="Shape" t-if="this.state.isShapeSupported">
        <div class="btn-group o-hb-button-group">
            <div class="o-hb-btn btn btn-secondary o-dropdown dropdown-toggle dropdown" t-att-class="{'border-end-0 rounded-end-0': state.hasShape}" role="button" tabindex="0" t-on-click="this.showImageShapes" t-out="state.shapeLabel"/>
            <BuilderButton action="'setImageShape'" actionValue="" preview="false" icon="'oi-close'" className="'btn-danger-color-hover rounded-start-0 m-0 py-0 flex-grow-0'" t-if="state.hasShape"/>
        </div>
    </BuilderRow>
    <t t-if="this.state.hasShape">
        <t t-set="enabledTabs" t-value="['solid', 'custom']"/>
        <BuilderRow label.translate="Colors" level="2">
            <BuilderColorPicker action="'setImgShapeColor'" actionParam="{index: 0}" t-if="this.state.showImageShape0" enabledTabs="enabledTabs"/>
            <BuilderColorPicker action="'setImgShapeColor'" actionParam="{index: 1}" t-if="this.state.showImageShape1" enabledTabs="enabledTabs"/>
            <BuilderColorPicker action="'setImgShapeColor'" actionParam="{index: 2}" t-if="this.state.showImageShape2" enabledTabs="enabledTabs"/>
            <BuilderColorPicker action="'setImgShapeColor'" actionParam="{index: 3}" t-if="this.state.showImageShape3" enabledTabs="enabledTabs"/>
            <BuilderColorPicker action="'setImgShapeColor'" actionParam="{index: 4}" t-if="this.state.showImageShape4" enabledTabs="enabledTabs"/>
        </BuilderRow>

        <BuilderRow label.translate="Transform" level="1" t-if="this.state.showImageShapeTransform" preview="false">
            <BuilderButton title.translate="Horizontal mirror" icon="'oi-arrows-h'" action="'flipImageShape'" actionParam="{axis: 'x'}"/>
            <BuilderButton title.translate="Vertical mirror" icon="'oi-arrows-v'" action="'flipImageShape'" actionParam="{axis: 'y'}"/>
            <BuilderButton title.translate="Rotate left" icon="'fa-rotate-left'" action="'rotateImageShape'" actionParam="{side: 'left'}"/>
            <BuilderButton title.translate="Rotate right" icon="'fa-rotate-right'" action="'rotateImageShape'" actionParam="{side: 'right'}"/>
            <BuilderButton title.translate="Reset shape transformation" icon="'oi-close'" action="'resetImageShapeTransformation'" className="'btn-danger-color-hover'" t-if="this.state.hasShapeTransformation"/>
        </BuilderRow>

        <BuilderRow label.translate="Speed" level="1" t-if="this.state.showImageShapeAnimation" preview="false">
            <BuilderRange action="'setImageShapeSpeed'" min="-2" max="2" step="0.1" displayRangeValue="true" computedOutput="this.toRatio"/>
        </BuilderRow>

        <BuilderRow label.translate="Stretch" level="1" t-if="this.state.togglableRatio" preview="false">
            <BuilderCheckbox action="'toggleImageShapeRatio'"/>
        </BuilderRow>
    </t>
</t>

`);
registerTemplate("html_builder.ImageSize", `/html_builder/static/src/plugins/image/image_size.xml`, `<t t-name="html_builder.ImageSize" xml:space="preserve">
    <span t-if="state.size" class="o-hb-image-size-info text-nowrap p-1 rounded" title="Size" t-out="state.size"/>
</t>

`);
registerTemplate("html_builder.ImageToolOption", `/html_builder/static/src/plugins/image/image_tool_option.xml`, `<t t-name="html_builder.ImageToolOption" xml:space="preserve">
    <t t-if="!state.isDynamicSVG">
        <ImageShapeOption/>
    </t>
    <BuilderRow label.translate="Description" t-if="!state.isImageBinaryField" tooltip.translate="'Alt tag' specifies an alternate text for an image, if the image cannot be displayed (slow connection, missing image, screen reader ...).">
        <BuilderTextInput action="'alt'" placeholder.translate="Alt tag"/>
    </BuilderRow>
    <BuilderRow label.translate="Tooltip" t-if="!state.isImageBinaryField" tooltip.translate="'Title tag' is shown as a tooltip when you hover the picture.">
        <BuilderTextInput attributeAction="'title'" placeholder.translate="Title tag"/>
    </BuilderRow>
    <BuilderRow label.translate="Transform" preview="false">
        <BuilderButton t-if="state.showCropTool" title.translate="Crop image" action="'cropImage'" icon="'fa-crop'" id="'cropImage'"/>
        <BuilderButton title.translate="Reset crop" action="'resetCrop'" t-if="this.state.showCropTool and this.isActiveItem('cropImage')">Reset</BuilderButton>
        <ImageTransformOption t-if="!state.isImageAnimated and !state.isImageBinaryField"/>
    </BuilderRow>
    <ImageFilterOption/>
    <BuilderRow label.translate="Size" t-if="!state.isImageBinaryField">
        <BuilderButtonGroup styleAction="'width'">
            <BuilderButton styleActionValue="''" title.translate="Resize Default">Default</BuilderButton>
            <BuilderButton styleActionValue="'25%'" title.translate="Resize Quarter">25%</BuilderButton>
            <BuilderButton styleActionValue="'50%'" title.translate="Resize Half">50%</BuilderButton>
            <BuilderButton styleActionValue="'100%'" title.translate="Resize Full">100%</BuilderButton>
        </BuilderButtonGroup>
    </BuilderRow>
    <ImageFormatOption/>
</t>

`);
registerTemplate("html_builder.ImageAndFaOption", `/html_builder/static/src/plugins/image/image_tool_option.xml`, `<t t-name="html_builder.ImageAndFaOption" xml:space="preserve">
    <BuilderRow label.translate="Alignment">
        <BuilderSelect>
            <BuilderSelectItem action="'imageAlignClassAction'" actionParam="''" title.translate="Unalign">None</BuilderSelectItem>
            <BuilderSelectItem action="'imageAlignClassAction'" actionParam="'me-auto float-start'" title.translate="Align Left">Left</BuilderSelectItem>
            <BuilderSelectItem action="'imageAlignClassAction'" actionParam="'mx-auto d-block'" title.translate="Align Center">Center</BuilderSelectItem>
            <BuilderSelectItem action="'imageAlignClassAction'" actionParam="'ms-auto float-end'" title.translate="Align Right">Right</BuilderSelectItem>
        </BuilderSelect>
    </BuilderRow>
    <BuilderRow label.translate="Style">
        <BuilderButton icon="'fa-square'" classAction="'rounded'" title.translate="Shape: Rounded"/>
        <BuilderButton icon="'fa-circle-o'" classAction="'rounded-circle'" title.translate="Shape: Circle"/>
        <BuilderButton icon="'fa-sun-o'" classAction="'shadow'" title.translate="Shadow"/>
        <BuilderButton icon="'fa-picture-o'" classAction="'img-thumbnail'" title.translate="Shape: Thumbnail"/>
    </BuilderRow>

    <BuilderRow label.translate="Padding">
        <BuilderNumberInput styleAction="'padding'" unit="'px'" composable="true"/>
    </BuilderRow>

</t>

`);
registerTemplate("website.ImageTransformOption", `/html_builder/static/src/plugins/image/image_transform_option.xml`, `<t t-name="website.ImageTransformOption" xml:space="preserve">
        <BuilderButton title.translate="Transform the picture" id="'transform_image'" action="'transformImage'" actionParam="{ isImageTransformationOpen: transform.isImageTransformationOpen, closeImageTransformation: closeImageTransformation.bind(this) }" icon="'fa-object-ungroup'"/>
        <BuilderButton title.translate="Reset transformation" action="'resetTransformImage'" actionParam="closeImageTransformation.bind(this)" t-if="isActiveItem('transform_image')">Reset</BuilderButton>
    </t>
`);
registerTemplate("html_builder.ReplaceMediaOption", `/html_builder/static/src/plugins/image/replace_media_option.xml`, `<t t-name="html_builder.ReplaceMediaOption" xml:space="preserve">
    <BuilderRow label.translate="Media">
        <BuilderButton action="'replaceMedia'" title="state.tooltipName" className="'flex-grow-1'" type="'success'" preview="false" label.translate="Replace"/>
        <BuilderButton icon="'fa-link'" t-if="state.canSetLink" id="'media_link_opt'" action="'setLink'" title.translate="Redirect the user elsewhere when he clicks on the media."/>
    </BuilderRow>
    <BuilderRow label.translate="Your URL" level="1" t-if="isActiveItem('media_link_opt')">
        <BuilderUrlPicker title.translate="Your URL" action="'setUrl'" inputClasses="'o_we_large'" placeholder.translate="www.example.com"/>
    </BuilderRow>
    <BuilderRow label.translate="Open in New Window" level="1" t-if="state.hasHref">
        <BuilderCheckbox action="'setNewWindow'"/>
    </BuilderRow>
</t>

`);
registerTemplate("html_builder.LayoutColumnOption", `/html_builder/static/src/plugins/layout_column_option.xml`, `<t t-name="html_builder.LayoutColumnOption" xml:space="preserve">
        <BuilderRow label.translate="Columns">
            <SelectNumberColumn/>
        </BuilderRow>
    </t>
`);
registerTemplate("html_builder.Many2OneOption", `/html_builder/static/src/plugins/many2one_option.xml`, `<t t-name="html_builder.Many2OneOption" xml:space="preserve">
    <BuilderRow label="label">
        <BuilderMany2One action="'many2One'" model="model" fields="['name']" domain="domain" nullText="nullText" allowUnselect="false"/>
    </BuilderRow>
</t>

`);
registerTemplate("html_builder.RatingOption", `/html_builder/static/src/plugins/rating_option.xml`, `<t t-name="html_builder.RatingOption" xml:space="preserve">
    <BuilderRow label.translate="Icon">
        <BuilderSelect>
            <BuilderSelectItem action="'setIcons'" actionParam="'fa-star'">Stars</BuilderSelectItem>
            <BuilderSelectItem action="'setIcons'" actionParam="'fa-thumbs-up'">Thumbs</BuilderSelectItem>
            <BuilderSelectItem action="'setIcons'" actionParam="'fa-circle'">Circles</BuilderSelectItem>
            <BuilderSelectItem action="'setIcons'" actionParam="'fa-square'">Squares</BuilderSelectItem>
            <BuilderSelectItem action="'setIcons'" actionParam="'fa-heart'">Hearts</BuilderSelectItem>
            <BuilderSelectItem action="'setIcons'" actionParam="'custom'">Custom</BuilderSelectItem>
        </BuilderSelect>
    </BuilderRow>
    <BuilderRow label.translate="⌙ Active">
        <BuilderColorPicker applyTo="'.s_rating_active_icons'" styleAction="'color'" enabledTabs="['solid', 'custom']"/>
        <BuilderButton action="'customIcon'" actionParam="'customActiveIcon'" preview="false"><i class="fa fa-fw fa-refresh me-1"/> Replace Icon</BuilderButton>
    </BuilderRow>
    <BuilderRow label.translate="⌙ Inactive">
        <BuilderColorPicker applyTo="'.s_rating_inactive_icons'" styleAction="'color'" enabledTabs="['solid', 'custom']"/>
        <BuilderButton action="'customIcon'" actionParam="'customInactiveIcon'" preview="false"><i class="fa fa-fw fa-refresh me-1"/> Replace Icon</BuilderButton>
    </BuilderRow>
    <BuilderRow label.translate="Score">
        <BuilderNumberInput action="'activeIconsNumber'" min="0"/>
        <span class="mx-2">/</span>
        <BuilderNumberInput action="'totalIconsNumber'" min="1"/>
    </BuilderRow>
    <BuilderRow label.translate="Size">
        <BuilderButtonGroup applyTo="'.s_rating_icons'">
            <BuilderButton classAction="''" title.translate="Small"><Img src="'/html_builder/static/img/options/size_small.svg'"/></BuilderButton>
            <BuilderButton classAction="'fa-2x'" title.translate="Medium"><Img src="'/html_builder/static/img/options/size_medium.svg'"/></BuilderButton>
            <BuilderButton classAction="'fa-3x'" title.translate="Large"><Img src="'/html_builder/static/img/options/size_large.svg'"/></BuilderButton>
        </BuilderButtonGroup>
    </BuilderRow>
    <BuilderRow label.translate="Title Position">
        <BuilderSelect>
            <BuilderSelectItem classAction="''">Top</BuilderSelectItem>
            <BuilderSelectItem classAction="'s_rating_inline'">Left</BuilderSelectItem>
            <BuilderSelectItem classAction="'s_rating_no_title'">None</BuilderSelectItem>
        </BuilderSelect>
    </BuilderRow>
</t>

`);
registerTemplate("html_builder.SeparatorOption", `/html_builder/static/src/plugins/separator_option.xml`, `<t t-name="html_builder.SeparatorOption" xml:space="preserve">
    <BorderConfigurator withRoundCorner="false" withBSClass="false" label.translate="Border" direction="'top'"/>
    <BuilderRow label.translate="Width">
        <BuilderSelect>
            <BuilderSelectItem classAction="'w-25'">25%</BuilderSelectItem>
            <BuilderSelectItem classAction="'w-50'">50%</BuilderSelectItem>
            <BuilderSelectItem classAction="'w-75'">75%</BuilderSelectItem>
            <BuilderSelectItem classAction="'w-100'" id="'so_width_100'">100%</BuilderSelectItem>
        </BuilderSelect>
    </BuilderRow>
    <BuilderRow label.translate="Alignment" t-if="!this.isActiveItem('so_width_100')">
        <BuilderButtonGroup>
            <BuilderButton icon="'fa-align-left'" title.translate="Left" classAction="'me-auto'"/>
            <BuilderButton icon="'fa-align-center'" title.translate="Center" classAction="'mx-auto'"/>
            <BuilderButton icon="'fa-align-right'" title.translate="Right" classAction="'ms-auto'"/>
        </BuilderButtonGroup>
    </BuilderRow>
</t>

`);
registerTemplate("html_builder.ShadowOption", `/html_builder/static/src/plugins/shadow_option.xml`, `<t t-name="html_builder.ShadowOption" xml:space="preserve">
    <BuilderRow label.translate="Shadow">
       <BuilderButtonGroup action="props.setShadowModeAction">
         <BuilderButton actionValue="'none'" id="'no_shadow'" className="'lh-1'">None</BuilderButton>
         <BuilderButton actionValue="'outset'" title.translate="Outset" iconImg="'/html_builder/static/img/options/shadow_out.svg'"/>
         <BuilderButton actionValue="'inset'" title.translate="Inset" iconImg="'/html_builder/static/img/options/shadow_in.svg'"/>
       </BuilderButtonGroup>
    </BuilderRow>
    <BuilderContext t-if="!this.isActiveItem('no_shadow')" action="props.setShadowAction">
        <BuilderRow label.translate="Color" level="1">
            <BuilderColorPicker actionParam="'color'" enabledTabs="['solid', 'custom']"/>
        </BuilderRow>

        <BuilderRow label.translate="Offset (X, Y)" level="1">
            <BuilderNumberInput actionParam="'offsetX'" unit="'px'"/>
            <BuilderNumberInput actionParam="'offsetY'" unit="'px'"/>
        </BuilderRow>

        <BuilderRow label.translate="Blur" level="1">
            <BuilderNumberInput actionParam="'blur'" unit="'px'"/>
        </BuilderRow>

        <BuilderRow label.translate="Spread" level="1">
            <BuilderNumberInput actionParam="'spread'" unit="'px'"/>
        </BuilderRow>
    </BuilderContext>
</t>

`);
registerTemplate("html_builder.shapeSelector", `/html_builder/static/src/plugins/shape/shape_selector.xml`, `<t t-name="html_builder.shapeSelector" xml:space="preserve">
    <header class="o_pager_nav d-flex flex-column flex-wrap flex-shrink-0 mh-100">
        <div class="d-flex align-items-center p-2">
            <button class="o_pager_nav_angle btn btn-secondary bg-transparent border-0" t-on-click="this.props.onClose" t-ref="backButton">
                    <i class="fa fa-angle-left" aria-hidden="true"/>
                    <span class="visually-hidden">Back</span>
                    <span class="ps-2" t-out="props.selectorTitle"/>
            </button>
        </div>
        <div class="o-hb-select-pager-tab-container d-flex" t-ref="tabs">
            <t t-foreach="Object.entries(this.props.shapeGroups)" t-as="group" t-key="group_index">
                <button type="button" class="o-hb-select-pager-tab p-0 text-uppercase" t-att-class="{ 'active': state.activeGroup === group[0] }" t-on-click="() =&gt; this.scrollToShapes(group[0])" t-att-data-group-id="group[0]">
                    <span class="w-100" t-out="group[1].label"/>
                </button>
            </t>
        </div>
    </header>
    <div class="o_pager_container" t-ref="root" t-on-scroll="onScroll">
        <t t-foreach="Object.entries(this.props.shapeGroups)" t-as="group" t-key="group_index">
            <div t-att-data-shape-group-id="group[0]">
                <t t-foreach="Object.entries(group[1].subgroups)" t-as="subgroup" t-key="subgroup_index">
                    <div class="ms-3 py-2" t-out="subgroup[1].label"/>
                    <div class="builder_select_page my-2">
                        <ImgGroup>
                            <t t-foreach="Object.entries(subgroup[1].shapes)" t-as="shape" t-key="shape_index">
                                <div t-att-class="this.props.buttonWrapperClassName" t-on-click="this.props.onClose" t-if="!shape[1].isTechnical">
                                    <BuilderButton type="''" action="this.props.shapeActionId" actionValue="shape[0]">
                                        <div t-att-class="props.imgThroughDiv ? 'o_we_shape_btn_content' : ''">
                                            <t t-if="props.imgThroughDiv">
                                                <div class="o_we_shape" t-att-class="this.getShapeClass(shape[0])"/>
                                            </t>
                                            <t t-else="">
                                                <Img src="this.getShapeUrl(shape[0])" svgCheck="false"/>
                                            </t>
                                            <span t-if="shape[1].imgSize" class="o_we_shape_animated_label">
                                                <i class="fa fa-expand"/>
                                                <span t-out="shape[1].imgSize"/>
                                            </span>
                                            <span t-elif="shape[1].animated" class="o_we_shape_animated_label">A<span>nimated</span></span>
                                        </div>
                                    </BuilderButton>
                                </div>
                            </t>
                        </ImgGroup>
                    </div>
                </t>
            </div>
        </t>
    </div>
</t>


`);
registerTemplate("html_builder.SizeOption", `/html_builder/static/src/plugins/size_option.xml`, `<t t-name="html_builder.SizeOption" xml:space="preserve">
    <BuilderRow label.translate="Size">
        <BuilderSelect>
            <BuilderSelectItem classAction="'s_alert_sm'">Small</BuilderSelectItem>
            <BuilderSelectItem classAction="'s_alert_md'">Medium</BuilderSelectItem>
            <BuilderSelectItem classAction="'s_alert_lg'">Large</BuilderSelectItem>
        </BuilderSelect>
    </BuilderRow>
</t>

`);
registerTemplate("html_builder.TextAlignmentOption", `/html_builder/static/src/plugins/text_alignment_option.xml`, `<t t-name="html_builder.TextAlignmentOption" xml:space="preserve">
    <BuilderRow label.translate="Alignment">
        <BuilderButtonGroup>
            <BuilderButton icon="'fa-align-left'" title.translate="Left" classAction="'text-start'"/>
            <BuilderButton icon="'fa-align-center'" title.translate="Center" classAction="'text-center'"/>
            <BuilderButton icon="'fa-align-right'" title.translate="Right" classAction="'text-end'"/>
        </BuilderButtonGroup>
    </BuilderRow>
</t>

`);
registerTemplate("html_builder.VerticalAlignmentOption", `/html_builder/static/src/plugins/vertical_alignment_option.xml`, `<t t-name="html_builder.VerticalAlignmentOption" xml:space="preserve">
    <t t-if="!isActiveItem('grid_mode')">

        <BuilderRow label.translate="Vert. Alignment" level="this.level">
            <BuilderButtonGroup action="'setVerticalAlignment'">
                <BuilderButton actionParam="'align-items-start'" title.translate="Align Top" iconImg="'/html_builder/static/img/snippets_options/align_top.svg'"/>
                <BuilderButton actionParam="'align-items-center'" title.translate="Align Middle" iconImg="'/html_builder/static/img/snippets_options/align_middle.svg'"/>
                <BuilderButton actionParam="'align-items-end'" title.translate="Align Bottom" iconImg="'/html_builder/static/img/snippets_options/align_bottom.svg'"/>
                <BuilderButton t-if="this.justify" actionParam="'align-items-stretch'" title.translate="Stretch to Equal Height" iconImg="'/html_builder/static/img/snippets_options/align_stretch.svg'"/>
            </BuilderButtonGroup>
        </BuilderRow>
    </t>
</t>

`);
registerTemplate("html_builder.VerticalJustifyOption", `/html_builder/static/src/plugins/vertical_justify_option.xml`, `<t t-name="html_builder.VerticalJustifyOption" xml:space="preserve">

    <BuilderRow label.translate="Vert. Alignment" tooltip.translate="Vertical Alignment">
        <BuilderButtonGroup>
            <BuilderButton title.translate="Align Top" classAction="'justify-content-start'" iconImg="'/html_builder/static/img/snippets_options/align_solo_top.svg'"/>
            <BuilderButton title.translate="Align Middle" classAction="'justify-content-center'" iconImg="'/html_builder/static/img/snippets_options/align_solo_middle.svg'"/>
            <BuilderButton title.translate="Align Bottom" classAction="'justify-content-end'" iconImg="'/html_builder/static/img/snippets_options/align_solo_bottom.svg'"/>
        </BuilderButtonGroup>
    </BuilderRow>
</t>
`);
registerTemplate("html_builder.WidthOption", `/html_builder/static/src/plugins/width_option.xml`, `<t t-name="html_builder.WidthOption" xml:space="preserve">
    <BuilderRow label.translate="Width">
        <BuilderSelect>
            <BuilderSelectItem classAction="'w-25'">25%</BuilderSelectItem>
            <BuilderSelectItem classAction="'w-50'">50%</BuilderSelectItem>
            <BuilderSelectItem classAction="'w-75'">75%</BuilderSelectItem>
            <BuilderSelectItem classAction="'w-100'" id="'so_width_100'">100%</BuilderSelectItem>
        </BuilderSelect>
    </BuilderRow>
</t>

`);
registerTemplate("html_builder.BlockTab", `/html_builder/static/src/sidebar/block_tab.xml`, `<t t-name="html_builder.BlockTab" xml:space="preserve">
    <t t-set="disabledGroupTooltip">No block of this category can be dropped on this page.</t>
    <t t-set="disabledBlockTooltip">This block cannot be dropped anywhere on this page.</t>
    <div class="o_block_tab" t-att-class="{'o_we_ongoing_insertion': this.state.ongoingInsertion}" t-ref="block-tab" role="tabpanel" aria-labelledby="blocks-tab">
        <div t-if="this.snippetModel.snippetGroups.length" class="o_snippets_container" id="snippet_groups">
            <div class="o_snippets_container_body o_snippets_container_body_row_cols_2">
                <t t-foreach="this.snippetModel.snippetGroups" t-as="snippet" t-key="snippet.id">
                    <Snippet snippet="snippet" snippetModel="this.snippetModel" onClickHandler="() =&gt; this.onSnippetGroupClick(snippet)" disabledTooltip="disabledGroupTooltip"/>
                </t>
            </div>
        </div>

        <t t-if="this.snippetModel.hasCustomInnerContents">
            <div class="o_snippets_container" id="snippet_custom_content">
                <div class="o_snippets_container_header"><span>Custom Inner Content</span></div>
                <div class="o_snippets_container_body">
                    <t t-foreach="this.snippetModel.snippetCustomInnerContents" t-as="snippet" t-key="snippet.id">
                        <CustomInnerSnippet snippet="snippet" snippetModel="this.snippetModel" onClickHandler.bind="showSnippetTooltip" disabledTooltip="disabledBlockTooltip"/>
                    </t>
                </div>
            </div>
        </t>

        <div t-if="this.snippetModel.snippetInnerContents.length" class="o_snippets_container" id="snippet_content">
            <div class="o_snippets_container_header"><span>Inner Content</span></div>
            <div class="o_snippets_container_body">
                <t t-foreach="this.snippetModel.snippetInnerContents" t-as="snippet" t-key="snippet.id">
                    <Snippet snippet="snippet" snippetModel="this.snippetModel" onClickHandler.bind="showSnippetTooltip" disabledTooltip="disabledBlockTooltip"/>
                </t>
            </div>
        </div>
    </div>
</t>

`);
registerTemplate("html_builder.CustomInnerSnippet", `/html_builder/static/src/sidebar/custom_inner_snippet.xml`, `<t t-name="html_builder.CustomInnerSnippet" xml:space="preserve">
    <t t-set="disabledTooltip">This block cannot be dropped anywhere on this page.</t>
    <div class="o_snippet" t-att-class="{'o_disabled': snippet.isDisabled, 'o_draggable': !snippet.isDisabled and !state.isRenaming}" t-att-name="snippet.title" t-att-data-id="snippet.id" t-att-data-tooltip="snippet.isDisabled and props.disabledTooltip">
        <div class="o_snippet_thumbnail" t-att-data-snippet="snippet.name">
            <button t-if="!snippet.isInstallable" class="o_snippet_thumbnail_area" t-on-click="props.onClickHandler" title="Insert snippet"/>
            <Img t-if="snippet.isDisabled" src="'/html_builder/static/img/snippet_disabled.svg'" class="'o_snippet_undroppable'"/>
            <div class="o_snippet_thumbnail_img" t-attf-style="background-image: url({{snippet.thumbnailSrc}});"/>
            <t t-if="state.isRenaming">
                <div class="rename-input w-100 mx-1 z-1">
                    <input t-ref="rename-input" type="text" autocomplete="chrome-off" t-att-value="snippet.title" class="text-start" t-on-pointerdown.stop=""/>
                    <button class="o_we_text_success fa fa-check btn btn-outline-success border-0" data-tooltip="Confirm" t-on-click="onConfirmRename"/>
                    <button class="o_we_text_danger fa fa-times btn btn-outline-danger border-0" data-tooltip="Cancel" t-on-click="toggleRenamingState"/>
                </div>
            </t>
            <t t-else="">
                <span class="o_snippet_thumbnail_title" t-esc="snippet.title"/>
            </t>
        </div>
        <div t-if="!state.isRenaming" class="rename-delete-buttons float-end z-1">
            <button class="fa fa-pencil btn o_we_hover_success btn-outline-info border-0" t-att-data-tooltip="renameButtonTooltip" t-on-click.stop="toggleRenamingState"/>
            <button class="fa fa-trash btn o_we_hover_danger btn-outline-danger border-0" t-att-data-tooltip="deleteButtonTooltip" t-on-click="() =&gt; this.props.snippetModel.deleteCustomSnippet(snippet)"/>
        </div>
    </div>
</t>

`);
registerTemplate("html_builder.CustomizeComponent", `/html_builder/static/src/sidebar/customize_component.xml`, `<t t-name="html_builder.CustomizeComponent" xml:space="preserve">
    <t t-component="this.props.comp" t-props="this.props.compProps"/>
</t>

`);
registerTemplate("html_builder.CustomizeTab", `/html_builder/static/src/sidebar/customize_tab.xml`, `<t t-name="html_builder.CustomizeTab" xml:space="preserve">
    <div class="o_customize_tab h-100" role="tabpanel" aria-labelledby="customize-tab">
        <t t-set="currentOptionsContainers" t-value="this.getCurrentOptionsContainers()"/>
        <t t-if="!currentOptionsContainers.length || !this.state.hasContent">
            <div class="text-center pt-5">
                Select a block on your page to style it.
            </div>
        </t>
        <t t-else="">
            <div t-ref="content" class="d-flex flex-column h-100">
                <CustomizeComponent t-if="this.customizeComponent.component" editingElements="this.customizeComponent.editingEls" comp="this.customizeComponent.component" compProps="this.customizeComponent.props"/>
                <t t-else="" t-foreach="currentOptionsContainers" t-as="optionsContainer" t-key="optionsContainer.id">
                    <OptionsContainer snippetModel="props.snippetModel" editingElement="optionsContainer.element" options="optionsContainer.options" containerTitle="optionsContainer.containerTitle" optionTitleComponents="optionsContainer.optionTitleComponents" headerMiddleButtons="optionsContainer.headerMiddleButtons" isRemovable="optionsContainer.isRemovable" removeDisabledReason="optionsContainer.removeDisabledReason" isClonable="optionsContainer.isClonable" cloneDisabledReason="optionsContainer.cloneDisabledReason" containerTopButtons="optionsContainer.optionsContainerTopButtons"/>
                </t>
            </div>
        </t>
    </div>
</t>

`);
registerTemplate("html_builder.InvisibleElementsPanel", `/html_builder/static/src/sidebar/invisible_elements_panel.xml`, `<t t-name="html_builder.InvisibleElementsPanel" xml:space="preserve">
    <div class="o_we_invisible_el_panel d-contents" t-if="state.invisibleEntries.length">
        <div class="o_panel_header">
            Invisible Elements
        </div>
        <t t-foreach="state.invisibleEntries" t-as="invisibleEntry" t-key="invisibleEntry_index">
            <t t-call="html_builder.invisibleSnippetEntry" t-call-context="{'entry': invisibleEntry, 'toggleElementVisibility': toggleElementVisibility.bind(this)}"/>
        </t>
    </div>
</t>

`);
registerTemplate("html_builder.invisibleSnippetEntry", `/html_builder/static/src/sidebar/invisible_elements_panel.xml`, `<t t-name="html_builder.invisibleSnippetEntry" xml:space="preserve">
    <div class="o_we_invisible_entry d-flex py-1 align-items-center justify-content-between" t-att-class="{'o_we_invisible_root_parent': entry.isRootParent, 'o_we_sublevel_1': entry.isDescendant}" t-on-click="() =&gt; toggleElementVisibility(entry)">
        <div class="o_title" t-out="entry.name"/>
        <i class="fa ms-2" t-att-class="entry.isVisible ? 'fa-eye' : 'fa-eye-slash'"/>
    </div>
    <ul t-if="entry.isVisible and entry.children.length &gt; 0">
        <t t-foreach="entry.children" t-as="child" t-key="child_index">
            <li>
                <t t-call="html_builder.invisibleSnippetEntry" t-call-context="{'entry': child, toggleElementVisibility}"/>
            </li>
        </t>
    </ul>
</t>

`);
registerTemplate("html_builder.OptionsContainer", `/html_builder/static/src/sidebar/option_container.xml`, `<t t-name="html_builder.OptionsContainer" xml:space="preserve">
    <div t-if="props.options.length" class="options-container mb-1" t-ref="root" t-att-data-container-title="title" t-on-pointerenter="onPointerEnter" t-on-pointerleave="onPointerLeave">
        <div class="options-container-header d-flex align-items-center justify-content-between">
            <t t-set="isActionable" t-value="Object.keys(props.snippetModel).length &gt; 0"/>
            <span class="options-container-label ps-2 py-2" t-att-class="{                     'options-container-label-actionable cursor-pointer': isActionable,                 }" t-out="title" t-att-role="isActionable ? 'button' : 'heading'" t-on-click="selectElement"/>
            <t t-if="props.optionTitleComponents" t-foreach="props.optionTitleComponents" t-as="optionTitleComponent" t-key="optionTitleComponent.id">
                <t t-component="optionTitleComponent.Component" t-props="optionTitleComponent.props || {}"/>
            </t>
            <span class="flex-grow-1"/>

            <div class="d-flex align-items-center gap-1 p-2">
                <div t-if="props.headerMiddleButtons">
                    <t t-foreach="props.headerMiddleButtons" t-as="headerMiddleButton" t-key="headerMiddleButton.id">
                        <BuilderContext applyTo="headerMiddleButton.applyTo">
                            <t t-if="headerMiddleButton.Component" t-component="headerMiddleButton.Component" t-props="headerMiddleButton.props || {}"/>
                            <t t-else="" t-call="{{headerMiddleButton.template}}"/>
                        </BuilderContext>
                    </t>
                </div>
                <t t-foreach="props.containerTopButtons" t-as="button" t-key="button_index">
                    <button class="o-hb-btn" t-att-class="button.class" t-att-title="button.title" t-att-aria-label="button.title" t-on-click="() =&gt; button.handler(props.editingElement)"/>
                </t>
                <t t-if="domState.isClonable || domState.cloneDisabledReason">

                    <span t-att-title="domState.cloneDisabledReason" t-att-aria-label="domState.cloneDisabledReason">
	                    <button class="fa fa-fw fa-clone oe_snippet_clone o-hb-btn btn btn-success-color-hover" title="Duplicate this block" aria-label="Duplicate this block" t-att-disabled="!!domState.cloneDisabledReason" t-on-click="cloneElement"/>
	                </span>
                </t>
                <t t-if="domState.isRemovable || domState.removeDisabledReason">

                    <span t-att-title="domState.removeDisabledReason" t-att-aria-label="domState.removeDisabledReason">
	                    <button class="fa fa-fw fa-trash oe_snippet_remove o-hb-btn btn btn-danger-color-hover" title="Remove this block" aria-label="Remove this block" t-att-disabled="!!domState.removeDisabledReason" t-on-click="removeElement"/>
	                </span>
                </t>
            </div>
        </div>
        <div class="we-bg-options-container pb-3" t-ref="content">
            <t t-foreach="props.options" t-as="OptionClass" t-key="OptionClass.name + '-' + OptionClass.template">
                <t t-if="isLegacyOption(OptionClass)">
                    <t t-set="option" t-value="OptionClass"/>
                    <BuilderContext applyTo="option.applyTo" t-if="hasAccess(option.groups)">
                        <t t-if="option.OptionComponent" t-component="option.OptionComponent" t-props="option.props || {}"/>
                        <t t-else="" t-call="{{option.template}}"/>
                    </BuilderContext>
                </t>
                <t t-else="">
                    <BuilderContext applyTo="OptionClass.applyTo" t-if="hasAccess(OptionClass.groups)">
                        <t t-component="OptionClass"/>
                    </BuilderContext>
                </t>
            </t>
        </div>
    </div>
</t>

`);
registerTemplate("html_builder.Snippet", `/html_builder/static/src/sidebar/snippet.xml`, `<t t-name="html_builder.Snippet" xml:space="preserve">
    <div class="o_snippet" t-att-class="{'o_disabled': snippet.isDisabled, 'o_to_install': snippet.isInstallable, 'o_draggable': !snippet.isInstallable and !snippet.isDisabled}" t-att-data-snippet-group="snippet.groupName" t-att-name="snippet.title" t-att-data-id="snippet.id" t-att-data-tooltip="snippet.isDisabled and props.disabledTooltip" t-on-mouseover="onInstallableHover" t-on-mouseout="onInstallableHover">
        <div class="o_snippet_thumbnail" t-att-data-snippet="snippet.name">
            <button t-if="!snippet.isInstallable and !snippet.isDisabled" class="o_snippet_thumbnail_area" t-on-click="props.onClickHandler" title="Insert snippet"/>
            <Img t-if="snippet.isDisabled" src="'/html_builder/static/img/snippet_disabled.svg'" class="'o_snippet_undroppable'"/>
            <div class="o_snippet_thumbnail_img" t-attf-style="background-image: url({{snippet.thumbnailSrc}});"/>
            <span class="o_snippet_thumbnail_title" t-esc="snippet.title"/>
            <button t-if="snippet.isInstallable" class="o_install_btn btn btn-success btn-lg position-absolute start-50 bottom-50 translate-middle-x visually-hidden-focusable z-1" t-on-click="onClickInstall">
                Install
            </button>
        </div>
    </div>
</t>

`);
registerTemplate("html_builder.AddSnippetDialog", `/html_builder/static/src/snippets/add_snippet_dialog.xml`, `<t t-name="html_builder.AddSnippetDialog" xml:space="preserve">
    <Dialog title.translate="Insert a block" contentClass="'o_add_snippet_dialog h-100'" footer="false" size="'xl'" modalRef="modalRef">
        <div class="overflow-hidden w-100">
            <div class="d-flex w-100 h-100 vertical flex-row">
                <aside class="border-end overflow-auto">
                    <div class="d-block position-relative p-2 border-bottom">
                        <input type="search" class="o_add_snippet_dialog_search form-control pe-4" placeholder="Search for a block" aria-label="Search for a block" t-model="state.search"/>
                        <span class="input-group-text position-absolute top-50 end-0 translate-middle-y me-2 border-0 bg-transparent text-muted">
                            <i class="oi oi-search" aria-hidden="true"/>
                        </span>
                    </div>
                    <div class="list-group list-group-flush flex-column flex-nowrap overflow-y-auto" role="tablist" aria-orientation="vertical" aria-label="Block Categories">
                        <t t-if="!state.search" t-foreach="snippetGroups" t-as="snippetGroup" t-key="snippetGroup.id">
                            <t t-set="isActive" t-value="state.groupSelected === snippetGroup.groupName"/>
                            <button class="list-group-item list-group-item-action p-3" role="tab" t-att-class="{ 'active': isActive }" t-att-id="'tab_' + snippetGroup.groupName" t-att-aria-controls="'tabpanel_' + snippetGroup.groupName" t-att-aria-selected="isActive ? 'true' : 'false'" t-att-tabindex="isActive ? '0' : '-1'" t-on-click="() =&gt; this.selectGroup(snippetGroup)" t-on-keydown="onTabKeydown">
                                <t t-out="snippetGroup.title"/>
                            </button>
                        </t>
                    </div>
                </aside>
                <div class="position-relative flex-grow-1 flex-shrink-1">
                    <t t-if="state.hasNoSearchResults">
                        <div class="d-flex flex-column justify-content-center text-center h-100 p-4" role="status">
                            <img src="/web/static/img/smiling_face.svg" alt="No snippets found" class="h-25 mb-3"/>
                            <p class="h2 mb-2">Oops! No snippets found.</p>
                            <p class="h4">Take a look at the search bar, there might be a small typo!</p>
                        </div>
                    </t>
                    <t t-elif="!state.showIframe">
                        <div class="o_add_snippet_dialog_iframe_loader d-flex flex-column justify-content-center text-center h-100 p-4" role="status">
                            <i class="fa fa-3x fa-circle-o-notch fa-spin"/>
                            <p class="h3 mt-3">
                                Almost there! Snippets are incoming, grab a coffee and relax!
                            </p>
                        </div>
                    </t>
                    <iframe class="border-0 fade bg-200 position-relative o_add_snippet_iframe" t-ref="iframe" role="tabpanel" t-att-aria-labelledby="'tab_' + state.groupSelected" t-att-id="'tabpanel_' + state.groupSelected" t-att-class="state.showIframe ? 'show' : '' " src="about:blank" height="333%" width="333%"/>
                </div>
            </div>
        </div>
    </Dialog>
</t>

`);
registerTemplate("html_builder.InputConfirmationDialog", `/html_builder/static/src/snippets/input_confirmation_dialog.xml`, `<t t-name="html_builder.InputConfirmationDialog" xml:space="preserve">
    <Dialog size="'md'" title="props.title" modalRef="modalRef">
        <div class="row">
            <label class="col-form-label col-md-2" for="inputConfirmation" t-esc="props.inputLabel"/>
            <div class="col-md-10">
                <input id="inputConfirmation" type="text" class="form-control" t-model="inputState.value"/>
            </div>
        </div>

        <t t-set-slot="footer">
          <button class="btn" t-att-class="props.confirmClass" t-on-click="_confirm" t-esc="props.confirmLabel" data-hotkey="q"/>
          <button t-if="props.cancel" class="btn btn-secondary" t-on-click="_cancel" t-esc="props.cancelLabel" data-hotkey="x"/>
        </t>
    </Dialog>
</t>

`);
registerTemplate("html_builder.SnippetViewer", `/html_builder/static/src/snippets/snippet_viewer.xml`, `<t t-name="html_builder.SnippetViewer" xml:space="preserve">
    <div t-ref="content" class="row g-0 o_snippets_preview_row" t-att-class="{ 'flex-row-reverse': props.frontendDirection !== backendDirection }" t-att-dir="props.frontendDirection">
        <div class="col-lg-6" t-foreach="this.getSnippetColumns()" t-as="snippetsColumn" t-key="snippetsColumn_index">
            <t t-foreach="snippetsColumn" t-as="snippet" t-key="snippet.id">
                <div t-on-click="() =&gt; this.onClick(snippet)" t-on-keydown="(ev) =&gt; this.onPreviewKeydown(ev, snippet)" t-att-data-snippet-id="snippet.key" t-att-data-label="snippet.label ? snippet.label : ''" t-attf-class="o_snippet_preview_wrap position-relative #{ snippet.isCustom ? 'mb-0' : '' } #{snippet.moduleId ? 'o_snippet_preview_install' : '' }" t-att-tabindex="snippet.moduleId ? '-1' : '0'" t-att-aria-label="snippet.label || snippet.title">
                    <div inert="inert">
                        <div t-if="snippet.imagePreviewSrc" class="s_dialog_preview s_dialog_preview_image">
                            <img t-att-src="snippet.imagePreviewSrc" loading="eager"/>
                        </div>
                        <t t-else="" t-out="this.getContent(snippet.content)"/>
                    </div>
                    <button t-if="snippet.moduleId" class="o_snippet_preview_install_btn btn text-white rounded-1 mx-auto p-2 bottom-50" t-esc="this.getButtonInstallName(snippet)"/>
                </div>
                <div t-if="snippet.isCustom" class="d-grid mt-2 mx-5 gap-2 d-md-flex justify-content-md-end align-items-md-center o_custom_snippet_edit">
                    <span t-foreach="this.getPrefixIcons(snippet.content)" t-as="icon" t-key="icon.keyClass" t-attf-class="me-2 #{icon.keyClass}" t-att-title="icon.title">
                        <span class="visually-hidden" t-out="icon.title"/>
                        <t t-if="icon.Component" t-component="icon.Component" t-props="icon.props"/>
                        <t t-else="" t-out="icon.content"/>
                    </span>
                    <span class="w-100" t-esc="snippet.title"/>
                    <button class="o_btn_reset me-md-2" t-on-click="() =&gt; this.onClickRename(snippet)">
                        <span class="visually-hidden" t-esc="getRenameBtnLabel(snippet.title)"/>
                        <span class="fa fa-pencil"/>
                    </button>
                    <button class="o_btn_reset" t-on-click="() =&gt; this.onClickDelete(snippet)">
                        <span class="visually-hidden" t-esc="getDeleteBtnLabel(snippet.title)"/>
                        <span class="fa fa-trash"/>
                    </button>
                </div>
            </t>
        </div>
    </div>
</t>

`);
registerTemplate("mass_mailing.FontFamilyPicker", `/mass_mailing/static/src/builder/fontfamily_picker.xml`, `<t t-name="mass_mailing.FontFamilyPicker" xml:space="preserve">
        <BuilderSelect className="props.extraClass" action="this.props.action" actionParam="this.props.actionParam">
            <t t-foreach="this.FONT_FAMILIES" t-as="fontFamily" t-key="fontFamily">
                <BuilderSelectItem t-out="fontFamily" actionValue="fontFamily_value"/>
            </t>
        </BuilderSelect>
    </t>
`);
registerTemplate("mass_mailing.MassMailingBuilder", `/mass_mailing/static/src/builder/mass_mailing_builder.xml`, `<t t-name="mass_mailing.MassMailingBuilder" xml:space="preserve">
    <Builder t-props="this.builderProps">
        <t t-set-slot="extraActions">
            <button t-if="props.toggleCodeView" t-on-click="props.toggleCodeView" class="o-hb-btn btn d-flex align-items-center o_codeview_btn" title="Code View" accesskey="d"><i class="fa fa-code"/></button>
            <button t-on-click="props.toggleFullScreen" class="o-hb-btn btn d-flex align-items-center" title="Fullscreen" accesskey="f">
                <span t-attf-class="fa fa-expand"/>
            </button>
        </t>
    </Builder>
</t>

`);
registerTemplate("mass_mailing.AlertOption", `/mass_mailing/static/src/builder/options/alert_option.xml`, `<t t-name="mass_mailing.AlertOption" xml:space="preserve">
        <BuilderRow label.translate="Size">
            <BuilderSelect>
                <BuilderSelectItem classAction="'s_alert_sm'">Small</BuilderSelectItem>
                <BuilderSelectItem classAction="'s_alert_md'">Medium</BuilderSelectItem>
                <BuilderSelectItem classAction="'s_alert_lg'">Large</BuilderSelectItem>
            </BuilderSelect>
        </BuilderRow>
        <BuilderRow label.translate="Background Color">
            <BuilderColorPicker styleAction="'background-color'" enabledTabs="['solid', 'custom']"/>
        </BuilderRow>
    </t>
`);
registerTemplate("mass_mailing.BlockAlignmentOption", `/mass_mailing/static/src/builder/options/alignment_option.xml`, `<t t-name="mass_mailing.BlockAlignmentOption" xml:space="preserve">
    <BuilderRow label.translate="Alignment" t-if="!this.isActiveItem('so_width_100')">
        <BuilderButtonGroup>

            <BuilderButton icon="'fa-align-left'" title.translate="Left" classAction="'me-auto'"/>
            <BuilderButton icon="'fa-align-center'" title.translate="Center" classAction="'mx-auto'"/>
            <BuilderButton icon="'fa-align-right'" title.translate="Right" classAction="'ms-auto'"/>
        </BuilderButtonGroup>
    </BuilderRow>
</t>
`);
registerTemplate("mass_mailing.CustomerTestimonialsBlockquote", `/mass_mailing/static/src/builder/options/blockquote_option.xml`, `<t t-name="mass_mailing.CustomerTestimonialsBlockquote" xml:space="preserve">
        <BuilderRow label.translate="Edge Spacing">
            <BuilderRange action="'setClassRange'" actionParam="['p-1', 'p-2', 'p-3', 'p-4', 'p-5']" max="4"/>
        </BuilderRow>
        <t t-call="mass_mailing.BorderOption"/>
    </t>
`);
registerTemplate("mass_mailing.BorderOption", `/mass_mailing/static/src/builder/options/border_options.xml`, `<t t-name="mass_mailing.BorderOption" xml:space="preserve">
        <BorderConfigurator label.translate="Border" withRoundCorner="this.withRoundCorner"/>
    </t>
`);
registerTemplate("mass_mailing.ColorPickerOption", `/mass_mailing/static/src/builder/options/color_picker_option.xml`, `<t t-name="mass_mailing.ColorPickerOption" xml:space="preserve">
     <BuilderRow label.translate="Background Color">
        <BuilderColorPicker styleAction="'background-color'" noTransparency="true" enabledTabs="['solid', 'custom']"/>
    </BuilderRow>
</t>
`);
registerTemplate("mass_mailing.CompanyTeamShapesWidth", `/mass_mailing/static/src/builder/options/company_team_options.xml`, `<t t-name="mass_mailing.CompanyTeamShapesWidth" xml:space="preserve">
        <BuilderRow label.translate="Content Width" applyTo="'div:is(.o_container_small, .container, .container-fluid)'">
            <BuilderButtonGroup action="'classAction'">
                <BuilderButton actionParam="'o_container_small'"><Img src="'/mass_mailing/static/src/img/snippets_options/content_width_small.svg'"/></BuilderButton>
                <BuilderButton actionParam="'container'"><Img src="'/mass_mailing/static/src/img/snippets_options/content_width_normal.svg'"/></BuilderButton>
                <BuilderButton actionParam="'container-fluid'"><Img src="'/mass_mailing/static/src/img/snippets_options/content_width_full.svg'"/></BuilderButton>
            </BuilderButtonGroup>
        </BuilderRow>
    </t>
`);
registerTemplate("mass_mailing.CTABadgeOption", `/mass_mailing/static/src/builder/options/cta_badge_option.xml`, `<t t-name="mass_mailing.CTABadgeOption" xml:space="preserve">
        <t t-call="mass_mailing.BlockAlignmentOption"/>
        <t t-call="mass_mailing.BorderOption"/>
    </t>
`);
registerTemplate("mass_mailing.ImageAndFaOption", `/mass_mailing/static/src/builder/options/image_tool_option.xml`, `<t t-name="mass_mailing.ImageAndFaOption" xml:space="preserve">
        <t t-call="mass_mailing.BorderOption"/>
        <t t-call="mass_mailing.HorizontalPaddingOption"/>
        <t t-call="mass_mailing.VerticalPaddingOption"/>
    </t>
    `);
registerTemplate("mass_mailing.ImageToolOption", `/mass_mailing/static/src/builder/options/image_tool_option.xml`, `<t t-name="mass_mailing.ImageToolOption" t-inherit="html_builder.ImageToolOption" xml:space="preserve">
        <xpath expr="//ImageShapeOption" position="attributes">
            <attribute name="withAnimatedShapes">false</attribute>
        </xpath>
        <xpath expr="//ImageTransformOption" position="replace"/>
        <xpath expr="//BuilderRow[@label.translate=&quot;Size&quot;]" position="attributes">
            <attribute name="t-if">massMailingState.isImgFluid</attribute>
        </xpath>
    </t>
    `);
registerTemplate("mass_mailing.FontAwesomeOption", `/mass_mailing/static/src/builder/options/image_tool_option.xml`, `<t t-name="mass_mailing.FontAwesomeOption" xml:space="preserve">
        <BuilderRow label.translate="Color">
            <BuilderColorPicker styleAction="'color'" enabledTabs="['custom', 'solid']"/>
        </BuilderRow>

        <BuilderRow label.translate="Background Color">
            <BuilderColorPicker styleAction="'background-color'" enabledTabs="['custom', 'solid']"/>
        </BuilderRow>

        <BuilderRow label.translate="Size">
            <BuilderButtonGroup>
                <BuilderButton classAction="''" title.translate="Default">1X</BuilderButton>
                <BuilderButton classAction="'fa-2x'" title.translate="2X Size">2X</BuilderButton>
                <BuilderButton classAction="'fa-3x'" title.translate="3X Size">3X</BuilderButton>
                <BuilderButton classAction="'fa-4x'" title.translate="4X Size">4X</BuilderButton>
                <BuilderButton classAction="'fa-5x'" title.translate="5X Size">5X</BuilderButton>
            </BuilderButtonGroup>
        </BuilderRow>
    </t>
`);
registerTemplate("mass_mailing.MasonryBlockTemplateOption", `/mass_mailing/static/src/builder/options/masonry_block_template_option.xml`, `<t t-name="mass_mailing.MasonryBlockTemplateOption" xml:space="preserve">
    <BuilderRow label.translate="Template">
        <BuilderSelect id="'masonry_template_opt'" action="'changeMasonryTemplate'">
            <BuilderSelectItem title.translate="Default" actionValue="'default_template'"><img src="/mass_mailing/static/src/img/snippets_options/masonry_template_default.svg"/></BuilderSelectItem>
            <BuilderSelectItem title.translate="Default Reversed" actionValue="'reversed_template'"><img src="/mass_mailing/static/src/img/snippets_options/masonry_template_reversed.svg"/></BuilderSelectItem>
            <BuilderSelectItem title.translate="Images" actionValue="'images_template'"><img src="/mass_mailing/static/src/img/snippets_options/masonry_template_images.svg"/></BuilderSelectItem>
            <BuilderSelectItem title.translate="Image Text Image" actionValue="'image_texts_image_template'"><img src="/mass_mailing/static/src/img/snippets_options/masonry_template_image_texts_image.svg"/></BuilderSelectItem>
            <BuilderSelectItem title.translate="Mosaic" actionValue="'mosaic_template'"><img src="/mass_mailing/static/src/img/snippets_options/masonry_template_mosaic.svg"/></BuilderSelectItem>
            <BuilderSelectItem title.translate="Text Image Text" actionValue="'texts_image_texts_template'"><img src="/mass_mailing/static/src/img/snippets_options/masonry_template_texts_image_texts.svg"/></BuilderSelectItem>
            <BuilderSelectItem title.translate="Alternate Text" actionValue="'alternation_text_template'"><img src="/mass_mailing/static/src/img/snippets_options/masonry_template_alternate_texts.svg"/></BuilderSelectItem>
            <BuilderSelectItem title.translate="Alternate Text Image" actionValue="'alternation_text_image_template'"><img src="/mass_mailing/static/src/img/snippets_options/masonry_template_alternate_text_image.svg"/></BuilderSelectItem>
            <BuilderSelectItem title.translate="Alternate Image Text" actionValue="'alternation_image_text_template'"><img src="/mass_mailing/static/src/img/snippets_options/masonry_template_alternate_image_text.svg"/></BuilderSelectItem>
            <BuilderSelectItem title.translate="Alternate Text Image Text" actionValue="'alternation_text_image_text_template'"><img src="/mass_mailing/static/src/img/snippets_options/masonry_template_alternate_text_image_text.svg"/></BuilderSelectItem>
        </BuilderSelect>
    </BuilderRow>
    </t>
    `);
registerTemplate("mass_mailing.s_masonry_block_default_template", `/mass_mailing/static/src/builder/options/masonry_block_template_option.xml`, `<t t-name="mass_mailing.s_masonry_block_default_template" xml:space="preserve">
        <div class="row">
            <div class="col-md-6 col-12 oe_img_bg text-center pb224 pt224" data-name="Block" style="background-image: url(/web/image/mass_mailing.s_masonry_block_default_image_1);">
                <p><br/></p>
            </div>
            <div class="col-md-6 col-12 s_col_no_resize o_masonry_grid_container">
                <div class="row h-100">
                    <div class="col-md-6 col-12 pt24 pb8 text-center o_cc" data-name="Block">
                        <h3>A great title</h3>
                        <p>And a great subtitle</p>
                    </div>
                    <div class="col-md-6 col-12 pt24 pb8 text-center o_cc o_cc3" data-name="Block">
                        <h3>A great title</h3>
                        <p>And a great subtitle</p>
                    </div>
                    <div class="col-md-6 col-12 pt24 pb8 text-center o_cc o_cc4" data-name="Block">
                        <h3><font style="color: white">A great title</font></h3>
                        <p><font style="color: white">And a great subtitle</font></p>
                    </div>
                    <div class="col-md-6 col-12 pt24 pb8 text-center o_cc" data-name="Block">
                        <h3>A great title</h3>
                        <p>And a great subtitle</p>
                    </div>
                </div>
            </div>
        </div>
    </t>

    `);
registerTemplate("mass_mailing.s_masonry_block_reversed_template", `/mass_mailing/static/src/builder/options/masonry_block_template_option.xml`, `<t t-name="mass_mailing.s_masonry_block_reversed_template" xml:space="preserve">
        <div class="row">
            <div class="col-md-6 col-12 s_col_no_resize o_masonry_grid_container">
                <div class="row h-100">
                    <div class="col-md-6 col-12 pt24 pb8 text-center o_cc o_cc3" data-name="Block">
                        <h3>A great title</h3>
                        <p>And a great subtitle</p>
                    </div>
                    <div class="col-md-6 col-12 pt24 pb8 text-center o_cc" data-name="Block">
                        <h3>A great title</h3>
                        <p>And a great subtitle</p>
                    </div>
                    <div class="col-md-6 col-12 pt24 pb8 text-center o_cc" data-name="Block">
                        <h3>A great title</h3>
                        <p>And a great subtitle</p>
                    </div>
                    <div class="col-md-6 col-12 pt24 pb8 text-center o_cc o_cc4" data-name="Block">
                        <h3><font style="color: white">A great title</font></h3>
                        <p><font style="color: white">And a great subtitle</font></p>
                    </div>
                </div>
            </div>
            <div class="col-md-6 col-12 oe_img_bg text-center pb224 pt224" data-name="Block" style="background-image: url(/web/image/mass_mailing.s_masonry_block_default_image_1);">
                <p><br/></p>
            </div>
        </div>
    </t>

    `);
registerTemplate("mass_mailing.s_masonry_block_images_template", `/mass_mailing/static/src/builder/options/masonry_block_template_option.xml`, `<t t-name="mass_mailing.s_masonry_block_images_template" xml:space="preserve">
        <div class="row">
            <div class="col-md-6 col-12 oe_img_bg text-center pb224 pt224" data-name="Block" style="background-image: url(/web/image/mass_mailing.s_masonry_block_default_image_1);">
                <p><br/></p>
            </div>
            <div class="col-md-6 col-12 oe_img_bg text-center pb224 pt224" data-name="Block" style="background-image: url(/web/image/mass_mailing.s_masonry_block_default_image_2);">
                <p><br/></p>
            </div>
        </div>
    </t>

    `);
registerTemplate("mass_mailing.s_masonry_block_image_texts_image_template", `/mass_mailing/static/src/builder/options/masonry_block_template_option.xml`, `<t t-name="mass_mailing.s_masonry_block_image_texts_image_template" xml:space="preserve">
        <div class="row">
            <div class="col-md-3 col-12 oe_img_bg text-center pt224 pb224" data-name="Block" style="background-image: url(/web/image/mass_mailing.s_masonry_block_default_image_2);">
                <p><br/></p>
            </div>
            <div class="col-md-3 col-12 s_col_no_resize o_masonry_grid_container">
                <div class="row h-100">
                    <div class="col-md-12 col-12 pt24 pb8 text-center o_cc" data-name="Block">
                        <h3>A great title</h3>
                        <p>And a great subtitle</p>
                    </div>
                    <div class="col-md-12 col-12 pt24 pb8 text-center o_cc o_cc4" data-name="Block">
                        <h3><font style="color: white">A great title</font></h3>
                        <p><font style="color: white">And a great subtitle</font></p>
                    </div>
                </div>
            </div>
            <div class="col-md-6 col-12 oe_img_bg text-center pt224 pb224" data-name="Block" style="background-image: url(/web/image/mass_mailing.s_masonry_block_default_image_1);">
                <p><br/></p>
            </div>
        </div>
    </t>

    `);
registerTemplate("mass_mailing.s_masonry_block_mosaic_template", `/mass_mailing/static/src/builder/options/masonry_block_template_option.xml`, `<t t-name="mass_mailing.s_masonry_block_mosaic_template" xml:space="preserve">
        <div class="row">
            <div class="col-md-6 col-12 s_col_no_resize o_masonry_grid_container">
                <div class="row">
                    <div class="col-md-6 col-12 pt24 pb8 text-center o_cc o_cc3" data-name="Block">
                        <h3>A great title</h3>
                        <p>And a great subtitle</p>
                    </div>
                    <div class="col-md-6 col-12 pt24 pb8 text-center o_cc" data-name="Block">
                        <h3>A great title</h3>
                        <p>And a great subtitle</p>
                    </div>
                </div>
                <div class="row">
                    <div class="col-md-12 col-12 oe_img_bg text-center pt224 pb224" data-name="Block" style="background-image: url(/web/image/mass_mailing.s_masonry_block_default_image_1);">
                        <p><br/></p>
                    </div>
                </div>
            </div>
            <div class="col-md-6 col-12 s_col_no_resize o_masonry_grid_container">
                <div class="row">
                    <div class="col-md-12 col-12 oe_img_bg text-center pt224 pb224" data-name="Block" style="background-image: url(/web/image/mass_mailing.s_masonry_block_default_image_2);">
                        <p><br/></p>
                    </div>
                </div>
                <div class="row">
                    <div class="col-md-6 col-12 pt24 pb8 text-center o_cc" data-name="Block">
                        <h3>A great title</h3>
                        <p>And a great subtitle</p>
                    </div>
                    <div class="col-md-6 col-12 pt24 pb8 text-center o_cc o_cc4" data-name="Block">
                        <h3><font style="color: white">A great title</font></h3>
                        <p><font style="color: white">And a great subtitle</font></p>
                    </div>
                </div>
            </div>
        </div>
    </t>

    `);
registerTemplate("mass_mailing.s_masonry_block_texts_image_texts_template", `/mass_mailing/static/src/builder/options/masonry_block_template_option.xml`, `<t t-name="mass_mailing.s_masonry_block_texts_image_texts_template" xml:space="preserve">
        <div class="row">
            <div class="col-md-3 col-12 s_col_no_resize o_masonry_grid_container">
                <div class="row h-100">
                    <div class="col-md-12 col-12 pt24 pb8 text-center o_cc o_cc3" data-name="Block">
                        <h3>A great title</h3>
                        <p>And a great subtitle</p>
                    </div>
                    <div class="col-md-12 col-12 pt24 pb8 text-center o_cc" data-name="Block">
                        <h3>A great title</h3>
                        <p>And a great subtitle</p>
                    </div>
                </div>
            </div>
            <div class="col-md-6 col-12 oe_img_bg text-center pt224 pb224" data-name="Block" style="background-image: url(/web/image/mass_mailing.s_masonry_block_default_image_1);">
                <p><br/></p>
            </div>
            <div class="col-md-3 col-12 s_col_no_resize o_masonry_grid_container">
                <div class="row h-100">
                    <div class="col-md-12 col-12 pt24 pb8 text-center o_cc" data-name="Block">
                        <h3>A great title</h3>
                        <p>And a great subtitle</p>
                    </div>
                    <div class="col-md-12 col-12 pt24 pb8 text-center o_cc o_cc4" data-name="Block">
                        <h3><font style="color: white">A great title</font></h3>
                        <p><font style="color: white">And a great subtitle</font></p>
                    </div>
                </div>
            </div>
        </div>
    </t>

    `);
registerTemplate("mass_mailing.s_masonry_block_alternation_text_template", `/mass_mailing/static/src/builder/options/masonry_block_template_option.xml`, `<t t-name="mass_mailing.s_masonry_block_alternation_text_template" xml:space="preserve">
        <div class="row">
            <div class="col-md-3 col-12 pt24 pb8 text-center o_cc" data-name="Block">
                <h3>A great title</h3>
                <p>And a great subtitle</p>
            </div>
            <div class="col-md-3 col-12 pt24 pb8 text-center o_cc o_cc4" data-name="Block">
                <h3><font style="color: white">A great title</font></h3>
                <p><font style="color: white">And a great subtitle</font></p>
            </div>
            <div class="col-md-3 col-12 pt24 pb8 text-center o_cc" data-name="Block">
                <h3>A great title</h3>
                <p>And a great subtitle</p>
            </div>
            <div class="col-md-3 col-12 pt24 pb8 text-center o_cc o_cc3" data-name="Block">
                <h3>A great title</h3>
                <p>And a great subtitle</p>
            </div>
        </div>
    </t>

    `);
registerTemplate("mass_mailing.s_masonry_block_alternation_text_image_template", `/mass_mailing/static/src/builder/options/masonry_block_template_option.xml`, `<t t-name="mass_mailing.s_masonry_block_alternation_text_image_template" xml:space="preserve">
        <div class="row">
            <div class="col-md-3 col-12 pt24 pb8 text-center o_cc" data-name="Block">
                <h3>A great title</h3>
                <p>And a great subtitle</p>
            </div>
            <div class="col-md-3 col-12 oe_img_bg text-center pt224 pb224" data-name="Block" style="background-image: url(/web/image/mass_mailing.s_masonry_block_default_image_1);">
                <p><br/></p>
            </div>
            <div class="col-md-3 col-12 pt24 pb8 text-center o_cc" data-name="Block">
                <h3>A great title</h3>
                <p>And a great subtitle</p>
            </div>
            <div class="col-md-3 col-12 oe_img_bg text-center pt224 pb224" data-name="Block" style="background-image: url(/web/image/mass_mailing.s_masonry_block_default_image_2);">
                <p><br/></p>
            </div>
        </div>
    </t>

    `);
registerTemplate("mass_mailing.s_masonry_block_alternation_image_text_template", `/mass_mailing/static/src/builder/options/masonry_block_template_option.xml`, `<t t-name="mass_mailing.s_masonry_block_alternation_image_text_template" xml:space="preserve">
        <div class="row">
            <div class="col-md-3 col-12 oe_img_bg text-center pt224 pb224" data-name="Block" style="background-image: url(/web/image/mass_mailing.s_masonry_block_default_image_1);">
                <p><br/></p>
            </div>
            <div class="col-md-3 col-12 pt24 pb8 text-center o_cc o_cc4" data-name="Block">
                <h3><font style="color: white">A great title</font></h3>
                <p><font style="color: white">And a great subtitle</font></p>
            </div>
            <div class="col-md-3 col-12 oe_img_bg text-center pt224 pb224" data-name="Block" style="background-image: url(/web/image/mass_mailing.s_masonry_block_default_image_2);">
                <p><br/></p>
            </div>
            <div class="col-md-3 col-12 pt24 pb8 text-center o_cc o_cc3" data-name="Block">
                <h3>A great title</h3>
                <p>And a great subtitle</p>
            </div>
        </div>
    </t>

    `);
registerTemplate("mass_mailing.s_masonry_block_alternation_text_image_text_template", `/mass_mailing/static/src/builder/options/masonry_block_template_option.xml`, `<t t-name="mass_mailing.s_masonry_block_alternation_text_image_text_template" xml:space="preserve">
        <div class="row">
            <div class="col-md-3 col-12 pt24 pb8 text-center o_cc" data-name="Block">
                <h3>A great title</h3>
                <p>And a great subtitle</p>
            </div>
            <div class="col-md-6 col-12 oe_img_bg text-center pt224 pb224" data-name="Block" style="background-image: url(/web/image/mass_mailing.s_masonry_block_default_image_1);">
                <p><br/></p>
            </div>
            <div class="col-md-3 col-12 pt24 pb8 text-center o_cc" data-name="Block">
                <h3>A great title</h3>
                <p>And a great subtitle</p>
            </div>
        </div>
    </t>
`);
registerTemplate("mass_mailing.OptionsContainer", `/mass_mailing/static/src/builder/options/options_container.xml`, `<t t-name="mass_mailing.OptionsContainer" t-inherit="html_builder.OptionsContainer" xml:space="preserve">
        <xpath expr="//div[@t-ref='content']" position="replace">
            <t t-if="versionState.isUpToDate">
                <div class="we-bg-options-container pb-3" t-ref="content">
                    <t t-foreach="props.options" t-as="OptionClass" t-key="OptionClass.name + '-' + OptionClass.template">
                        <BuilderContext applyTo="OptionClass.applyTo" t-if="hasAccess(OptionClass.groups)">
                            <t t-component="OptionClass"/>
                        </BuilderContext>
                    </t>
                </div>
            </t>
            <t t-else="">
                <div class="o_we_version_control d-flex flex-column p-3 pt-4 align-items-center text-center text-white">
                    <div class="title">This block is outdated.</div>
                    <div>You might not be able to customize it anymore.</div>
                    <button type="button" class="btn btn-primary py-2 my-4 border-0" t-on-click="() =&gt; this.replaceElementWithNewVersion()">REPLACE BY NEW VERSION</button>
                    <div>You can still access the block options but it might be ineffective.</div>
                    <button type="button" class="btn btn-primary py-2 my-4 border-0" t-on-click="() =&gt; this.accessOutdated()">ACCESS OPTIONS ANYWAY</button>
                </div>
            </t>
        </xpath>
    </t>
`);
registerTemplate("mass_mailing.HorizontalPaddingOption", `/mass_mailing/static/src/builder/options/padding_option.xml`, `<t t-name="mass_mailing.HorizontalPaddingOption" xml:space="preserve">
        <BuilderRow label.translate="Padding ↔">
            <BuilderNumberInput title.translate="Left" styleAction="'padding-left'" unit="'px'"/>
            <BuilderNumberInput title.translate="Right" styleAction="'padding-right'" unit="'px'"/>
        </BuilderRow>
    </t>
    `);
registerTemplate("mass_mailing.VerticalPaddingOption", `/mass_mailing/static/src/builder/options/padding_option.xml`, `<t t-name="mass_mailing.VerticalPaddingOption" xml:space="preserve">
        <BuilderRow label.translate="Padding ↕">
            <BuilderNumberInput title.translate="Top" styleAction="'padding-top'" unit="'px'"/>
            <BuilderNumberInput title.translate="Bottom" styleAction="'padding-bottom'" unit="'px'"/>
        </BuilderRow>
    </t>
`);
registerTemplate("mass_mailing.VisibilityOption", `/mass_mailing/static/src/builder/options/snippet_visibility_option.xml`, `<t t-name="mass_mailing.VisibilityOption" xml:space="preserve">
        <BuilderRow label.translate="Visibility">
            <BuilderSelect action="'dataAttributeChangeAction'" actionParam="'filterDomain'">
                <BuilderSelectItem actionValue="''">Always Visible</BuilderSelectItem>
                <BuilderSelectItem actionValue="this.stringifiedDomain" id="'show_domain_selector'">Conditionally</BuilderSelectItem>
            </BuilderSelect>
        </BuilderRow>
        <BuilderContext t-if="this.isActiveItem('show_domain_selector')">
            <BuilderRow level="1" label.translate="Domain" extraLabelClass="'align-self-end'">
                <div t-if="this.state.facets?.length" class="d-flex flex-column">
                    <div class="d-inline-flex align-items-center pt-1" t-foreach="this.state.facets" t-as="facet" t-key="facet_index">
                        <span class="fa fa-filter pe-1"/>
                        <span t-out="facet"/>
                    </div>
                </div>
                <button t-else="" class="btn btn-secondary me-auto mt-1" t-on-click="this.onClickEditDomain">
                    Edit Conditions
                </button>
            </BuilderRow>

            <BuilderRow t-if="this.state.facets?.length" label.translate=" ">
                <button class="btn btn-secondary me-auto mt-1" t-on-click="this.onClickEditDomain">
                    Add Conditions
                </button>
            </BuilderRow>
        </BuilderContext>
    </t>
`);
registerTemplate("mass_mailing.DesignTab", `/mass_mailing/static/src/builder/tabs/design_tab.xml`, `<t t-name="mass_mailing.DesignTab" xml:space="preserve">
    <div class="o_design_tab h-100">
        <div t-ref="content" class="d-flex flex-column h-100">
            <t t-foreach="optionsContainers" t-as="optionsContainer" t-key="optionsContainer.id">

                <OptionsContainer snippetModel="optionsContainer.snippetModel" editingElement="optionsContainer.element" options="optionsContainer.options" containerTitle="optionsContainer.containerTitle" headerMiddleButtons="optionsContainer.headerMiddleButtons" isRemovable="optionsContainer.isRemovable" isClonable="optionsContainer.isClonable" containerTopButtons="optionsContainer.optionsContainerTopButtons"/>
            </t>
        </div>
    </div>
</t>

`);
registerTemplate("mass_mailing.DesignBodyOption", `/mass_mailing/static/src/builder/tabs/design_tab.xml`, `<t t-name="mass_mailing.DesignBodyOption" xml:space="preserve">
    <BuilderRow label.translate="Body Width">
        <BuilderButtonGroup>
            <BuilderButton classAction="'o_mail_small'" applyTo="'.o_mail_wrapper'">
                <Img src="'/mass_mailing/static/src/img/snippets_options/content_width_small.svg'"/>
            </BuilderButton>
            <BuilderButton classAction="'o_mail_regular'" applyTo="'.o_mail_wrapper'">
                <Img src="'/mass_mailing/static/src/img/snippets_options/content_width_normal.svg'"/>
            </BuilderButton>
            <BuilderButton classAction="''" applyTo="'.o_mail_wrapper'">
                <Img src="'/mass_mailing/static/src/img/snippets_options/content_width_full.svg'"/>
            </BuilderButton>
        </BuilderButtonGroup>
    </BuilderRow>
    <BuilderRow label.translate="Mailing Background" extraLabelClass="'pe-2'">
        <BuilderColorPicker noTransparency="true" enabledTabs="['solid', 'custom']" styleAction="'background-color'" applyTo="'.o_layout'"/>
    </BuilderRow>
    <BuilderRow label.translate="Content Background" extraLabelClass="'pe-2'">
        <BuilderColorPicker noTransparency="true" enabledTabs="['solid', 'custom']" action="'mass_mailing.CustomizeMailingVariable'" actionParam="{ variable: '--wrapper-background-color' }"/>
    </BuilderRow>
</t>

`);
registerTemplate("mass_mailing.DesignHeadingsOption", `/mass_mailing/static/src/builder/tabs/design_tab.xml`, `<t t-name="mass_mailing.DesignHeadingsOption" xml:space="preserve">
    <t t-call="mass_mailing.DesignTextOption">
        <t t-set="label">Heading 1</t>
        <t t-set="prefix" t-value="\`--h1-\`"/>
        <t t-set="marginPrefix" t-value="prefix"/>
    </t>
    <t t-call="mass_mailing.DesignTextOption">
        <t t-set="label">Heading 2</t>
        <t t-set="prefix" t-value="\`--h2-\`"/>
        <t t-set="marginPrefix" t-value="prefix"/>
    </t>
    <t t-call="mass_mailing.DesignTextOption">
        <t t-set="label">Heading 3</t>
        <t t-set="prefix" t-value="\`--h3-\`"/>
        <t t-set="marginPrefix" t-value="prefix"/>
    </t>
</t>

`);
registerTemplate("mass_mailing.DesignParagraphOption", `/mass_mailing/static/src/builder/tabs/design_tab.xml`, `<t t-name="mass_mailing.DesignParagraphOption" xml:space="preserve">
    <t t-call="mass_mailing.DesignTextOption">
        <t t-set="label">Text</t>
        <t t-set="prefix" t-value="\`--text-\`"/>
        <t t-set="marginPrefix" t-value="\`--text-container-\`"/>
    </t>
</t>

`);
registerTemplate("mass_mailing.DesignLinkOption", `/mass_mailing/static/src/builder/tabs/design_tab.xml`, `<t t-name="mass_mailing.DesignLinkOption" xml:space="preserve">
    <t t-call="mass_mailing.DesignTextOption">
        <t t-set="label">Links</t>
        <t t-set="prefix" t-value="\`--link-\`"/>
    </t>
</t>

`);
registerTemplate("mass_mailing.DesignTextOption", `/mass_mailing/static/src/builder/tabs/design_tab.xml`, `<t t-name="mass_mailing.DesignTextOption" xml:space="preserve">
    <BuilderContext action="'mass_mailing.CustomizeMailingVariable'">
        <BuilderRow label="label" extraLabelClass="'fw-bolder'">
            <BuilderNumberInput actionParam="{ variable: \`\${prefix}font-size\` }" unit="'px'" saveUnit="'px'" default="0"/>
            <BuilderColorPicker noTransparency="true" title.translate="Text Color" enabledTabs="['solid', 'custom']" actionParam="{ variable: \`\${prefix}color\` }"/>
        </BuilderRow>
        <BuilderRow t-if="marginPrefix" label.translate="Margin" level="1">
            <BuilderNumberInput title.translate="Bottom" unit="'px'" saveUnit="'px'" actionParam="{ variable: \`\${marginPrefix}margin-bottom\` }" default="0"/>
        </BuilderRow>
        <BuilderRow>
            <FontFamilyPicker extraClass="'ps-2'" action="'mass_mailing.CustomizeMailingVariable'" actionParam="{variable: \`\${prefix}font-family\`}"/>
            <BuilderButton icon="'fa-fw fa-bold'" actionParam="{ variable: \`\${prefix}font-weight\` }" actionValue="'bolder'"/>
            <BuilderButton icon="'fa-fw fa-italic'" actionParam="{ variable: \`\${prefix}font-style\` }" actionValue="'italic'"/>
            <BuilderButton icon="'fa-fw fa-underline'" actionParam="{ variable: \`\${prefix}text-decoration-line\`}" actionValue="'underline'"/>
        </BuilderRow>
    </BuilderContext>
</t>

`);
registerTemplate("mass_mailing.DesignGenericButtonOption", `/mass_mailing/static/src/builder/tabs/design_tab.xml`, `<t t-name="mass_mailing.DesignGenericButtonOption" xml:space="preserve">
    <BuilderContext action="'mass_mailing.CustomizeMailingVariable'">
        <BuilderRow label="label" extraLabelClass="'fw-bolder'">
            <BuilderNumberInput actionParam="{ variable: \`\${prefix}font-size\` }" unit="'px'" saveUnit="'px'" default="0"/>
            <BuilderColorPicker noTransparency="true" title.translate="Text Color" enabledTabs="['solid', 'custom']" actionParam="{ variable: \`\${prefix}color\` }"/>
            <BuilderColorPicker noTransparency="true" title.translate="Background Color" enabledTabs="['solid', 'custom']" actionParam="{ variable: \`\${prefix}background-color\` }"/>
        </BuilderRow>
        <BuilderRow label.translate="Padding" level="1">
            <BuilderNumberInput title.translate="Y" unit="'px'" saveUnit="'px'" actionParam="{ variable: \`\${prefix}padding-y\` }" default="0"/>
            <BuilderNumberInput title.translate="X" unit="'px'" saveUnit="'px'" actionParam="{ variable: \`\${prefix}padding-x\` }" default="0"/>
        </BuilderRow>
        <BuilderRow label.translate="Font Family" level="1">
            <FontFamilyPicker action="'mass_mailing.CustomizeMailingVariable'" actionParam="{ variable: \`\${prefix}font-family\`}"/>
            <BuilderButton icon="'fa-fw fa-bold'" actionParam="{ variable: \`\${prefix}font-weight\` }" actionValue="'bolder'"/>
            <BuilderButton icon="'fa-fw fa-italic'" actionParam="{ variable: \`\${prefix}font-style\` }" actionValue="'italic'"/>
            <BuilderButton icon="'fa-fw fa-underline'" actionParam="{ variable: \`\${prefix}text-decoration-line\`}" actionValue="'underline'"/>
        </BuilderRow>
        <BuilderRow label.translate="Border" level="1">
            <BuilderNumberInput actionParam="{ variable: \`\${prefix}border-width\` }" unit="'px'" saveUnit="'px'" min="0" default="0" composable="true"/>
            <BuilderSelect actionParam="{ variable: \`\${prefix}border-style\` }">
                <BuilderSelectItem title.translate="Solid" actionValue="'solid'"><div class="o-hb-border-preview" style="border-style: solid;"/></BuilderSelectItem>
                <BuilderSelectItem title.translate="Dashed" actionValue="'dashed'"><div class="o-hb-border-preview" style="border-style: dashed;"/></BuilderSelectItem>
                <BuilderSelectItem title.translate="Dotted" actionValue="'dotted'"><div class="o-hb-border-preview" style="border-style: dotted;"/></BuilderSelectItem>
                <BuilderSelectItem title.translate="Double" actionValue="'double'"><div class="o-hb-border-preview" style="border-style: double;"/></BuilderSelectItem>
            </BuilderSelect>
            <BuilderColorPicker actionParam="{ variable: \`\${prefix}border-color\` }" noTransparency="true" enabledTabs="['solid', 'custom']"/>
        </BuilderRow>
    </BuilderContext>
</t>

`);
registerTemplate("mass_mailing.DesignButtonOption", `/mass_mailing/static/src/builder/tabs/design_tab.xml`, `<t t-name="mass_mailing.DesignButtonOption" xml:space="preserve">
    <t t-call="mass_mailing.DesignGenericButtonOption">
        <t t-set="prefix" t-value="\`--btn-primary-\`"/>
        <t t-set="label">Primary Button</t>
    </t>
    <t t-call="mass_mailing.DesignGenericButtonOption">
        <t t-set="prefix" t-value="\`--btn-secondary-\`"/>
        <t t-set="label">Secondary Button</t>
    </t>
</t>

`);
registerTemplate("mass_mailing.DesignSeparatorOption", `/mass_mailing/static/src/builder/tabs/design_tab.xml`, `<t t-name="mass_mailing.DesignSeparatorOption" xml:space="preserve">
    <t t-set="prefix" t-value="\`--separator-\`"/>
    <BuilderContext action="'mass_mailing.CustomizeMailingVariable'">
        <BuilderRow label.translate="Separators" extraLabelClass="'fw-bolder'">
            <BuilderNumberInput actionParam="{ variable: \`\${prefix}border-top-width\` }" unit="'px'" saveUnit="'px'" min="0" default="0" composable="true"/>
            <BuilderSelect actionParam="{ variable: \`\${prefix}border-style\` }">
                <BuilderSelectItem title.translate="Solid" actionValue="'solid'"><div class="o-hb-border-preview" style="border-style: solid;"/></BuilderSelectItem>
                <BuilderSelectItem title.translate="Dashed" actionValue="'dashed'"><div class="o-hb-border-preview" style="border-style: dashed;"/></BuilderSelectItem>
                <BuilderSelectItem title.translate="Dotted" actionValue="'dotted'"><div class="o-hb-border-preview" style="border-style: dotted;"/></BuilderSelectItem>
                <BuilderSelectItem title.translate="Double" actionValue="'double'"><div class="o-hb-border-preview" style="border-style: double;"/></BuilderSelectItem>
            </BuilderSelect>
            <BuilderColorPicker actionParam="{ variable: \`\${prefix}border-color\` }" noTransparency="true" enabledTabs="['solid', 'custom']"/>
        </BuilderRow>
        <BuilderRow label.translate="Width" level="1">
            <BuilderButtonGroup actionParam="{ variable: \`\${prefix}width\` }">
                <BuilderButton actionValue="'25%'" title.translate="Resize Quarter">25%</BuilderButton>
                <BuilderButton actionValue="'50%'" title.translate="Resize Half">50%</BuilderButton>
                <BuilderButton actionValue="'75%'" title.translate="Resize Three Quarters">75%</BuilderButton>
                <BuilderButton actionValue="'100%'" title.translate="Resize Full">100%</BuilderButton>
            </BuilderButtonGroup>
        </BuilderRow>
    </BuilderContext>
</t>
`);
checkPrimaryTemplateParents(["html_editor.FontSizeSelector"]);
                    });
