
/* /web/static/src/module_loader.js */
(function(odoo){"use strict";if(odoo.loader){return;}
class ModuleLoader{bus=new EventTarget();checkErrorProm=null;factories=new Map();failed=new Set();jobs=new Set();modules=new Map();constructor(root){this.root=root;const strDebug=new URLSearchParams(location.search).get("debug");this.debug=Boolean(strDebug&&strDebug!=="0");}
addJob(name){this.jobs.add(name);this.startModules();}
define(name,deps,factory,lazy=false){if(typeof name!=="string"){throw new Error(`Module name should be a string, got: ${String(name)}`);}
if(!Array.isArray(deps)){throw new Error(`Module dependencies should be a list of strings, got: ${String(deps)}`);}
if(typeof factory!=="function"){throw new Error(`Module factory should be a function, got: ${String(factory)}`);}
if(this.factories.has(name)){return;}
this.factories.set(name,{deps,fn:factory,ignoreMissingDeps:globalThis.__odooIgnoreMissingDependencies,});if(!lazy){this.addJob(name);this.checkErrorProm||=Promise.resolve().then(()=>{this.checkErrorProm=null;this.reportErrors(this.findErrors());});}}
findErrors(moduleNames){const findCycle=(currentModuleNames,visited)=>{for(const name of currentModuleNames||[]){if(visited.has(name)){const cycleModuleNames=[...visited,name];return cycleModuleNames.slice(cycleModuleNames.indexOf(name)).map((j)=>`"${j}"`).join(" => ");}
const cycle=findCycle(dependencyGraph[name],new Set(visited).add(name));if(cycle){return cycle;}}
return null;};moduleNames||=this.jobs;const dependencyGraph=Object.create(null);const missing=new Set();const unloaded=new Set();for(const moduleName of moduleNames){const{deps,ignoreMissingDeps}=this.factories.get(moduleName);dependencyGraph[moduleName]=deps;if(ignoreMissingDeps){continue;}
unloaded.add(moduleName);for(const dep of deps){if(!this.factories.has(dep)){missing.add(dep);}}}
const cycle=findCycle(moduleNames,new Set());const errors={};if(cycle){errors.cycle=cycle;}
if(this.failed.size){errors.failed=this.failed;}
if(missing.size){errors.missing=missing;}
if(unloaded.size){errors.unloaded=unloaded;}
return errors;}
findJob(){for(const job of this.jobs){if(this.factories.get(job).deps.every((dep)=>this.modules.has(dep))){return job;}}
return null;}
async reportErrors(errors){if(!Object.keys(errors).length){return;}
if(errors.failed){console.error("The following modules failed to load because of an error:",[...errors.failed,]);}
if(errors.missing){console.error("The following modules are needed by other modules but have not been defined, they may not be present in the correct asset bundle:",[...errors.missing]);}
if(errors.cycle){console.error("The following modules could not be loaded because they form a dependency cycle:",errors.cycle);}
if(errors.unloaded){console.error("The following modules could not be loaded because they have unmet dependencies, this is a secondary error which is likely caused by one of the above problems:",[...errors.unloaded]);}
const document=this.root?.ownerDocument||globalThis.document;if(document.readyState==="loading"){await new Promise((resolve)=>document.addEventListener("DOMContentLoaded",resolve));}
if(this.debug){const style=document.createElement("style");style.className="o_module_error_banner";style.textContent=`
                    body::before {
                        font-weight: bold;
                        content: "An error occurred while loading javascript modules, you may find more information in the devtools console";
                        position: fixed;
                        left: 0;
                        bottom: 0;
                        z-index: 100000000000;
                        background-color: #C00;
                        color: #DDD;
                    }
                `;document.head.appendChild(style);}}
startModules(){let job;while((job=this.findJob())){this.startModule(job);}}
startModule(name){const require=(dependency)=>this.modules.get(dependency);this.jobs.delete(name);const factory=this.factories.get(name);let module=null;try{module=factory.fn(require);}catch(error){this.failed.add(name);throw new Error(`Error while loading "${name}":\n${error}`);}
this.modules.set(name,module);this.bus.dispatchEvent(new CustomEvent("module-started",{detail:{moduleName:name,module},}));return module;}}
const loader=new ModuleLoader();odoo.define=loader.define.bind(loader);odoo.loader=loader;if(odoo.debug&&!loader.debug){odoo.debug="";}})((globalThis.odoo||={}));;

/* /web/static/lib/owl/owl.js */
(function(exports){'use strict';function filterOutModifiersFromData(dataList){dataList=dataList.slice();const modifiers=[];let elm;while((elm=dataList[0])&&typeof elm==="string"){modifiers.push(dataList.shift());}
return{modifiers,data:dataList};}
const config={shouldNormalizeDom:true,mainEventHandler:(data,ev,currentTarget)=>{if(typeof data==="function"){data(ev);}
else if(Array.isArray(data)){data=filterOutModifiersFromData(data).data;data[0](data[1],ev);}
return false;},};class VToggler{constructor(key,child){this.key=key;this.child=child;}
mount(parent,afterNode){this.parentEl=parent;this.child.mount(parent,afterNode);}
moveBeforeDOMNode(node,parent){this.child.moveBeforeDOMNode(node,parent);}
moveBeforeVNode(other,afterNode){this.moveBeforeDOMNode((other&&other.firstNode())||afterNode);}
patch(other,withBeforeRemove){if(this===other){return;}
let child1=this.child;let child2=other.child;if(this.key===other.key){child1.patch(child2,withBeforeRemove);}
else{child2.mount(this.parentEl,child1.firstNode());if(withBeforeRemove){child1.beforeRemove();}
child1.remove();this.child=child2;this.key=other.key;}}
beforeRemove(){this.child.beforeRemove();}
remove(){this.child.remove();}
firstNode(){return this.child.firstNode();}
toString(){return this.child.toString();}}
function toggler(key,child){return new VToggler(key,child);}
class OwlError extends Error{}
const{setAttribute:elemSetAttribute,removeAttribute}=Element.prototype;const tokenList=DOMTokenList.prototype;const tokenListAdd=tokenList.add;const tokenListRemove=tokenList.remove;const isArray=Array.isArray;const{split,trim}=String.prototype;const wordRegexp=/\s+/;function setAttribute(key,value){switch(value){case false:case undefined:removeAttribute.call(this,key);break;case true:elemSetAttribute.call(this,key,"");break;default:elemSetAttribute.call(this,key,value);}}
function createAttrUpdater(attr){return function(value){setAttribute.call(this,attr,value);};}
function attrsSetter(attrs){if(isArray(attrs)){if(attrs[0]==="class"){setClass.call(this,attrs[1]);}
else{setAttribute.call(this,attrs[0],attrs[1]);}}
else{for(let k in attrs){if(k==="class"){setClass.call(this,attrs[k]);}
else{setAttribute.call(this,k,attrs[k]);}}}}
function attrsUpdater(attrs,oldAttrs){if(isArray(attrs)){const name=attrs[0];const val=attrs[1];if(name===oldAttrs[0]){if(val===oldAttrs[1]){return;}
if(name==="class"){updateClass.call(this,val,oldAttrs[1]);}
else{setAttribute.call(this,name,val);}}
else{removeAttribute.call(this,oldAttrs[0]);setAttribute.call(this,name,val);}}
else{for(let k in oldAttrs){if(!(k in attrs)){if(k==="class"){updateClass.call(this,"",oldAttrs[k]);}
else{removeAttribute.call(this,k);}}}
for(let k in attrs){const val=attrs[k];if(val!==oldAttrs[k]){if(k==="class"){updateClass.call(this,val,oldAttrs[k]);}
else{setAttribute.call(this,k,val);}}}}}
function toClassObj(expr){const result={};switch(typeof expr){case"string":const str=trim.call(expr);if(!str){return{};}
let words=split.call(str,wordRegexp);for(let i=0,l=words.length;i<l;i++){result[words[i]]=true;}
return result;case"object":for(let key in expr){const value=expr[key];if(value){key=trim.call(key);if(!key){continue;}
const words=split.call(key,wordRegexp);for(let word of words){result[word]=value;}}}
return result;case"undefined":return{};case"number":return{[expr]:true};default:return{[expr]:true};}}
function setClass(val){val=val===""?{}:toClassObj(val);const cl=this.classList;for(let c in val){tokenListAdd.call(cl,c);}}
function updateClass(val,oldVal){oldVal=oldVal===""?{}:toClassObj(oldVal);val=val===""?{}:toClassObj(val);const cl=this.classList;for(let c in oldVal){if(!(c in val)){tokenListRemove.call(cl,c);}}
for(let c in val){if(!(c in oldVal)){tokenListAdd.call(cl,c);}}}
function batched(callback){let scheduled=false;return async(...args)=>{if(!scheduled){scheduled=true;await Promise.resolve();scheduled=false;callback(...args);}};}
function inOwnerDocument(el){if(!el){return false;}
if(el.ownerDocument.contains(el)){return true;}
const rootNode=el.getRootNode();return rootNode instanceof ShadowRoot&&el.ownerDocument.contains(rootNode.host);}
function isAttachedToDocument(element,documentElement){let current=element;const shadowRoot=documentElement.defaultView.ShadowRoot;while(current){if(current===documentElement){return true;}
if(current.parentNode){current=current.parentNode;}
else if(current instanceof shadowRoot&&current.host){current=current.host;}
else{return false;}}
return false;}
function validateTarget(target){const document=target&&target.ownerDocument;if(document){if(!document.defaultView){throw new OwlError("Cannot mount a component: the target document is not attached to a window (defaultView is missing)");}
const HTMLElement=document.defaultView.HTMLElement;if(target instanceof HTMLElement||target instanceof ShadowRoot){if(!isAttachedToDocument(target,document)){throw new OwlError("Cannot mount a component on a detached dom node");}
return;}}
throw new OwlError("Cannot mount component: the target is not a valid DOM element");}
class EventBus extends EventTarget{trigger(name,payload){this.dispatchEvent(new CustomEvent(name,{detail:payload}));}}
function whenReady(fn){return new Promise(function(resolve){if(document.readyState!=="loading"){resolve(true);}
else{document.addEventListener("DOMContentLoaded",resolve,false);}}).then(fn||function(){});}
async function loadFile(url){const result=await fetch(url);if(!result.ok){throw new OwlError("Error while fetching xml templates");}
return await result.text();}
class Markup extends String{}
function htmlEscape(str){if(str instanceof Markup){return str;}
if(str===undefined){return markup("");}
if(typeof str==="number"){return markup(String(str));}
[["&","&amp;"],["<","&lt;"],[">","&gt;"],["'","&#x27;"],['"',"&quot;"],["`","&#x60;"],].forEach((pairs)=>{str=String(str).replace(new RegExp(pairs[0],"g"),pairs[1]);});return markup(str);}
function markup(valueOrStrings,...placeholders){if(!Array.isArray(valueOrStrings)){return new Markup(valueOrStrings);}
const strings=valueOrStrings;let acc="";let i=0;for(;i<placeholders.length;++i){acc+=strings[i]+htmlEscape(placeholders[i]);}
acc+=strings[i];return new Markup(acc);}
function createEventHandler(rawEvent){const eventName=rawEvent.split(".")[0];const capture=rawEvent.includes(".capture");if(rawEvent.includes(".synthetic")){return createSyntheticHandler(eventName,capture);}
else{return createElementHandler(eventName,capture);}}
let nextNativeEventId=1;function createElementHandler(evName,capture=false){let eventKey=`__event__${evName}_${nextNativeEventId++}`;if(capture){eventKey=`${eventKey}_capture`;}
function listener(ev){const currentTarget=ev.currentTarget;if(!currentTarget||!inOwnerDocument(currentTarget))
return;const data=currentTarget[eventKey];if(!data)
return;config.mainEventHandler(data,ev,currentTarget);}
function setup(data){this[eventKey]=data;this.addEventListener(evName,listener,{capture});}
function remove(){delete this[eventKey];this.removeEventListener(evName,listener,{capture});}
function update(data){this[eventKey]=data;}
return{setup,update,remove};}
let nextSyntheticEventId=1;function createSyntheticHandler(evName,capture=false){let eventKey=`__event__synthetic_${evName}`;if(capture){eventKey=`${eventKey}_capture`;}
setupSyntheticEvent(evName,eventKey,capture);const currentId=nextSyntheticEventId++;function setup(data){const _data=this[eventKey]||{};_data[currentId]=data;this[eventKey]=_data;}
function remove(){delete this[eventKey];}
return{setup,update:setup,remove};}
function nativeToSyntheticEvent(eventKey,event){let dom=event.target;while(dom!==null){const _data=dom[eventKey];if(_data){for(const data of Object.values(_data)){const stopped=config.mainEventHandler(data,event,dom);if(stopped)
return;}}
dom=dom.parentNode;}}
const CONFIGURED_SYNTHETIC_EVENTS={};function setupSyntheticEvent(evName,eventKey,capture=false){if(CONFIGURED_SYNTHETIC_EVENTS[eventKey]){return;}
document.addEventListener(evName,(event)=>nativeToSyntheticEvent(eventKey,event),{capture,});CONFIGURED_SYNTHETIC_EVENTS[eventKey]=true;}
const getDescriptor$3=(o,p)=>Object.getOwnPropertyDescriptor(o,p);const nodeProto$4=Node.prototype;const nodeInsertBefore$3=nodeProto$4.insertBefore;const nodeSetTextContent$1=getDescriptor$3(nodeProto$4,"textContent").set;const nodeRemoveChild$3=nodeProto$4.removeChild;class VMulti{constructor(children){this.children=children;}
mount(parent,afterNode){const children=this.children;const l=children.length;const anchors=new Array(l);for(let i=0;i<l;i++){let child=children[i];if(child){child.mount(parent,afterNode);}
else{const childAnchor=document.createTextNode("");anchors[i]=childAnchor;nodeInsertBefore$3.call(parent,childAnchor,afterNode);}}
this.anchors=anchors;this.parentEl=parent;}
moveBeforeDOMNode(node,parent=this.parentEl){this.parentEl=parent;const children=this.children;const anchors=this.anchors;for(let i=0,l=children.length;i<l;i++){let child=children[i];if(child){child.moveBeforeDOMNode(node,parent);}
else{const anchor=anchors[i];nodeInsertBefore$3.call(parent,anchor,node);}}}
moveBeforeVNode(other,afterNode){if(other){const next=other.children[0];afterNode=(next?next.firstNode():other.anchors[0])||null;}
const children=this.children;const parent=this.parentEl;const anchors=this.anchors;for(let i=0,l=children.length;i<l;i++){let child=children[i];if(child){child.moveBeforeVNode(null,afterNode);}
else{const anchor=anchors[i];nodeInsertBefore$3.call(parent,anchor,afterNode);}}}
patch(other,withBeforeRemove){if(this===other){return;}
const children1=this.children;const children2=other.children;const anchors=this.anchors;const parentEl=this.parentEl;for(let i=0,l=children1.length;i<l;i++){const vn1=children1[i];const vn2=children2[i];if(vn1){if(vn2){vn1.patch(vn2,withBeforeRemove);}
else{const afterNode=vn1.firstNode();const anchor=document.createTextNode("");anchors[i]=anchor;nodeInsertBefore$3.call(parentEl,anchor,afterNode);if(withBeforeRemove){vn1.beforeRemove();}
vn1.remove();children1[i]=undefined;}}
else if(vn2){children1[i]=vn2;const anchor=anchors[i];vn2.mount(parentEl,anchor);nodeRemoveChild$3.call(parentEl,anchor);}}}
beforeRemove(){const children=this.children;for(let i=0,l=children.length;i<l;i++){const child=children[i];if(child){child.beforeRemove();}}}
remove(){const parentEl=this.parentEl;if(this.isOnlyChild){nodeSetTextContent$1.call(parentEl,"");}
else{const children=this.children;const anchors=this.anchors;for(let i=0,l=children.length;i<l;i++){const child=children[i];if(child){child.remove();}
else{nodeRemoveChild$3.call(parentEl,anchors[i]);}}}}
firstNode(){const child=this.children[0];return child?child.firstNode():this.anchors[0];}
toString(){return this.children.map((c)=>(c?c.toString():"")).join("");}}
function multi(children){return new VMulti(children);}
const getDescriptor$2=(o,p)=>Object.getOwnPropertyDescriptor(o,p);const nodeProto$3=Node.prototype;const characterDataProto$1=CharacterData.prototype;const nodeInsertBefore$2=nodeProto$3.insertBefore;const characterDataSetData$1=getDescriptor$2(characterDataProto$1,"data").set;const nodeRemoveChild$2=nodeProto$3.removeChild;class VSimpleNode{constructor(text){this.text=text;}
mountNode(node,parent,afterNode){this.parentEl=parent;nodeInsertBefore$2.call(parent,node,afterNode);this.el=node;}
moveBeforeDOMNode(node,parent=this.parentEl){this.parentEl=parent;nodeInsertBefore$2.call(parent,this.el,node);}
moveBeforeVNode(other,afterNode){nodeInsertBefore$2.call(this.parentEl,this.el,other?other.el:afterNode);}
beforeRemove(){}
remove(){nodeRemoveChild$2.call(this.parentEl,this.el);}
firstNode(){return this.el;}
toString(){return this.text;}}
class VText$1 extends VSimpleNode{mount(parent,afterNode){this.mountNode(document.createTextNode(toText(this.text)),parent,afterNode);}
patch(other){const text2=other.text;if(this.text!==text2){characterDataSetData$1.call(this.el,toText(text2));this.text=text2;}}}
class VComment extends VSimpleNode{mount(parent,afterNode){this.mountNode(document.createComment(toText(this.text)),parent,afterNode);}
patch(){}}
function text(str){return new VText$1(str);}
function comment(str){return new VComment(str);}
function toText(value){switch(typeof value){case"string":return value;case"number":return String(value);case"boolean":return value?"true":"false";default:return value||"";}}
const getDescriptor$1=(o,p)=>Object.getOwnPropertyDescriptor(o,p);const nodeProto$2=Node.prototype;const elementProto=Element.prototype;const characterDataProto=CharacterData.prototype;const characterDataSetData=getDescriptor$1(characterDataProto,"data").set;const nodeGetFirstChild=getDescriptor$1(nodeProto$2,"firstChild").get;const nodeGetNextSibling=getDescriptor$1(nodeProto$2,"nextSibling").get;const NO_OP$1=()=>{};function makePropSetter(name){return function setProp(value){this[name]=value===0?0:value?value.valueOf():"";};}
const cache$1={};function createBlock(str){if(str in cache$1){return cache$1[str];}
const doc=new DOMParser().parseFromString(`<t>${str}</t>`,"text/xml");const node=doc.firstChild.firstChild;if(config.shouldNormalizeDom){normalizeNode(node);}
const tree=buildTree(node);const context=buildContext(tree);const template=tree.el;const Block=buildBlock(template,context);cache$1[str]=Block;return Block;}
function normalizeNode(node){if(node.nodeType===Node.TEXT_NODE){if(!/\S/.test(node.textContent)){node.remove();return;}}
if(node.nodeType===Node.ELEMENT_NODE){if(node.tagName==="pre"){return;}}
for(let i=node.childNodes.length-1;i>=0;--i){normalizeNode(node.childNodes.item(i));}}
function buildTree(node,parent=null,domParentTree=null){switch(node.nodeType){case Node.ELEMENT_NODE:{let currentNS=domParentTree&&domParentTree.currentNS;const tagName=node.tagName;let el=undefined;const info=[];if(tagName.startsWith("block-text-")){const index=parseInt(tagName.slice(11),10);info.push({type:"text",idx:index});el=document.createTextNode("");}
if(tagName.startsWith("block-child-")){if(!domParentTree.isRef){addRef(domParentTree);}
const index=parseInt(tagName.slice(12),10);info.push({type:"child",idx:index});el=document.createTextNode("");}
currentNS||(currentNS=node.namespaceURI);if(!el){el=currentNS?document.createElementNS(currentNS,tagName):document.createElement(tagName);}
if(el instanceof Element){if(!domParentTree){const fragment=document.createElement("template").content;fragment.appendChild(el);}
const attrs=node.attributes;for(let i=0;i<attrs.length;i++){const attrName=attrs[i].name;const attrValue=attrs[i].value;if(attrName.startsWith("block-handler-")){const idx=parseInt(attrName.slice(14),10);info.push({type:"handler",idx,event:attrValue,});}
else if(attrName.startsWith("block-attribute-")){const idx=parseInt(attrName.slice(16),10);info.push({type:"attribute",idx,name:attrValue,tag:tagName,});}
else if(attrName.startsWith("block-property-")){const idx=parseInt(attrName.slice(15),10);info.push({type:"property",idx,name:attrValue,tag:tagName,});}
else if(attrName==="block-attributes"){info.push({type:"attributes",idx:parseInt(attrValue,10),});}
else if(attrName==="block-ref"){info.push({type:"ref",idx:parseInt(attrValue,10),});}
else{el.setAttribute(attrs[i].name,attrValue);}}}
const tree={parent,firstChild:null,nextSibling:null,el,info,refN:0,currentNS,};if(node.firstChild){const childNode=node.childNodes[0];if(node.childNodes.length===1&&childNode.nodeType===Node.ELEMENT_NODE&&childNode.tagName.startsWith("block-child-")){const tagName=childNode.tagName;const index=parseInt(tagName.slice(12),10);info.push({idx:index,type:"child",isOnlyChild:true});}
else{tree.firstChild=buildTree(node.firstChild,tree,tree);el.appendChild(tree.firstChild.el);let curNode=node.firstChild;let curTree=tree.firstChild;while((curNode=curNode.nextSibling)){curTree.nextSibling=buildTree(curNode,curTree,tree);el.appendChild(curTree.nextSibling.el);curTree=curTree.nextSibling;}}}
if(tree.info.length){addRef(tree);}
return tree;}
case Node.TEXT_NODE:case Node.COMMENT_NODE:{const el=node.nodeType===Node.TEXT_NODE?document.createTextNode(node.textContent):document.createComment(node.textContent);return{parent:parent,firstChild:null,nextSibling:null,el,info:[],refN:0,currentNS:null,};}}
throw new OwlError("boom");}
function addRef(tree){tree.isRef=true;do{tree.refN++;}while((tree=tree.parent));}
function parentTree(tree){let parent=tree.parent;while(parent&&parent.nextSibling===tree){tree=parent;parent=parent.parent;}
return parent;}
function buildContext(tree,ctx,fromIdx){if(!ctx){const children=new Array(tree.info.filter((v)=>v.type==="child").length);ctx={collectors:[],locations:[],children,cbRefs:[],refN:tree.refN,refList:[]};fromIdx=0;}
if(tree.refN){const initialIdx=fromIdx;const isRef=tree.isRef;const firstChild=tree.firstChild?tree.firstChild.refN:0;const nextSibling=tree.nextSibling?tree.nextSibling.refN:0;if(isRef){for(let info of tree.info){info.refIdx=initialIdx;}
tree.refIdx=initialIdx;updateCtx(ctx,tree);fromIdx++;}
if(nextSibling){const idx=fromIdx+firstChild;ctx.collectors.push({idx,prevIdx:initialIdx,getVal:nodeGetNextSibling});buildContext(tree.nextSibling,ctx,idx);}
if(firstChild){ctx.collectors.push({idx:fromIdx,prevIdx:initialIdx,getVal:nodeGetFirstChild});buildContext(tree.firstChild,ctx,fromIdx);}}
return ctx;}
function updateCtx(ctx,tree){for(let info of tree.info){switch(info.type){case"text":ctx.locations.push({idx:info.idx,refIdx:info.refIdx,setData:setText,updateData:setText,});break;case"child":if(info.isOnlyChild){ctx.children[info.idx]={parentRefIdx:info.refIdx,isOnlyChild:true,};}
else{ctx.children[info.idx]={parentRefIdx:parentTree(tree).refIdx,afterRefIdx:info.refIdx,};}
break;case"property":{const refIdx=info.refIdx;const setProp=makePropSetter(info.name);ctx.locations.push({idx:info.idx,refIdx,setData:setProp,updateData:setProp,});break;}
case"attribute":{const refIdx=info.refIdx;let updater;let setter;if(info.name==="class"){setter=setClass;updater=updateClass;}
else{setter=createAttrUpdater(info.name);updater=setter;}
ctx.locations.push({idx:info.idx,refIdx,setData:setter,updateData:updater,});break;}
case"attributes":ctx.locations.push({idx:info.idx,refIdx:info.refIdx,setData:attrsSetter,updateData:attrsUpdater,});break;case"handler":{const{setup,update}=createEventHandler(info.event);ctx.locations.push({idx:info.idx,refIdx:info.refIdx,setData:setup,updateData:update,});break;}
case"ref":const index=ctx.cbRefs.push(info.idx)-1;ctx.locations.push({idx:info.idx,refIdx:info.refIdx,setData:makeRefSetter(index,ctx.refList),updateData:NO_OP$1,});}}}
function buildBlock(template,ctx){let B=createBlockClass(template,ctx);if(ctx.cbRefs.length){const cbRefs=ctx.cbRefs;const refList=ctx.refList;let cbRefsNumber=cbRefs.length;B=class extends B{mount(parent,afterNode){refList.push(new Array(cbRefsNumber));super.mount(parent,afterNode);for(let cbRef of refList.pop()){cbRef();}}
remove(){super.remove();for(let cbRef of cbRefs){let fn=this.data[cbRef];fn(null);}}};}
if(ctx.children.length){B=class extends B{constructor(data,children){super(data);this.children=children;}};B.prototype.beforeRemove=VMulti.prototype.beforeRemove;return(data,children=[])=>new B(data,children);}
return(data)=>new B(data);}
function createBlockClass(template,ctx){const{refN,collectors,children}=ctx;const colN=collectors.length;ctx.locations.sort((a,b)=>a.idx-b.idx);const locations=ctx.locations.map((loc)=>({refIdx:loc.refIdx,setData:loc.setData,updateData:loc.updateData,}));const locN=locations.length;const childN=children.length;const childrenLocs=children;const isDynamic=refN>0;const nodeCloneNode=nodeProto$2.cloneNode;const nodeInsertBefore=nodeProto$2.insertBefore;const elementRemove=elementProto.remove;class Block{constructor(data){this.data=data;}
beforeRemove(){}
remove(){elementRemove.call(this.el);}
firstNode(){return this.el;}
moveBeforeDOMNode(node,parent=this.parentEl){this.parentEl=parent;nodeInsertBefore.call(parent,this.el,node);}
moveBeforeVNode(other,afterNode){nodeInsertBefore.call(this.parentEl,this.el,other?other.el:afterNode);}
toString(){const div=document.createElement("div");this.mount(div,null);return div.innerHTML;}
mount(parent,afterNode){const el=nodeCloneNode.call(template,true);nodeInsertBefore.call(parent,el,afterNode);this.el=el;this.parentEl=parent;}
patch(other,withBeforeRemove){}}
if(isDynamic){Block.prototype.mount=function mount(parent,afterNode){const el=nodeCloneNode.call(template,true);const refs=new Array(refN);this.refs=refs;refs[0]=el;for(let i=0;i<colN;i++){const w=collectors[i];refs[w.idx]=w.getVal.call(refs[w.prevIdx]);}
if(locN){const data=this.data;for(let i=0;i<locN;i++){const loc=locations[i];loc.setData.call(refs[loc.refIdx],data[i]);}}
nodeInsertBefore.call(parent,el,afterNode);if(childN){const children=this.children;for(let i=0;i<childN;i++){const child=children[i];if(child){const loc=childrenLocs[i];const afterNode=loc.afterRefIdx?refs[loc.afterRefIdx]:null;child.isOnlyChild=loc.isOnlyChild;child.mount(refs[loc.parentRefIdx],afterNode);}}}
this.el=el;this.parentEl=parent;};Block.prototype.patch=function patch(other,withBeforeRemove){if(this===other){return;}
const refs=this.refs;if(locN){const data1=this.data;const data2=other.data;for(let i=0;i<locN;i++){const val1=data1[i];const val2=data2[i];if(val1!==val2){const loc=locations[i];loc.updateData.call(refs[loc.refIdx],val2,val1);}}
this.data=data2;}
if(childN){let children1=this.children;const children2=other.children;for(let i=0;i<childN;i++){const child1=children1[i];const child2=children2[i];if(child1){if(child2){child1.patch(child2,withBeforeRemove);}
else{if(withBeforeRemove){child1.beforeRemove();}
child1.remove();children1[i]=undefined;}}
else if(child2){const loc=childrenLocs[i];const afterNode=loc.afterRefIdx?refs[loc.afterRefIdx]:null;child2.mount(refs[loc.parentRefIdx],afterNode);children1[i]=child2;}}}};}
return Block;}
function setText(value){characterDataSetData.call(this,toText(value));}
function makeRefSetter(index,refs){return function setRef(fn){refs[refs.length-1][index]=()=>fn(this);};}
const getDescriptor=(o,p)=>Object.getOwnPropertyDescriptor(o,p);const nodeProto$1=Node.prototype;const nodeInsertBefore$1=nodeProto$1.insertBefore;const nodeAppendChild=nodeProto$1.appendChild;const nodeRemoveChild$1=nodeProto$1.removeChild;const nodeSetTextContent=getDescriptor(nodeProto$1,"textContent").set;class VList{constructor(children){this.children=children;}
mount(parent,afterNode){const children=this.children;const _anchor=document.createTextNode("");this.anchor=_anchor;nodeInsertBefore$1.call(parent,_anchor,afterNode);const l=children.length;if(l){const mount=children[0].mount;for(let i=0;i<l;i++){mount.call(children[i],parent,_anchor);}}
this.parentEl=parent;}
moveBeforeDOMNode(node,parent=this.parentEl){this.parentEl=parent;const children=this.children;for(let i=0,l=children.length;i<l;i++){children[i].moveBeforeDOMNode(node,parent);}
parent.insertBefore(this.anchor,node);}
moveBeforeVNode(other,afterNode){if(other){const next=other.children[0];afterNode=(next?next.firstNode():other.anchor)||null;}
const children=this.children;for(let i=0,l=children.length;i<l;i++){children[i].moveBeforeVNode(null,afterNode);}
this.parentEl.insertBefore(this.anchor,afterNode);}
patch(other,withBeforeRemove){if(this===other){return;}
const ch1=this.children;const ch2=other.children;if(ch2.length===0&&ch1.length===0){return;}
this.children=ch2;const proto=ch2[0]||ch1[0];const{mount:cMount,patch:cPatch,remove:cRemove,beforeRemove,moveBeforeVNode:cMoveBefore,firstNode:cFirstNode,}=proto;const _anchor=this.anchor;const isOnlyChild=this.isOnlyChild;const parent=this.parentEl;if(ch2.length===0&&isOnlyChild){if(withBeforeRemove){for(let i=0,l=ch1.length;i<l;i++){beforeRemove.call(ch1[i]);}}
nodeSetTextContent.call(parent,"");nodeAppendChild.call(parent,_anchor);return;}
let startIdx1=0;let startIdx2=0;let startVn1=ch1[0];let startVn2=ch2[0];let endIdx1=ch1.length-1;let endIdx2=ch2.length-1;let endVn1=ch1[endIdx1];let endVn2=ch2[endIdx2];let mapping=undefined;while(startIdx1<=endIdx1&&startIdx2<=endIdx2){if(startVn1===null){startVn1=ch1[++startIdx1];continue;}
if(endVn1===null){endVn1=ch1[--endIdx1];continue;}
let startKey1=startVn1.key;let startKey2=startVn2.key;if(startKey1===startKey2){cPatch.call(startVn1,startVn2,withBeforeRemove);ch2[startIdx2]=startVn1;startVn1=ch1[++startIdx1];startVn2=ch2[++startIdx2];continue;}
let endKey1=endVn1.key;let endKey2=endVn2.key;if(endKey1===endKey2){cPatch.call(endVn1,endVn2,withBeforeRemove);ch2[endIdx2]=endVn1;endVn1=ch1[--endIdx1];endVn2=ch2[--endIdx2];continue;}
if(startKey1===endKey2){cPatch.call(startVn1,endVn2,withBeforeRemove);ch2[endIdx2]=startVn1;const nextChild=ch2[endIdx2+1];cMoveBefore.call(startVn1,nextChild,_anchor);startVn1=ch1[++startIdx1];endVn2=ch2[--endIdx2];continue;}
if(endKey1===startKey2){cPatch.call(endVn1,startVn2,withBeforeRemove);ch2[startIdx2]=endVn1;const nextChild=ch1[startIdx1];cMoveBefore.call(endVn1,nextChild,_anchor);endVn1=ch1[--endIdx1];startVn2=ch2[++startIdx2];continue;}
mapping=mapping||createMapping(ch1,startIdx1,endIdx1);let idxInOld=mapping[startKey2];if(idxInOld===undefined){cMount.call(startVn2,parent,cFirstNode.call(startVn1)||null);}
else{const elmToMove=ch1[idxInOld];cMoveBefore.call(elmToMove,startVn1,null);cPatch.call(elmToMove,startVn2,withBeforeRemove);ch2[startIdx2]=elmToMove;ch1[idxInOld]=null;}
startVn2=ch2[++startIdx2];}
if(startIdx1<=endIdx1||startIdx2<=endIdx2){if(startIdx1>endIdx1){const nextChild=ch2[endIdx2+1];const anchor=nextChild?cFirstNode.call(nextChild)||null:_anchor;for(let i=startIdx2;i<=endIdx2;i++){cMount.call(ch2[i],parent,anchor);}}
else{for(let i=startIdx1;i<=endIdx1;i++){let ch=ch1[i];if(ch){if(withBeforeRemove){beforeRemove.call(ch);}
cRemove.call(ch);}}}}}
beforeRemove(){const children=this.children;const l=children.length;if(l){const beforeRemove=children[0].beforeRemove;for(let i=0;i<l;i++){beforeRemove.call(children[i]);}}}
remove(){const{parentEl,anchor}=this;if(this.isOnlyChild){nodeSetTextContent.call(parentEl,"");}
else{const children=this.children;const l=children.length;if(l){const remove=children[0].remove;for(let i=0;i<l;i++){remove.call(children[i]);}}
nodeRemoveChild$1.call(parentEl,anchor);}}
firstNode(){const child=this.children[0];return child?child.firstNode():undefined;}
toString(){return this.children.map((c)=>c.toString()).join("");}}
function list(children){return new VList(children);}
function createMapping(ch1,startIdx1,endIdx2){let mapping={};for(let i=startIdx1;i<=endIdx2;i++){mapping[ch1[i].key]=i;}
return mapping;}
const nodeProto=Node.prototype;const nodeInsertBefore=nodeProto.insertBefore;const nodeRemoveChild=nodeProto.removeChild;class VHtml{constructor(html){this.content=[];this.html=html;}
mount(parent,afterNode){this.parentEl=parent;const template=document.createElement("template");template.innerHTML=this.html;this.content=[...template.content.childNodes];for(let elem of this.content){nodeInsertBefore.call(parent,elem,afterNode);}
if(!this.content.length){const textNode=document.createTextNode("");this.content.push(textNode);nodeInsertBefore.call(parent,textNode,afterNode);}}
moveBeforeDOMNode(node,parent=this.parentEl){this.parentEl=parent;for(let elem of this.content){nodeInsertBefore.call(parent,elem,node);}}
moveBeforeVNode(other,afterNode){const target=other?other.content[0]:afterNode;this.moveBeforeDOMNode(target);}
patch(other){if(this===other){return;}
const html2=other.html;if(this.html!==html2){const parent=this.parentEl;const afterNode=this.content[0];const template=document.createElement("template");template.innerHTML=html2;const content=[...template.content.childNodes];for(let elem of content){nodeInsertBefore.call(parent,elem,afterNode);}
if(!content.length){const textNode=document.createTextNode("");content.push(textNode);nodeInsertBefore.call(parent,textNode,afterNode);}
this.remove();this.content=content;this.html=other.html;}}
beforeRemove(){}
remove(){const parent=this.parentEl;for(let elem of this.content){nodeRemoveChild.call(parent,elem);}}
firstNode(){return this.content[0];}
toString(){return this.html;}}
function html(str){return new VHtml(str);}
function createCatcher(eventsSpec){const n=Object.keys(eventsSpec).length;class VCatcher{constructor(child,handlers){this.handlerFns=[];this.afterNode=null;this.child=child;this.handlerData=handlers;}
mount(parent,afterNode){this.parentEl=parent;this.child.mount(parent,afterNode);this.afterNode=document.createTextNode("");parent.insertBefore(this.afterNode,afterNode);this.wrapHandlerData();for(let name in eventsSpec){const index=eventsSpec[name];const handler=createEventHandler(name);this.handlerFns[index]=handler;handler.setup.call(parent,this.handlerData[index]);}}
wrapHandlerData(){for(let i=0;i<n;i++){let handler=this.handlerData[i];let idx=handler.length-2;let origFn=handler[idx];const self=this;handler[idx]=function(ev){const target=ev.target;let currentNode=self.child.firstNode();const afterNode=self.afterNode;while(currentNode&&currentNode!==afterNode){if(currentNode.contains(target)){return origFn.call(this,ev);}
currentNode=currentNode.nextSibling;}};}}
moveBeforeDOMNode(node,parent=this.parentEl){this.parentEl=parent;this.child.moveBeforeDOMNode(node,parent);parent.insertBefore(this.afterNode,node);}
moveBeforeVNode(other,afterNode){if(other){afterNode=other.firstNode()||afterNode;}
this.child.moveBeforeVNode(other?other.child:null,afterNode);this.parentEl.insertBefore(this.afterNode,afterNode);}
patch(other,withBeforeRemove){if(this===other){return;}
this.handlerData=other.handlerData;this.wrapHandlerData();for(let i=0;i<n;i++){this.handlerFns[i].update.call(this.parentEl,this.handlerData[i]);}
this.child.patch(other.child,withBeforeRemove);}
beforeRemove(){this.child.beforeRemove();}
remove(){for(let i=0;i<n;i++){this.handlerFns[i].remove.call(this.parentEl);}
this.child.remove();this.afterNode.remove();}
firstNode(){return this.child.firstNode();}
toString(){return this.child.toString();}}
return function(child,handlers){return new VCatcher(child,handlers);};}
function mount$1(vnode,fixture,afterNode=null){vnode.mount(fixture,afterNode);}
function patch(vnode1,vnode2,withBeforeRemove=false){vnode1.patch(vnode2,withBeforeRemove);}
function remove(vnode,withBeforeRemove=false){if(withBeforeRemove){vnode.beforeRemove();}
vnode.remove();}
const fibersInError=new WeakMap();const nodeErrorHandlers=new WeakMap();function _handleError(node,error){if(!node){return false;}
const fiber=node.fiber;if(fiber){fibersInError.set(fiber,error);}
const errorHandlers=nodeErrorHandlers.get(node);if(errorHandlers){let handled=false;for(let i=errorHandlers.length-1;i>=0;i--){try{errorHandlers[i](error);handled=true;break;}
catch(e){error=e;}}
if(handled){return true;}}
return _handleError(node.parent,error);}
function handleError(params){let{error}=params;if(!(error instanceof OwlError)){error=Object.assign(new OwlError(`An error occured in the owl lifecycle (see this Error's "cause" property)`),{cause:error});}
const node="node"in params?params.node:params.fiber.node;const fiber="fiber"in params?params.fiber:node.fiber;if(fiber){let current=fiber;do{current.node.fiber=current;fibersInError.set(current,error);current=current.parent;}while(current);fibersInError.set(fiber.root,error);}
const handled=_handleError(node,error);if(!handled){console.warn(`[Owl] Unhandled error. Destroying the root component`);try{node.app.destroy();}
catch(e){console.error(e);}
throw error;}}
function makeChildFiber(node,parent){let current=node.fiber;if(current){cancelFibers(current.children);current.root=null;}
return new Fiber(node,parent);}
function makeRootFiber(node){let current=node.fiber;if(current){let root=current.root;root.locked=true;root.setCounter(root.counter+1-cancelFibers(current.children));root.locked=false;current.children=[];current.childrenMap={};current.bdom=null;if(fibersInError.has(current)){fibersInError.delete(current);fibersInError.delete(root);current.appliedToDom=false;if(current instanceof RootFiber){current.mounted=current instanceof MountFiber?[current]:[];}}
return current;}
const fiber=new RootFiber(node,null);if(node.willPatch.length){fiber.willPatch.push(fiber);}
if(node.patched.length){fiber.patched.push(fiber);}
return fiber;}
function throwOnRender(){throw new OwlError("Attempted to render cancelled fiber");}
function cancelFibers(fibers){let result=0;for(let fiber of fibers){let node=fiber.node;fiber.render=throwOnRender;if(node.status===0){node.cancel();}
node.fiber=null;if(fiber.bdom){node.forceNextRender=true;}
else{result++;}
result+=cancelFibers(fiber.children);}
return result;}
class Fiber{constructor(node,parent){this.bdom=null;this.children=[];this.appliedToDom=false;this.deep=false;this.childrenMap={};this.node=node;this.parent=parent;if(parent){this.deep=parent.deep;const root=parent.root;root.setCounter(root.counter+1);this.root=root;parent.children.push(this);}
else{this.root=this;}}
render(){let prev=this.root.node;let scheduler=prev.app.scheduler;let current=prev.parent;while(current){if(current.fiber){let root=current.fiber.root;if(root.counter===0&&prev.parentKey in current.fiber.childrenMap){current=root.node;}
else{scheduler.delayedRenders.push(this);return;}}
prev=current;current=current.parent;}
this._render();}
_render(){const node=this.node;const root=this.root;if(root){try{this.bdom=true;this.bdom=node.renderFn();}
catch(e){node.app.handleError({node,error:e});}
root.setCounter(root.counter-1);}}}
class RootFiber extends Fiber{constructor(){super(...arguments);this.counter=1;this.willPatch=[];this.patched=[];this.mounted=[];this.locked=false;}
complete(){const node=this.node;this.locked=true;let current=undefined;let mountedFibers=this.mounted;try{for(current of this.willPatch){let node=current.node;if(node.fiber===current){const component=node.component;for(let cb of node.willPatch){cb.call(component);}}}
current=undefined;node._patch();this.locked=false;while((current=mountedFibers.pop())){current=current;if(current.appliedToDom){for(let cb of current.node.mounted){cb();}}}
let patchedFibers=this.patched;while((current=patchedFibers.pop())){current=current;if(current.appliedToDom){for(let cb of current.node.patched){cb();}}}}
catch(e){for(let fiber of mountedFibers){fiber.node.willUnmount=[];}
this.locked=false;node.app.handleError({fiber:current||this,error:e});}}
setCounter(newValue){this.counter=newValue;if(newValue===0){this.node.app.scheduler.flush();}}}
class MountFiber extends RootFiber{constructor(node,target,options={}){super(node,null);this.target=target;this.position=options.position||"last-child";}
complete(){let current=this;try{const node=this.node;node.children=this.childrenMap;node.app.constructor.validateTarget(this.target);if(node.bdom){node.updateDom();}
else{node.bdom=this.bdom;if(this.position==="last-child"||this.target.childNodes.length===0){mount$1(node.bdom,this.target);}
else{const firstChild=this.target.childNodes[0];mount$1(node.bdom,this.target,firstChild);}}
node.fiber=null;node.status=1;this.appliedToDom=true;let mountedFibers=this.mounted;while((current=mountedFibers.pop())){if(current.appliedToDom){for(let cb of current.node.mounted){cb();}}}}
catch(e){this.node.app.handleError({fiber:current,error:e});}}}
const KEYCHANGES=Symbol("Key changes");const NO_CALLBACK=()=>{throw new Error("Called NO_CALLBACK. Owl is broken, please report this to the maintainers.");};const objectToString=Object.prototype.toString;const objectHasOwnProperty=Object.prototype.hasOwnProperty;const SUPPORTED_RAW_TYPES=["Object","Array","Set","Map","WeakMap"];const COLLECTION_RAW_TYPES=["Set","Map","WeakMap"];function rawType(obj){return objectToString.call(toRaw(obj)).slice(8,-1);}
function canBeMadeReactive(value){if(typeof value!=="object"){return false;}
return SUPPORTED_RAW_TYPES.includes(rawType(value));}
function possiblyReactive(val,cb){return canBeMadeReactive(val)?reactive(val,cb):val;}
const skipped=new WeakSet();function markRaw(value){skipped.add(value);return value;}
function toRaw(value){return targets.has(value)?targets.get(value):value;}
const targetToKeysToCallbacks=new WeakMap();function observeTargetKey(target,key,callback){if(callback===NO_CALLBACK){return;}
if(!targetToKeysToCallbacks.get(target)){targetToKeysToCallbacks.set(target,new Map());}
const keyToCallbacks=targetToKeysToCallbacks.get(target);if(!keyToCallbacks.get(key)){keyToCallbacks.set(key,new Set());}
keyToCallbacks.get(key).add(callback);if(!callbacksToTargets.has(callback)){callbacksToTargets.set(callback,new Set());}
callbacksToTargets.get(callback).add(target);}
function notifyReactives(target,key){const keyToCallbacks=targetToKeysToCallbacks.get(target);if(!keyToCallbacks){return;}
const callbacks=keyToCallbacks.get(key);if(!callbacks){return;}
for(const callback of[...callbacks]){clearReactivesForCallback(callback);callback();}}
const callbacksToTargets=new WeakMap();function clearReactivesForCallback(callback){const targetsToClear=callbacksToTargets.get(callback);if(!targetsToClear){return;}
for(const target of targetsToClear){const observedKeys=targetToKeysToCallbacks.get(target);if(!observedKeys){continue;}
for(const[key,callbacks]of observedKeys.entries()){callbacks.delete(callback);if(!callbacks.size){observedKeys.delete(key);}}}
targetsToClear.clear();}
function getSubscriptions(callback){const targets=callbacksToTargets.get(callback)||[];return[...targets].map((target)=>{const keysToCallbacks=targetToKeysToCallbacks.get(target);let keys=[];if(keysToCallbacks){for(const[key,cbs]of keysToCallbacks){if(cbs.has(callback)){keys.push(key);}}}
return{target,keys};});}
const targets=new WeakMap();const reactiveCache=new WeakMap();function reactive(target,callback=NO_CALLBACK){if(!canBeMadeReactive(target)){throw new OwlError(`Cannot make the given value reactive`);}
if(skipped.has(target)){return target;}
if(targets.has(target)){return reactive(targets.get(target),callback);}
if(!reactiveCache.has(target)){reactiveCache.set(target,new WeakMap());}
const reactivesForTarget=reactiveCache.get(target);if(!reactivesForTarget.has(callback)){const targetRawType=rawType(target);const handler=COLLECTION_RAW_TYPES.includes(targetRawType)?collectionsProxyHandler(target,callback,targetRawType):basicProxyHandler(callback);const proxy=new Proxy(target,handler);reactivesForTarget.set(callback,proxy);targets.set(proxy,target);}
return reactivesForTarget.get(callback);}
function basicProxyHandler(callback){return{get(target,key,receiver){const desc=Object.getOwnPropertyDescriptor(target,key);if(desc&&!desc.writable&&!desc.configurable){return Reflect.get(target,key,receiver);}
observeTargetKey(target,key,callback);return possiblyReactive(Reflect.get(target,key,receiver),callback);},set(target,key,value,receiver){const hadKey=objectHasOwnProperty.call(target,key);const originalValue=Reflect.get(target,key,receiver);const ret=Reflect.set(target,key,toRaw(value),receiver);if(!hadKey&&objectHasOwnProperty.call(target,key)){notifyReactives(target,KEYCHANGES);}
if(originalValue!==Reflect.get(target,key,receiver)||(key==="length"&&Array.isArray(target))){notifyReactives(target,key);}
return ret;},deleteProperty(target,key){const ret=Reflect.deleteProperty(target,key);notifyReactives(target,KEYCHANGES);notifyReactives(target,key);return ret;},ownKeys(target){observeTargetKey(target,KEYCHANGES,callback);return Reflect.ownKeys(target);},has(target,key){observeTargetKey(target,KEYCHANGES,callback);return Reflect.has(target,key);},};}
function makeKeyObserver(methodName,target,callback){return(key)=>{key=toRaw(key);observeTargetKey(target,key,callback);return possiblyReactive(target[methodName](key),callback);};}
function makeIteratorObserver(methodName,target,callback){return function*(){observeTargetKey(target,KEYCHANGES,callback);const keys=target.keys();for(const item of target[methodName]()){const key=keys.next().value;observeTargetKey(target,key,callback);yield possiblyReactive(item,callback);}};}
function makeForEachObserver(target,callback){return function forEach(forEachCb,thisArg){observeTargetKey(target,KEYCHANGES,callback);target.forEach(function(val,key,targetObj){observeTargetKey(target,key,callback);forEachCb.call(thisArg,possiblyReactive(val,callback),possiblyReactive(key,callback),possiblyReactive(targetObj,callback));},thisArg);};}
function delegateAndNotify(setterName,getterName,target){return(key,value)=>{key=toRaw(key);const hadKey=target.has(key);const originalValue=target[getterName](key);const ret=target[setterName](key,value);const hasKey=target.has(key);if(hadKey!==hasKey){notifyReactives(target,KEYCHANGES);}
if(originalValue!==target[getterName](key)){notifyReactives(target,key);}
return ret;};}
function makeClearNotifier(target){return()=>{const allKeys=[...target.keys()];target.clear();notifyReactives(target,KEYCHANGES);for(const key of allKeys){notifyReactives(target,key);}};}
const rawTypeToFuncHandlers={Set:(target,callback)=>({has:makeKeyObserver("has",target,callback),add:delegateAndNotify("add","has",target),delete:delegateAndNotify("delete","has",target),keys:makeIteratorObserver("keys",target,callback),values:makeIteratorObserver("values",target,callback),entries:makeIteratorObserver("entries",target,callback),[Symbol.iterator]:makeIteratorObserver(Symbol.iterator,target,callback),forEach:makeForEachObserver(target,callback),clear:makeClearNotifier(target),get size(){observeTargetKey(target,KEYCHANGES,callback);return target.size;},}),Map:(target,callback)=>({has:makeKeyObserver("has",target,callback),get:makeKeyObserver("get",target,callback),set:delegateAndNotify("set","get",target),delete:delegateAndNotify("delete","has",target),keys:makeIteratorObserver("keys",target,callback),values:makeIteratorObserver("values",target,callback),entries:makeIteratorObserver("entries",target,callback),[Symbol.iterator]:makeIteratorObserver(Symbol.iterator,target,callback),forEach:makeForEachObserver(target,callback),clear:makeClearNotifier(target),get size(){observeTargetKey(target,KEYCHANGES,callback);return target.size;},}),WeakMap:(target,callback)=>({has:makeKeyObserver("has",target,callback),get:makeKeyObserver("get",target,callback),set:delegateAndNotify("set","get",target),delete:delegateAndNotify("delete","has",target),}),};function collectionsProxyHandler(target,callback,targetRawType){const specialHandlers=rawTypeToFuncHandlers[targetRawType](target,callback);return Object.assign(basicProxyHandler(callback),{get(target,key){if(objectHasOwnProperty.call(specialHandlers,key)){return specialHandlers[key];}
observeTargetKey(target,key,callback);return possiblyReactive(target[key],callback);},});}
let currentNode=null;function saveCurrent(){let n=currentNode;return()=>{currentNode=n;};}
function getCurrent(){if(!currentNode){throw new OwlError("No active component (a hook function should only be called in 'setup')");}
return currentNode;}
function useComponent(){return currentNode.component;}
function applyDefaultProps(props,defaultProps){for(let propName in defaultProps){if(props[propName]===undefined){props[propName]=defaultProps[propName];}}}
const batchedRenderFunctions=new WeakMap();function useState(state){const node=getCurrent();let render=batchedRenderFunctions.get(node);if(!render){const wrapper={fn:batched(node.render.bind(node,false))};render=(...args)=>wrapper.fn(...args);batchedRenderFunctions.set(node,render);node.willDestroy.push(cleanupRenderAndReactives.bind(null,wrapper,render));}
return reactive(state,render);}
const NO_OP=()=>{};function cleanupRenderAndReactives(wrapper,render){wrapper.fn=NO_OP;clearReactivesForCallback(render);}
class ComponentNode{constructor(C,props,app,parent,parentKey){this.fiber=null;this.bdom=null;this.status=0;this.forceNextRender=false;this.nextProps=null;this.children=Object.create(null);this.refs={};this.willStart=[];this.willUpdateProps=[];this.willUnmount=[];this.mounted=[];this.willPatch=[];this.patched=[];this.willDestroy=[];currentNode=this;this.app=app;this.parent=parent;this.props=props;this.parentKey=parentKey;const defaultProps=C.defaultProps;props=Object.assign({},props);if(defaultProps){applyDefaultProps(props,defaultProps);}
const env=(parent&&parent.childEnv)||app.env;this.childEnv=env;for(const key in props){const prop=props[key];if(prop&&typeof prop==="object"&&targets.has(prop)){props[key]=useState(prop);}}
this.component=new C(props,env,this);const ctx=Object.assign(Object.create(this.component),{this:this.component});this.renderFn=app.getTemplate(C.template).bind(this.component,ctx,this);this.component.setup();currentNode=null;}
mountComponent(target,options){const fiber=new MountFiber(this,target,options);this.app.scheduler.addFiber(fiber);this.initiateRender(fiber);}
async initiateRender(fiber){this.fiber=fiber;if(this.mounted.length){fiber.root.mounted.push(fiber);}
const component=this.component;try{await Promise.all(this.willStart.map((f)=>f.call(component)));}
catch(e){this.app.handleError({node:this,error:e});return;}
if(this.status===0&&this.fiber===fiber){fiber.render();}}
async render(deep){if(this.status>=2){return;}
let current=this.fiber;if(current&&(current.root.locked||current.bdom===true)){await Promise.resolve();current=this.fiber;}
if(current){if(!current.bdom&&!fibersInError.has(current)){if(deep){current.deep=deep;}
return;}
deep=deep||current.deep;}
else if(!this.bdom){return;}
const fiber=makeRootFiber(this);fiber.deep=deep;this.fiber=fiber;this.app.scheduler.addFiber(fiber);await Promise.resolve();if(this.status>=2){return;}
if(this.fiber===fiber&&(current||!fiber.parent)){fiber.render();}}
cancel(){this._cancel();delete this.parent.children[this.parentKey];this.app.scheduler.scheduleDestroy(this);}
_cancel(){this.status=2;const children=this.children;for(let childKey in children){children[childKey]._cancel();}}
destroy(){let shouldRemove=this.status===1;this._destroy();if(shouldRemove){this.bdom.remove();}}
_destroy(){const component=this.component;if(this.status===1){for(let cb of this.willUnmount){cb.call(component);}}
for(let child of Object.values(this.children)){child._destroy();}
if(this.willDestroy.length){try{for(let cb of this.willDestroy){cb.call(component);}}
catch(e){this.app.handleError({error:e,node:this});}}
this.status=3;}
async updateAndRender(props,parentFiber){this.nextProps=props;props=Object.assign({},props);const fiber=makeChildFiber(this,parentFiber);this.fiber=fiber;const component=this.component;const defaultProps=component.constructor.defaultProps;if(defaultProps){applyDefaultProps(props,defaultProps);}
currentNode=this;for(const key in props){const prop=props[key];if(prop&&typeof prop==="object"&&targets.has(prop)){props[key]=useState(prop);}}
currentNode=null;const prom=Promise.all(this.willUpdateProps.map((f)=>f.call(component,props)));await prom;if(fiber!==this.fiber){return;}
component.props=props;fiber.render();const parentRoot=parentFiber.root;if(this.willPatch.length){parentRoot.willPatch.push(fiber);}
if(this.patched.length){parentRoot.patched.push(fiber);}}
updateDom(){if(!this.fiber){return;}
if(this.bdom===this.fiber.bdom){for(let k in this.children){const child=this.children[k];child.updateDom();}}
else{this.bdom.patch(this.fiber.bdom,false);this.fiber.appliedToDom=true;this.fiber=null;}}
setRef(name,el){if(el){this.refs[name]=el;}}
firstNode(){const bdom=this.bdom;return bdom?bdom.firstNode():undefined;}
mount(parent,anchor){const bdom=this.fiber.bdom;this.bdom=bdom;bdom.mount(parent,anchor);this.status=1;this.fiber.appliedToDom=true;this.children=this.fiber.childrenMap;this.fiber=null;}
moveBeforeDOMNode(node,parent){this.bdom.moveBeforeDOMNode(node,parent);}
moveBeforeVNode(other,afterNode){this.bdom.moveBeforeVNode(other?other.bdom:null,afterNode);}
patch(){if(this.fiber&&this.fiber.parent){this._patch();this.props=this.nextProps;}}
_patch(){let hasChildren=false;for(let _k in this.children){hasChildren=true;break;}
const fiber=this.fiber;this.children=fiber.childrenMap;this.bdom.patch(fiber.bdom,hasChildren);fiber.appliedToDom=true;this.fiber=null;}
beforeRemove(){this._destroy();}
remove(){this.bdom.remove();}
get name(){return this.component.constructor.name;}
get subscriptions(){const render=batchedRenderFunctions.get(this);return render?getSubscriptions(render):[];}}
const TIMEOUT=Symbol("timeout");const HOOK_TIMEOUT={onWillStart:3000,onWillUpdateProps:3000,};function wrapError(fn,hookName){const error=new OwlError();const timeoutError=new OwlError();const node=getCurrent();return(...args)=>{const onError=(cause)=>{error.cause=cause;error.message=cause instanceof Error?`The following error occurred in ${hookName}: "${cause.message}"`:`Something that is not an Error was thrown in ${hookName} (see this Error's "cause" property)`;throw error;};let result;try{result=fn(...args);}
catch(cause){onError(cause);}
if(!(result instanceof Promise)){return result;}
const timeout=HOOK_TIMEOUT[hookName];if(timeout){const fiber=node.fiber;Promise.race([result.catch(()=>{}),new Promise((resolve)=>setTimeout(()=>resolve(TIMEOUT),timeout)),]).then((res)=>{if(res===TIMEOUT&&node.fiber===fiber&&node.status<=2){timeoutError.message=`${hookName}'s promise hasn't resolved after ${timeout / 1000} seconds`;console.log(timeoutError);}});}
return result.catch(onError);};}
function onWillStart(fn){const node=getCurrent();const decorate=node.app.dev?wrapError:(fn)=>fn;node.willStart.push(decorate(fn.bind(node.component),"onWillStart"));}
function onWillUpdateProps(fn){const node=getCurrent();const decorate=node.app.dev?wrapError:(fn)=>fn;node.willUpdateProps.push(decorate(fn.bind(node.component),"onWillUpdateProps"));}
function onMounted(fn){const node=getCurrent();const decorate=node.app.dev?wrapError:(fn)=>fn;node.mounted.push(decorate(fn.bind(node.component),"onMounted"));}
function onWillPatch(fn){const node=getCurrent();const decorate=node.app.dev?wrapError:(fn)=>fn;node.willPatch.unshift(decorate(fn.bind(node.component),"onWillPatch"));}
function onPatched(fn){const node=getCurrent();const decorate=node.app.dev?wrapError:(fn)=>fn;node.patched.push(decorate(fn.bind(node.component),"onPatched"));}
function onWillUnmount(fn){const node=getCurrent();const decorate=node.app.dev?wrapError:(fn)=>fn;node.willUnmount.unshift(decorate(fn.bind(node.component),"onWillUnmount"));}
function onWillDestroy(fn){const node=getCurrent();const decorate=node.app.dev?wrapError:(fn)=>fn;node.willDestroy.push(decorate(fn.bind(node.component),"onWillDestroy"));}
function onWillRender(fn){const node=getCurrent();const renderFn=node.renderFn;const decorate=node.app.dev?wrapError:(fn)=>fn;fn=decorate(fn.bind(node.component),"onWillRender");node.renderFn=()=>{fn();return renderFn();};}
function onRendered(fn){const node=getCurrent();const renderFn=node.renderFn;const decorate=node.app.dev?wrapError:(fn)=>fn;fn=decorate(fn.bind(node.component),"onRendered");node.renderFn=()=>{const result=renderFn();fn();return result;};}
function onError(callback){const node=getCurrent();let handlers=nodeErrorHandlers.get(node);if(!handlers){handlers=[];nodeErrorHandlers.set(node,handlers);}
handlers.push(callback.bind(node.component));}
class Component{constructor(props,env,node){this.props=props;this.env=env;this.__owl__=node;}
setup(){}
render(deep=false){this.__owl__.render(deep===true);}}
Component.template="";const VText=text("").constructor;class VPortal extends VText{constructor(selector,content){super("");this.target=null;this.selector=selector;this.content=content;}
mount(parent,anchor){super.mount(parent,anchor);this.target=document.querySelector(this.selector);if(this.target){this.content.mount(this.target,null);}
else{this.content.mount(parent,anchor);}}
beforeRemove(){this.content.beforeRemove();}
remove(){if(this.content){super.remove();this.content.remove();this.content=null;}}
patch(other){super.patch(other);if(this.content){this.content.patch(other.content,true);}
else{this.content=other.content;this.content.mount(this.target,null);}}}
function portalTemplate(app,bdom,helpers){let{callSlot}=helpers;return function template(ctx,node,key=""){return new VPortal(ctx.props.target,callSlot(ctx,node,key,"default",false,null));};}
class Portal extends Component{setup(){const node=this.__owl__;onMounted(()=>{const portal=node.bdom;if(!portal.target){const target=document.querySelector(this.props.target);if(target){portal.content.moveBeforeDOMNode(target.firstChild,target);}
else{throw new OwlError("invalid portal target");}}});onWillUnmount(()=>{const portal=node.bdom;portal.remove();});}}
Portal.template="__portal__";Portal.props={target:{type:String,},slots:true,};const isUnionType=(t)=>Array.isArray(t);const isBaseType=(t)=>typeof t!=="object";const isValueType=(t)=>typeof t==="object"&&t&&"value"in t;function isOptional(t){return typeof t==="object"&&"optional"in t?t.optional||false:false;}
function describeType(type){return type==="*"||type===true?"value":type.name.toLowerCase();}
function describe(info){if(isBaseType(info)){return describeType(info);}
else if(isUnionType(info)){return info.map(describe).join(" or ");}
else if(isValueType(info)){return String(info.value);}
if("element"in info){return`list of ${describe({ type: info.element, optional: false })}s`;}
if("shape"in info){return`object`;}
return describe(info.type||"*");}
function toSchema(spec){return Object.fromEntries(spec.map((e)=>e.endsWith("?")?[e.slice(0,-1),{optional:true}]:[e,{type:"*",optional:false}]));}
function validate(obj,spec){let errors=validateSchema(obj,spec);if(errors.length){throw new OwlError("Invalid object: "+errors.join(", "));}}
function validateSchema(obj,schema){if(Array.isArray(schema)){schema=toSchema(schema);}
obj=toRaw(obj);let errors=[];for(let key in obj){if(key in schema){let result=validateType(key,obj[key],schema[key]);if(result){errors.push(result);}}
else if(!("*"in schema)){errors.push(`unknown key '${key}'`);}}
for(let key in schema){const spec=schema[key];if(key!=="*"&&!isOptional(spec)&&!(key in obj)){const isObj=typeof spec==="object"&&!Array.isArray(spec);const isAny=spec==="*"||(isObj&&"type"in spec?spec.type==="*":isObj);let detail=isAny?"":` (should be a ${describe(spec)})`;errors.push(`'${key}' is missing${detail}`);}}
return errors;}
function validateBaseType(key,value,type){if(typeof type==="function"){if(typeof value==="object"){if(!(value instanceof type)){return`'${key}' is not a ${describeType(type)}`;}}
else if(typeof value!==type.name.toLowerCase()){return`'${key}' is not a ${describeType(type)}`;}}
return null;}
function validateArrayType(key,value,descr){if(!Array.isArray(value)){return`'${key}' is not a list of ${describe(descr)}s`;}
for(let i=0;i<value.length;i++){const error=validateType(`${key}[${i}]`,value[i],descr);if(error){return error;}}
return null;}
function validateType(key,value,descr){if(value===undefined){return isOptional(descr)?null:`'${key}' is undefined (should be a ${describe(descr)})`;}
else if(isBaseType(descr)){return validateBaseType(key,value,descr);}
else if(isValueType(descr)){return value===descr.value?null:`'${key}' is not equal to '${descr.value}'`;}
else if(isUnionType(descr)){let validDescr=descr.find((p)=>!validateType(key,value,p));return validDescr?null:`'${key}' is not a ${describe(descr)}`;}
let result=null;if("element"in descr){result=validateArrayType(key,value,descr.element);}
else if("shape"in descr){if(typeof value!=="object"||Array.isArray(value)){result=`'${key}' is not an object`;}
else{const errors=validateSchema(value,descr.shape);if(errors.length){result=`'${key}' doesn't have the correct shape (${errors.join(", ")})`;}}}
else if("values"in descr){if(typeof value!=="object"||Array.isArray(value)){result=`'${key}' is not an object`;}
else{const errors=Object.entries(value).map(([key,value])=>validateType(key,value,descr.values)).filter(Boolean);if(errors.length){result=`some of the values in '${key}' are invalid (${errors.join(", ")})`;}}}
if("type"in descr&&!result){result=validateType(key,value,descr.type);}
if("validate"in descr&&!result){result=!descr.validate(value)?`'${key}' is not valid`:null;}
return result;}
const ObjectCreate=Object.create;function withDefault(value,defaultValue){return value===undefined||value===null||value===false?defaultValue:value;}
function callSlot(ctx,parent,key,name,dynamic,extra,defaultContent){key=key+"__slot_"+name;const slots=ctx.props.slots||{};const{__render,__ctx,__scope}=slots[name]||{};const slotScope=ObjectCreate(__ctx||{});if(__scope){slotScope[__scope]=extra;}
const slotBDom=__render?__render(slotScope,parent,key):null;if(defaultContent){let child1=undefined;let child2=undefined;if(slotBDom){child1=dynamic?toggler(name,slotBDom):slotBDom;}
else{child2=defaultContent(ctx,parent,key);}
return multi([child1,child2]);}
return slotBDom||text("");}
function capture(ctx){const result=ObjectCreate(ctx);for(let k in ctx){result[k]=ctx[k];}
return result;}
function withKey(elem,k){elem.key=k;return elem;}
function prepareList(collection){let keys;let values;if(Array.isArray(collection)){keys=collection;values=collection;}
else if(collection instanceof Map){keys=[...collection.keys()];values=[...collection.values()];}
else if(Symbol.iterator in Object(collection)){keys=[...collection];values=keys;}
else if(collection&&typeof collection==="object"){values=Object.values(collection);keys=Object.keys(collection);}
else{throw new OwlError(`Invalid loop expression: "${collection}" is not iterable`);}
const n=values.length;return[keys,values,n,new Array(n)];}
const isBoundary=Symbol("isBoundary");function setContextValue(ctx,key,value){const ctx0=ctx;while(!ctx.hasOwnProperty(key)&&!ctx.hasOwnProperty(isBoundary)){const newCtx=ctx.__proto__;if(!newCtx){ctx=ctx0;break;}
ctx=newCtx;}
ctx[key]=value;}
function toNumber(val){const n=parseFloat(val);return isNaN(n)?val:n;}
function shallowEqual(l1,l2){for(let i=0,l=l1.length;i<l;i++){if(l1[i]!==l2[i]){return false;}}
return true;}
class LazyValue{constructor(fn,ctx,component,node,key){this.fn=fn;this.ctx=capture(ctx);this.component=component;this.node=node;this.key=key;}
evaluate(){return this.fn.call(this.component,this.ctx,this.node,this.key);}
toString(){return this.evaluate().toString();}}
function safeOutput(value,defaultValue){if(value===undefined||value===null){return defaultValue?toggler("default",defaultValue):toggler("undefined",text(""));}
let safeKey;let block;switch(typeof value){case"object":if(value instanceof Markup){safeKey=`string_safe`;block=html(value);}
else if(value instanceof LazyValue){safeKey=`lazy_value`;block=value.evaluate();}
else if(value instanceof String){safeKey="string_unsafe";block=text(value);}
else{safeKey="block_safe";block=value;}
break;case"string":safeKey="string_unsafe";block=text(value);break;default:safeKey="string_unsafe";block=text(String(value));}
return toggler(safeKey,block);}
function validateProps(name,props,comp){const ComponentClass=typeof name!=="string"?name:comp.constructor.components[name];if(!ComponentClass){return;}
const schema=ComponentClass.props;if(!schema){if(comp.__owl__.app.warnIfNoStaticProps){console.warn(`Component '${ComponentClass.name}' does not have a static props description`);}
return;}
const defaultProps=ComponentClass.defaultProps;if(defaultProps){let isMandatory=(name)=>Array.isArray(schema)?schema.includes(name):name in schema&&!("*"in schema)&&!isOptional(schema[name]);for(let p in defaultProps){if(isMandatory(p)){throw new OwlError(`A default value cannot be defined for a mandatory prop (name: '${p}', component: ${ComponentClass.name})`);}}}
const errors=validateSchema(props,schema);if(errors.length){throw new OwlError(`Invalid props for component '${ComponentClass.name}': `+errors.join(", "));}}
function makeRefWrapper(node){let refNames=new Set();return(name,fn)=>{if(refNames.has(name)){throw new OwlError(`Cannot set the same ref more than once in the same component, ref "${name}" was set multiple times in ${node.name}`);}
refNames.add(name);return fn;};}
const helpers={withDefault,zero:Symbol("zero"),isBoundary,callSlot,capture,withKey,prepareList,setContextValue,shallowEqual,toNumber,validateProps,LazyValue,safeOutput,createCatcher,markRaw,OwlError,makeRefWrapper,};function parseXML(xml){const parser=new DOMParser();const doc=parser.parseFromString(xml,"text/xml");if(doc.getElementsByTagName("parsererror").length){let msg="Invalid XML in template.";const parsererrorText=doc.getElementsByTagName("parsererror")[0].textContent;if(parsererrorText){msg+="\nThe parser has produced the following error message:\n"+parsererrorText;const re=/\d+/g;const firstMatch=re.exec(parsererrorText);if(firstMatch){const lineNumber=Number(firstMatch[0]);const line=xml.split("\n")[lineNumber-1];const secondMatch=re.exec(parsererrorText);if(line&&secondMatch){const columnIndex=Number(secondMatch[0])-1;if(line[columnIndex]){msg+=`\nThe error might be located at xml line ${lineNumber} column ${columnIndex}\n`+`${line}\n${"-".repeat(columnIndex - 1)}^`;}}}}
throw new OwlError(msg);}
return doc;}
const bdom={text,createBlock,list,multi,html,toggler,comment};class TemplateSet{constructor(config={}){this.rawTemplates=Object.create(globalTemplates);this.templates={};this.Portal=Portal;this.dev=config.dev||false;this.translateFn=config.translateFn;this.translatableAttributes=config.translatableAttributes;if(config.templates){if(config.templates instanceof Document||typeof config.templates==="string"){this.addTemplates(config.templates);}
else{for(const name in config.templates){this.addTemplate(name,config.templates[name]);}}}
this.getRawTemplate=config.getTemplate;this.customDirectives=config.customDirectives||{};this.runtimeUtils={...helpers,__globals__:config.globalValues||{}};this.hasGlobalValues=Boolean(config.globalValues&&Object.keys(config.globalValues).length);}
static registerTemplate(name,fn){globalTemplates[name]=fn;}
addTemplate(name,template){if(name in this.rawTemplates){if(!this.dev){return;}
const rawTemplate=this.rawTemplates[name];const currentAsString=typeof rawTemplate==="string"?rawTemplate:rawTemplate instanceof Element?rawTemplate.outerHTML:rawTemplate.toString();const newAsString=typeof template==="string"?template:template.outerHTML;if(currentAsString===newAsString){return;}
throw new OwlError(`Template ${name} already defined with different content`);}
this.rawTemplates[name]=template;}
addTemplates(xml){if(!xml){return;}
xml=xml instanceof Document?xml:parseXML(xml);for(const template of xml.querySelectorAll("[t-name]")){const name=template.getAttribute("t-name");this.addTemplate(name,template);}}
getTemplate(name){var _a;if(!(name in this.templates)){const rawTemplate=((_a=this.getRawTemplate)===null||_a===void 0?void 0:_a.call(this,name))||this.rawTemplates[name];if(rawTemplate===undefined){let extraInfo="";try{const componentName=getCurrent().component.constructor.name;extraInfo=` (for component "${componentName}")`;}
catch{}
throw new OwlError(`Missing template: "${name}"${extraInfo}`);}
const isFn=typeof rawTemplate==="function"&&!(rawTemplate instanceof Element);const templateFn=isFn?rawTemplate:this._compileTemplate(name,rawTemplate);const templates=this.templates;this.templates[name]=function(context,parent){return templates[name].call(this,context,parent);};const template=templateFn(this,bdom,this.runtimeUtils);this.templates[name]=template;}
return this.templates[name];}
_compileTemplate(name,template){throw new OwlError(`Unable to compile a template. Please use owl full build instead`);}
callTemplate(owner,subTemplate,ctx,parent,key){const template=this.getTemplate(subTemplate);return toggler(subTemplate,template.call(owner,ctx,parent,key+subTemplate));}}
const globalTemplates={};function xml(...args){const name=`__template__${xml.nextId++}`;const value=String.raw(...args);globalTemplates[name]=value;return name;}
xml.nextId=1;TemplateSet.registerTemplate("__portal__",portalTemplate);const RESERVED_WORDS="true,false,NaN,null,undefined,debugger,console,window,in,instanceof,new,function,return,eval,void,Math,RegExp,Array,Object,Date,__globals__".split(",");const WORD_REPLACEMENT=Object.assign(Object.create(null),{and:"&&",or:"||",gt:">",gte:">=",lt:"<",lte:"<=",});const STATIC_TOKEN_MAP=Object.assign(Object.create(null),{"{":"LEFT_BRACE","}":"RIGHT_BRACE","[":"LEFT_BRACKET","]":"RIGHT_BRACKET",":":"COLON",",":"COMMA","(":"LEFT_PAREN",")":"RIGHT_PAREN",});const OPERATORS="...,.,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>,=,;,in ,new ,|,&,^,~".split(",");let tokenizeString=function(expr){let s=expr[0];let start=s;if(s!=="'"&&s!=='"'&&s!=="`"){return false;}
let i=1;let cur;while(expr[i]&&expr[i]!==start){cur=expr[i];s+=cur;if(cur==="\\"){i++;cur=expr[i];if(!cur){throw new OwlError("Invalid expression");}
s+=cur;}
i++;}
if(expr[i]!==start){throw new OwlError("Invalid expression");}
s+=start;if(start==="`"){return{type:"TEMPLATE_STRING",value:s,replace(replacer){return s.replace(/\$\{(.*?)\}/g,(match,group)=>{return"${"+replacer(group)+"}";});},};}
return{type:"VALUE",value:s};};let tokenizeNumber=function(expr){let s=expr[0];if(s&&s.match(/[0-9]/)){let i=1;while(expr[i]&&expr[i].match(/[0-9]|\./)){s+=expr[i];i++;}
return{type:"VALUE",value:s};}
else{return false;}};let tokenizeSymbol=function(expr){let s=expr[0];if(s&&s.match(/[a-zA-Z_\$]/)){let i=1;while(expr[i]&&expr[i].match(/\w/)){s+=expr[i];i++;}
if(s in WORD_REPLACEMENT){return{type:"OPERATOR",value:WORD_REPLACEMENT[s],size:s.length};}
return{type:"SYMBOL",value:s};}
else{return false;}};const tokenizeStatic=function(expr){const char=expr[0];if(char&&char in STATIC_TOKEN_MAP){return{type:STATIC_TOKEN_MAP[char],value:char};}
return false;};const tokenizeOperator=function(expr){for(let op of OPERATORS){if(expr.startsWith(op)){return{type:"OPERATOR",value:op};}}
return false;};const TOKENIZERS=[tokenizeString,tokenizeNumber,tokenizeOperator,tokenizeSymbol,tokenizeStatic,];function tokenize(expr){const result=[];let token=true;let error;let current=expr;try{while(token){current=current.trim();if(current){for(let tokenizer of TOKENIZERS){token=tokenizer(current);if(token){result.push(token);current=current.slice(token.size||token.value.length);break;}}}
else{token=false;}}}
catch(e){error=e;}
if(current.length||error){throw new OwlError(`Tokenizer error: could not tokenize \`${expr}\``);}
return result;}
const isLeftSeparator=(token)=>token&&(token.type==="LEFT_BRACE"||token.type==="COMMA");const isRightSeparator=(token)=>token&&(token.type==="RIGHT_BRACE"||token.type==="COMMA");function compileExprToArray(expr){const localVars=new Set();const tokens=tokenize(expr);let i=0;let stack=[];while(i<tokens.length){let token=tokens[i];let prevToken=tokens[i-1];let nextToken=tokens[i+1];let groupType=stack[stack.length-1];switch(token.type){case"LEFT_BRACE":case"LEFT_BRACKET":case"LEFT_PAREN":stack.push(token.type);break;case"RIGHT_BRACE":case"RIGHT_BRACKET":case"RIGHT_PAREN":stack.pop();}
let isVar=token.type==="SYMBOL"&&!RESERVED_WORDS.includes(token.value);if(token.type==="SYMBOL"&&!RESERVED_WORDS.includes(token.value)){if(prevToken){if(groupType==="LEFT_BRACE"&&isLeftSeparator(prevToken)&&isRightSeparator(nextToken)){tokens.splice(i+1,0,{type:"COLON",value:":"},{...token});nextToken=tokens[i+1];}
if(prevToken.type==="OPERATOR"&&prevToken.value==="."){isVar=false;}
else if(prevToken.type==="LEFT_BRACE"||prevToken.type==="COMMA"){if(nextToken&&nextToken.type==="COLON"){isVar=false;}}}}
if(token.type==="TEMPLATE_STRING"){token.value=token.replace((expr)=>compileExpr(expr));}
if(nextToken&&nextToken.type==="OPERATOR"&&nextToken.value==="=>"){if(token.type==="RIGHT_PAREN"){let j=i-1;while(j>0&&tokens[j].type!=="LEFT_PAREN"){if(tokens[j].type==="SYMBOL"&&tokens[j].originalValue){tokens[j].value=tokens[j].originalValue;localVars.add(tokens[j].value);}
j--;}}
else{localVars.add(token.value);}}
if(isVar){token.varName=token.value;if(!localVars.has(token.value)){token.originalValue=token.value;token.value=`ctx['${token.value}']`;}}
i++;}
for(const token of tokens){if(token.type==="SYMBOL"&&token.varName&&localVars.has(token.value)){token.originalValue=token.value;token.value=`_${token.value}`;token.isLocal=true;}}
return tokens;}
const paddedValues=new Map([["in "," in "]]);function compileExpr(expr){return compileExprToArray(expr).map((t)=>paddedValues.get(t.value)||t.value).join("");}
const INTERP_REGEXP=/\{\{.*?\}\}|\#\{.*?\}/g;function replaceDynamicParts(s,replacer){let matches=s.match(INTERP_REGEXP);if(matches&&matches[0].length===s.length){return`(${replacer(s.slice(2, matches[0][0] === "{" ? -2 : -1))})`;}
let r=s.replace(INTERP_REGEXP,(s)=>"${"+replacer(s.slice(2,s[0]==="{"?-2:-1))+"}");return"`"+r+"`";}
function interpolate(s){return replaceDynamicParts(s,compileExpr);}
const whitespaceRE=/\s+/g;const xmlDoc=document.implementation.createDocument(null,null,null);const MODS=new Set(["stop","capture","prevent","self","synthetic"]);let nextDataIds={};function generateId(prefix=""){nextDataIds[prefix]=(nextDataIds[prefix]||0)+1;return prefix+nextDataIds[prefix];}
function isProp(tag,key){switch(tag){case"input":return(key==="checked"||key==="indeterminate"||key==="value"||key==="readonly"||key==="readOnly"||key==="disabled");case"option":return key==="selected"||key==="disabled";case"textarea":return key==="value"||key==="readonly"||key==="readOnly"||key==="disabled";case"select":return key==="value"||key==="disabled";case"button":case"optgroup":return key==="disabled";}
return false;}
function toStringExpression(str){return`\`${str.replace(/\\/g, "\\\\").replace(/`/g,"\\`").replace(/\$\{/,"\\${")}\``;}
class BlockDescription{constructor(target,type){this.dynamicTagName=null;this.isRoot=false;this.hasDynamicChildren=false;this.children=[];this.data=[];this.childNumber=0;this.parentVar="";this.id=BlockDescription.nextBlockId++;this.varName="b"+this.id;this.blockName="block"+this.id;this.target=target;this.type=type;}
insertData(str,prefix="d"){const id=generateId(prefix);this.target.addLine(`let ${id} = ${str};`);return this.data.push(id)-1;}
insert(dom){if(this.currentDom){this.currentDom.appendChild(dom);}
else{this.dom=dom;}}
generateExpr(expr){if(this.type==="block"){const hasChildren=this.children.length;let params=this.data.length?`[${this.data.join(", ")}]`:hasChildren?"[]":"";if(hasChildren){params+=", ["+this.children.map((c)=>c.varName).join(", ")+"]";}
if(this.dynamicTagName){return`toggler(${this.dynamicTagName}, ${this.blockName}(${this.dynamicTagName})(${params}))`;}
return`${this.blockName}(${params})`;}
else if(this.type==="list"){return`list(c_block${this.id})`;}
return expr;}
asXmlString(){const t=xmlDoc.createElement("t");t.appendChild(this.dom);return t.innerHTML;}}
BlockDescription.nextBlockId=1;function createContext(parentCtx,params){return Object.assign({block:null,index:0,forceNewBlock:true,translate:parentCtx.translate,translationCtx:parentCtx.translationCtx,tKeyExpr:null,nameSpace:parentCtx.nameSpace,tModelSelectedExpr:parentCtx.tModelSelectedExpr,},params);}
class CodeTarget{constructor(name,on){this.indentLevel=0;this.loopLevel=0;this.code=[];this.hasRoot=false;this.hasCache=false;this.shouldProtectScope=false;this.hasRefWrapper=false;this.name=name;this.on=on||null;}
addLine(line,idx){const prefix=new Array(this.indentLevel+2).join("  ");if(idx===undefined){this.code.push(prefix+line);}
else{this.code.splice(idx,0,prefix+line);}}
generateCode(){let result=[];result.push(`function ${this.name}(ctx, node, key = "") {`);if(this.shouldProtectScope){result.push(`  ctx = Object.create(ctx);`);result.push(`  ctx[isBoundary] = 1`);}
if(this.hasRefWrapper){result.push(`  let refWrapper = makeRefWrapper(this.__owl__);`);}
if(this.hasCache){result.push(`  let cache = ctx.cache || {};`);result.push(`  let nextCache = ctx.cache = {};`);}
for(let line of this.code){result.push(line);}
if(!this.hasRoot){result.push(`return text('');`);}
result.push(`}`);return result.join("\n  ");}
currentKey(ctx){let key=this.loopLevel?`key${this.loopLevel}`:"key";if(ctx.tKeyExpr){key=`${ctx.tKeyExpr} + ${key}`;}
return key;}}
const TRANSLATABLE_ATTRS=["alt","aria-label","aria-placeholder","aria-roledescription","aria-valuetext","label","placeholder","title",];const translationRE=/^(\s*)([\s\S]+?)(\s*)$/;class CodeGenerator{constructor(ast,options){this.blocks=[];this.nextBlockId=1;this.isDebug=false;this.targets=[];this.target=new CodeTarget("template");this.translatableAttributes=TRANSLATABLE_ATTRS;this.staticDefs=[];this.slotNames=new Set();this.helpers=new Set();this.translateFn=options.translateFn||((s)=>s);if(options.translatableAttributes){const attrs=new Set(TRANSLATABLE_ATTRS);for(let attr of options.translatableAttributes){if(attr.startsWith("-")){attrs.delete(attr.slice(1));}
else{attrs.add(attr);}}
this.translatableAttributes=[...attrs];}
this.hasSafeContext=options.hasSafeContext||false;this.dev=options.dev||false;this.ast=ast;this.templateName=options.name;if(options.hasGlobalValues){this.helpers.add("__globals__");}}
generateCode(){const ast=this.ast;this.isDebug=ast.type===12;BlockDescription.nextBlockId=1;nextDataIds={};this.compileAST(ast,{block:null,index:0,forceNewBlock:false,isLast:true,translate:true,translationCtx:"",tKeyExpr:null,});let mainCode=[`  let { text, createBlock, list, multi, html, toggler, comment } = bdom;`];if(this.helpers.size){mainCode.push(`let { ${[...this.helpers].join(", ")} } = helpers;`);}
if(this.templateName){mainCode.push(`// Template name: "${this.templateName}"`);}
for(let{id,expr}of this.staticDefs){mainCode.push(`const ${id} = ${expr};`);}
if(this.blocks.length){mainCode.push(``);for(let block of this.blocks){if(block.dom){let xmlString=toStringExpression(block.asXmlString());if(block.dynamicTagName){xmlString=xmlString.replace(/^`<\w+/,`\`<\${tag || '${block.dom.nodeName}'}`);xmlString=xmlString.replace(/\w+>`$/,`\${tag || '${block.dom.nodeName}'}>\``);mainCode.push(`let ${block.blockName} = tag => createBlock(${xmlString});`);}
else{mainCode.push(`let ${block.blockName} = createBlock(${xmlString});`);}}}}
if(this.targets.length){for(let fn of this.targets){mainCode.push("");mainCode=mainCode.concat(fn.generateCode());}}
mainCode.push("");mainCode=mainCode.concat("return "+this.target.generateCode());const code=mainCode.join("\n  ");if(this.isDebug){const msg=`[Owl Debug]\n${code}`;console.log(msg);}
return code;}
compileInNewTarget(prefix,ast,ctx,on){const name=generateId(prefix);const initialTarget=this.target;const target=new CodeTarget(name,on);this.targets.push(target);this.target=target;this.compileAST(ast,createContext(ctx));this.target=initialTarget;return name;}
addLine(line,idx){this.target.addLine(line,idx);}
define(varName,expr){this.addLine(`const ${varName} = ${expr};`);}
insertAnchor(block,index=block.children.length){const tag=`block-child-${index}`;const anchor=xmlDoc.createElement(tag);block.insert(anchor);}
createBlock(parentBlock,type,ctx){const hasRoot=this.target.hasRoot;const block=new BlockDescription(this.target,type);if(!hasRoot){this.target.hasRoot=true;block.isRoot=true;}
if(parentBlock){parentBlock.children.push(block);if(parentBlock.type==="list"){block.parentVar=`c_block${parentBlock.id}`;}}
return block;}
insertBlock(expression,block,ctx){let blockExpr=block.generateExpr(expression);if(block.parentVar){let key=this.target.currentKey(ctx);this.helpers.add("withKey");this.addLine(`${block.parentVar}[${ctx.index}] = withKey(${blockExpr}, ${key});`);return;}
if(ctx.tKeyExpr){blockExpr=`toggler(${ctx.tKeyExpr}, ${blockExpr})`;}
if(block.isRoot){if(this.target.on){blockExpr=this.wrapWithEventCatcher(blockExpr,this.target.on);}
this.addLine(`return ${blockExpr};`);}
else{this.define(block.varName,blockExpr);}}
captureExpression(expr,forceCapture=false){if(!forceCapture&&!expr.includes("=>")){return compileExpr(expr);}
const tokens=compileExprToArray(expr);const mapping=new Map();return tokens.map((tok)=>{if(tok.varName&&!tok.isLocal){if(!mapping.has(tok.varName)){const varId=generateId("v");mapping.set(tok.varName,varId);this.define(varId,tok.value);}
tok.value=mapping.get(tok.varName);}
return tok.value;}).join("");}
translate(str,translationCtx){const match=translationRE.exec(str);return match[1]+this.translateFn(match[2],translationCtx)+match[3];}
compileAST(ast,ctx){switch(ast.type){case 1:return this.compileComment(ast,ctx);case 0:return this.compileText(ast,ctx);case 2:return this.compileTDomNode(ast,ctx);case 4:return this.compileTEsc(ast,ctx);case 8:return this.compileTOut(ast,ctx);case 5:return this.compileTIf(ast,ctx);case 9:return this.compileTForeach(ast,ctx);case 10:return this.compileTKey(ast,ctx);case 3:return this.compileMulti(ast,ctx);case 7:return this.compileTCall(ast,ctx);case 15:return this.compileTCallBlock(ast,ctx);case 6:return this.compileTSet(ast,ctx);case 11:return this.compileComponent(ast,ctx);case 12:return this.compileDebug(ast,ctx);case 13:return this.compileLog(ast,ctx);case 14:return this.compileTSlot(ast,ctx);case 16:return this.compileTTranslation(ast,ctx);case 17:return this.compileTTranslationContext(ast,ctx);case 18:return this.compileTPortal(ast,ctx);}}
compileDebug(ast,ctx){this.addLine(`debugger;`);if(ast.content){return this.compileAST(ast.content,ctx);}
return null;}
compileLog(ast,ctx){this.addLine(`console.log(${compileExpr(ast.expr)});`);if(ast.content){return this.compileAST(ast.content,ctx);}
return null;}
compileComment(ast,ctx){let{block,forceNewBlock}=ctx;const isNewBlock=!block||forceNewBlock;if(isNewBlock){block=this.createBlock(block,"comment",ctx);this.insertBlock(`comment(${toStringExpression(ast.value)})`,block,{...ctx,forceNewBlock:forceNewBlock&&!block,});}
else{const text=xmlDoc.createComment(ast.value);block.insert(text);}
return block.varName;}
compileText(ast,ctx){let{block,forceNewBlock}=ctx;let value=ast.value;if(value&&ctx.translate!==false){value=this.translate(value,ctx.translationCtx);}
if(!ctx.inPreTag){value=value.replace(whitespaceRE," ");}
if(!block||forceNewBlock){block=this.createBlock(block,"text",ctx);this.insertBlock(`text(${toStringExpression(value)})`,block,{...ctx,forceNewBlock:forceNewBlock&&!block,});}
else{const createFn=ast.type===0?xmlDoc.createTextNode:xmlDoc.createComment;block.insert(createFn.call(xmlDoc,value));}
return block.varName;}
generateHandlerCode(rawEvent,handler){const modifiers=rawEvent.split(".").slice(1).map((m)=>{if(!MODS.has(m)){throw new OwlError(`Unknown event modifier: '${m}'`);}
return`"${m}"`;});let modifiersCode="";if(modifiers.length){modifiersCode=`${modifiers.join(",")}, `;}
return`[${modifiersCode}${this.captureExpression(handler)}, ctx]`;}
compileTDomNode(ast,ctx){var _a;let{block,forceNewBlock}=ctx;const isNewBlock=!block||forceNewBlock||ast.dynamicTag!==null||ast.ns;let codeIdx=this.target.code.length;if(isNewBlock){if((ast.dynamicTag||ctx.tKeyExpr||ast.ns)&&ctx.block){this.insertAnchor(ctx.block);}
block=this.createBlock(block,"block",ctx);this.blocks.push(block);if(ast.dynamicTag){const tagExpr=generateId("tag");this.define(tagExpr,compileExpr(ast.dynamicTag));block.dynamicTagName=tagExpr;}}
const attrs={};for(let key in ast.attrs){let expr,attrName;if(key.startsWith("t-attf")){expr=interpolate(ast.attrs[key]);const idx=block.insertData(expr,"attr");attrName=key.slice(7);attrs["block-attribute-"+idx]=attrName;}
else if(key.startsWith("t-att")){attrName=key==="t-att"?null:key.slice(6);expr=compileExpr(ast.attrs[key]);if(attrName&&isProp(ast.tag,attrName)){if(attrName==="readonly"){attrName="readOnly";}
if(attrName==="value"){expr=`new String((${expr}) === 0 ? 0 : ((${expr}) || ""))`;}
else{expr=`new Boolean(${expr})`;}
const idx=block.insertData(expr,"prop");attrs[`block-property-${idx}`]=attrName;}
else{const idx=block.insertData(expr,"attr");if(key==="t-att"){attrs[`block-attributes`]=String(idx);}
else{attrs[`block-attribute-${idx}`]=attrName;}}}
else if(this.translatableAttributes.includes(key)){const attrTranslationCtx=((_a=ast.attrsTranslationCtx)===null||_a===void 0?void 0:_a[key])||ctx.translationCtx;attrs[key]=this.translateFn(ast.attrs[key],attrTranslationCtx);}
else{expr=`"${ast.attrs[key]}"`;attrName=key;attrs[key]=ast.attrs[key];}
if(attrName==="value"&&ctx.tModelSelectedExpr){let selectedId=block.insertData(`${ctx.tModelSelectedExpr} === ${expr}`,"attr");attrs[`block-attribute-${selectedId}`]="selected";}}
let tModelSelectedExpr;if(ast.model){const{hasDynamicChildren,baseExpr,expr,eventType,shouldNumberize,shouldTrim,targetAttr,specialInitTargetAttr,}=ast.model;const baseExpression=compileExpr(baseExpr);const bExprId=generateId("bExpr");this.define(bExprId,baseExpression);const expression=compileExpr(expr);const exprId=generateId("expr");this.define(exprId,expression);const fullExpression=`${bExprId}[${exprId}]`;let idx;if(specialInitTargetAttr){let targetExpr=targetAttr in attrs&&`'${attrs[targetAttr]}'`;if(!targetExpr&&ast.attrs){const dynamicTgExpr=ast.attrs[`t-att-${targetAttr}`];if(dynamicTgExpr){targetExpr=compileExpr(dynamicTgExpr);}}
idx=block.insertData(`${fullExpression} === ${targetExpr}`,"prop");attrs[`block-property-${idx}`]=specialInitTargetAttr;}
else if(hasDynamicChildren){const bValueId=generateId("bValue");tModelSelectedExpr=`${bValueId}`;this.define(tModelSelectedExpr,fullExpression);}
else{idx=block.insertData(`${fullExpression}`,"prop");attrs[`block-property-${idx}`]=targetAttr;}
this.helpers.add("toNumber");let valueCode=`ev.target.${targetAttr}`;valueCode=shouldTrim?`${valueCode}.trim()`:valueCode;valueCode=shouldNumberize?`toNumber(${valueCode})`:valueCode;const handler=`[(ev) => { ${fullExpression} = ${valueCode}; }]`;idx=block.insertData(handler,"hdlr");attrs[`block-handler-${idx}`]=eventType;}
for(let ev in ast.on){const name=this.generateHandlerCode(ev,ast.on[ev]);const idx=block.insertData(name,"hdlr");attrs[`block-handler-${idx}`]=ev;}
if(ast.ref){if(this.dev){this.helpers.add("makeRefWrapper");this.target.hasRefWrapper=true;}
const isDynamic=INTERP_REGEXP.test(ast.ref);let name=`\`${ast.ref}\``;if(isDynamic){name=replaceDynamicParts(ast.ref,(expr)=>this.captureExpression(expr,true));}
let setRefStr=`(el) => this.__owl__.setRef((${name}), el)`;if(this.dev){setRefStr=`refWrapper(${name}, ${setRefStr})`;}
const idx=block.insertData(setRefStr,"ref");attrs["block-ref"]=String(idx);}
const nameSpace=ast.ns||ctx.nameSpace;const dom=nameSpace?xmlDoc.createElementNS(nameSpace,ast.tag):xmlDoc.createElement(ast.tag);for(const[attr,val]of Object.entries(attrs)){if(!(attr==="class"&&val==="")){dom.setAttribute(attr,val);}}
block.insert(dom);if(ast.content.length){const initialDom=block.currentDom;block.currentDom=dom;const children=ast.content;for(let i=0;i<children.length;i++){const child=ast.content[i];const subCtx=createContext(ctx,{block,index:block.childNumber,forceNewBlock:false,isLast:ctx.isLast&&i===children.length-1,tKeyExpr:ctx.tKeyExpr,nameSpace,tModelSelectedExpr,inPreTag:ctx.inPreTag||ast.tag==="pre",});this.compileAST(child,subCtx);}
block.currentDom=initialDom;}
if(isNewBlock){this.insertBlock(`${block.blockName}(ddd)`,block,ctx);if(block.children.length&&block.hasDynamicChildren){const code=this.target.code;const children=block.children.slice();let current=children.shift();for(let i=codeIdx;i<code.length;i++){if(code[i].trimStart().startsWith(`const ${current.varName} `)){code[i]=code[i].replace(`const ${current.varName}`,current.varName);current=children.shift();if(!current)
break;}}
this.addLine(`let ${block.children.map((c) => c.varName).join(", ")};`,codeIdx);}}
return block.varName;}
compileTEsc(ast,ctx){let{block,forceNewBlock}=ctx;let expr;if(ast.expr==="0"){this.helpers.add("zero");expr=`ctx[zero]`;}
else{expr=compileExpr(ast.expr);if(ast.defaultValue){this.helpers.add("withDefault");expr=`withDefault(${expr}, ${toStringExpression(ast.defaultValue)})`;}}
if(!block||forceNewBlock){block=this.createBlock(block,"text",ctx);this.insertBlock(`text(${expr})`,block,{...ctx,forceNewBlock:forceNewBlock&&!block});}
else{const idx=block.insertData(expr,"txt");const text=xmlDoc.createElement(`block-text-${idx}`);block.insert(text);}
return block.varName;}
compileTOut(ast,ctx){let{block}=ctx;if(block){this.insertAnchor(block);}
block=this.createBlock(block,"html",ctx);let blockStr;if(ast.expr==="0"){this.helpers.add("zero");blockStr=`ctx[zero]`;}
else if(ast.body){let bodyValue=null;bodyValue=BlockDescription.nextBlockId;const subCtx=createContext(ctx);this.compileAST({type:3,content:ast.body},subCtx);this.helpers.add("safeOutput");blockStr=`safeOutput(${compileExpr(ast.expr)}, b${bodyValue})`;}
else{this.helpers.add("safeOutput");blockStr=`safeOutput(${compileExpr(ast.expr)})`;}
this.insertBlock(blockStr,block,ctx);return block.varName;}
compileTIfBranch(content,block,ctx){this.target.indentLevel++;let childN=block.children.length;this.compileAST(content,createContext(ctx,{block,index:ctx.index}));if(block.children.length>childN){this.insertAnchor(block,childN);}
this.target.indentLevel--;}
compileTIf(ast,ctx,nextNode){let{block,forceNewBlock}=ctx;const codeIdx=this.target.code.length;const isNewBlock=!block||(block.type!=="multi"&&forceNewBlock);if(block){block.hasDynamicChildren=true;}
if(!block||(block.type!=="multi"&&forceNewBlock)){block=this.createBlock(block,"multi",ctx);}
this.addLine(`if (${compileExpr(ast.condition)}) {`);this.compileTIfBranch(ast.content,block,ctx);if(ast.tElif){for(let clause of ast.tElif){this.addLine(`} else if (${compileExpr(clause.condition)}) {`);this.compileTIfBranch(clause.content,block,ctx);}}
if(ast.tElse){this.addLine(`} else {`);this.compileTIfBranch(ast.tElse,block,ctx);}
this.addLine("}");if(isNewBlock){if(block.children.length){const code=this.target.code;const children=block.children.slice();let current=children.shift();for(let i=codeIdx;i<code.length;i++){if(code[i].trimStart().startsWith(`const ${current.varName} `)){code[i]=code[i].replace(`const ${current.varName}`,current.varName);current=children.shift();if(!current)
break;}}
this.addLine(`let ${block.children.map((c) => c.varName).join(", ")};`,codeIdx);}
const args=block.children.map((c)=>c.varName).join(", ");this.insertBlock(`multi([${args}])`,block,ctx);}
return block.varName;}
compileTForeach(ast,ctx){let{block}=ctx;if(block){this.insertAnchor(block);}
block=this.createBlock(block,"list",ctx);this.target.loopLevel++;const loopVar=`i${this.target.loopLevel}`;this.addLine(`ctx = Object.create(ctx);`);const vals=`v_block${block.id}`;const keys=`k_block${block.id}`;const l=`l_block${block.id}`;const c=`c_block${block.id}`;this.helpers.add("prepareList");this.define(`[${keys}, ${vals}, ${l}, ${c}]`,`prepareList(${compileExpr(ast.collection)});`);if(this.dev){this.define(`keys${block.id}`,`new Set()`);}
this.addLine(`for (let ${loopVar} = 0; ${loopVar} < ${l}; ${loopVar}++) {`);this.target.indentLevel++;this.addLine(`ctx[\`${ast.elem}\`] = ${keys}[${loopVar}];`);if(!ast.hasNoFirst){this.addLine(`ctx[\`${ast.elem}_first\`] = ${loopVar} === 0;`);}
if(!ast.hasNoLast){this.addLine(`ctx[\`${ast.elem}_last\`] = ${loopVar} === ${keys}.length - 1;`);}
if(!ast.hasNoIndex){this.addLine(`ctx[\`${ast.elem}_index\`] = ${loopVar};`);}
if(!ast.hasNoValue){this.addLine(`ctx[\`${ast.elem}_value\`] = ${vals}[${loopVar}];`);}
this.define(`key${this.target.loopLevel}`,ast.key?compileExpr(ast.key):loopVar);if(this.dev){this.helpers.add("OwlError");this.addLine(`if (keys${block.id}.has(String(key${this.target.loopLevel}))) { throw new OwlError(\`Got duplicate key in t-foreach: \${key${this.target.loopLevel}}\`)}`);this.addLine(`keys${block.id}.add(String(key${this.target.loopLevel}));`);}
let id;if(ast.memo){this.target.hasCache=true;id=generateId();this.define(`memo${id}`,compileExpr(ast.memo));this.define(`vnode${id}`,`cache[key${this.target.loopLevel}];`);this.addLine(`if (vnode${id}) {`);this.target.indentLevel++;this.addLine(`if (shallowEqual(vnode${id}.memo, memo${id})) {`);this.target.indentLevel++;this.addLine(`${c}[${loopVar}] = vnode${id};`);this.addLine(`nextCache[key${this.target.loopLevel}] = vnode${id};`);this.addLine(`continue;`);this.target.indentLevel--;this.addLine("}");this.target.indentLevel--;this.addLine("}");}
const subCtx=createContext(ctx,{block,index:loopVar});this.compileAST(ast.body,subCtx);if(ast.memo){this.addLine(`nextCache[key${this.target.loopLevel}] = Object.assign(${c}[${loopVar}], {memo: memo${id}});`);}
this.target.indentLevel--;this.target.loopLevel--;this.addLine(`}`);if(!ctx.isLast){this.addLine(`ctx = ctx.__proto__;`);}
this.insertBlock("l",block,ctx);return block.varName;}
compileTKey(ast,ctx){const tKeyExpr=generateId("tKey_");this.define(tKeyExpr,compileExpr(ast.expr));ctx=createContext(ctx,{tKeyExpr,block:ctx.block,index:ctx.index,});return this.compileAST(ast.content,ctx);}
compileMulti(ast,ctx){let{block,forceNewBlock}=ctx;const isNewBlock=!block||forceNewBlock;let codeIdx=this.target.code.length;if(isNewBlock){const n=ast.content.filter((c)=>!c.hasNoRepresentation).length;let result=null;if(n<=1){for(let child of ast.content){const blockName=this.compileAST(child,ctx);result=result||blockName;}
return result;}
block=this.createBlock(block,"multi",ctx);}
let index=0;for(let i=0,l=ast.content.length;i<l;i++){const child=ast.content[i];const forceNewBlock=!child.hasNoRepresentation;const subCtx=createContext(ctx,{block,index,forceNewBlock,isLast:ctx.isLast&&i===l-1,});this.compileAST(child,subCtx);if(forceNewBlock){index++;}}
if(isNewBlock){if(block.hasDynamicChildren&&block.children.length){const code=this.target.code;const children=block.children.slice();let current=children.shift();for(let i=codeIdx;i<code.length;i++){if(code[i].trimStart().startsWith(`const ${current.varName} `)){code[i]=code[i].replace(`const ${current.varName}`,current.varName);current=children.shift();if(!current)
break;}}
this.addLine(`let ${block.children.map((c) => c.varName).join(", ")};`,codeIdx);}
const args=block.children.map((c)=>c.varName).join(", ");this.insertBlock(`multi([${args}])`,block,ctx);}
return block.varName;}
compileTCall(ast,ctx){let{block,forceNewBlock}=ctx;let ctxVar=ctx.ctxVar||"ctx";if(ast.context){ctxVar=generateId("ctx");this.addLine(`let ${ctxVar} = ${compileExpr(ast.context)};`);}
const isDynamic=INTERP_REGEXP.test(ast.name);const subTemplate=isDynamic?interpolate(ast.name):"`"+ast.name+"`";if(block&&!forceNewBlock){this.insertAnchor(block);}
block=this.createBlock(block,"multi",ctx);if(ast.body){this.addLine(`${ctxVar} = Object.create(${ctxVar});`);this.addLine(`${ctxVar}[isBoundary] = 1;`);this.helpers.add("isBoundary");const subCtx=createContext(ctx,{ctxVar});const bl=this.compileMulti({type:3,content:ast.body},subCtx);if(bl){this.helpers.add("zero");this.addLine(`${ctxVar}[zero] = ${bl};`);}}
const key=this.generateComponentKey();if(isDynamic){const templateVar=generateId("template");if(!this.staticDefs.find((d)=>d.id==="call")){this.staticDefs.push({id:"call",expr:`app.callTemplate.bind(app)`});}
this.define(templateVar,subTemplate);this.insertBlock(`call(this, ${templateVar}, ${ctxVar}, node, ${key})`,block,{...ctx,forceNewBlock:!block,});}
else{const id=generateId(`callTemplate_`);this.staticDefs.push({id,expr:`app.getTemplate(${subTemplate})`});this.insertBlock(`${id}.call(this, ${ctxVar}, node, ${key})`,block,{...ctx,forceNewBlock:!block,});}
if(ast.body&&!ctx.isLast){this.addLine(`${ctxVar} = ${ctxVar}.__proto__;`);}
return block.varName;}
compileTCallBlock(ast,ctx){let{block,forceNewBlock}=ctx;if(block){if(!forceNewBlock){this.insertAnchor(block);}}
block=this.createBlock(block,"multi",ctx);this.insertBlock(compileExpr(ast.name),block,{...ctx,forceNewBlock:!block});return block.varName;}
compileTSet(ast,ctx){this.target.shouldProtectScope=true;this.helpers.add("isBoundary").add("withDefault");const expr=ast.value?compileExpr(ast.value||""):"null";if(ast.body){this.helpers.add("LazyValue");const bodyAst={type:3,content:ast.body};const name=this.compileInNewTarget("value",bodyAst,ctx);let key=this.target.currentKey(ctx);let value=`new LazyValue(${name}, ctx, this, node, ${key})`;value=ast.value?(value?`withDefault(${expr}, ${value})`:expr):value;this.addLine(`ctx[\`${ast.name}\`] = ${value};`);}
else{let value;if(ast.defaultValue){const defaultValue=toStringExpression(ctx.translate?this.translate(ast.defaultValue,ctx.translationCtx):ast.defaultValue);if(ast.value){value=`withDefault(${expr}, ${defaultValue})`;}
else{value=defaultValue;}}
else{value=expr;}
this.helpers.add("setContextValue");this.addLine(`setContextValue(${ctx.ctxVar || "ctx"}, "${ast.name}", ${value});`);}
return null;}
generateComponentKey(currentKey="key"){const parts=[generateId("__")];for(let i=0;i<this.target.loopLevel;i++){parts.push(`\${key${i + 1}}`);}
return`${currentKey} + \`${parts.join("__")}\``;}
formatProp(name,value,attrsTranslationCtx,translationCtx){if(name.endsWith(".translate")){const attrTranslationCtx=(attrsTranslationCtx===null||attrsTranslationCtx===void 0?void 0:attrsTranslationCtx[name])||translationCtx;value=toStringExpression(this.translateFn(value,attrTranslationCtx));}
else{value=this.captureExpression(value);}
if(name.includes(".")){let[_name,suffix]=name.split(".");name=_name;switch(suffix){case"bind":value=`(${value}).bind(this)`;break;case"alike":case"translate":break;default:throw new OwlError(`Invalid prop suffix: ${suffix}`);}}
name=/^[a-z_]+$/i.test(name)?name:`'${name}'`;return`${name}: ${value || undefined}`;}
formatPropObject(obj,attrsTranslationCtx,translationCtx){return Object.entries(obj).map(([k,v])=>this.formatProp(k,v,attrsTranslationCtx,translationCtx));}
getPropString(props,dynProps){let propString=`{${props.join(",")}}`;if(dynProps){propString=`Object.assign({}, ${compileExpr(dynProps)}${props.length ? ", " + propString : ""})`;}
return propString;}
compileComponent(ast,ctx){let{block}=ctx;const hasSlotsProp="slots"in(ast.props||{});const props=ast.props?this.formatPropObject(ast.props,ast.propsTranslationCtx,ctx.translationCtx):[];let slotDef="";if(ast.slots){let ctxStr="ctx";if(this.target.loopLevel||!this.hasSafeContext){ctxStr=generateId("ctx");this.helpers.add("capture");this.define(ctxStr,`capture(ctx)`);}
let slotStr=[];for(let slotName in ast.slots){const slotAst=ast.slots[slotName];const params=[];if(slotAst.content){const name=this.compileInNewTarget("slot",slotAst.content,ctx,slotAst.on);params.push(`__render: ${name}.bind(this), __ctx: ${ctxStr}`);}
const scope=ast.slots[slotName].scope;if(scope){params.push(`__scope: "${scope}"`);}
if(ast.slots[slotName].attrs){params.push(...this.formatPropObject(ast.slots[slotName].attrs,ast.slots[slotName].attrsTranslationCtx,ctx.translationCtx));}
const slotInfo=`{${params.join(", ")}}`;slotStr.push(`'${slotName}': ${slotInfo}`);}
slotDef=`{${slotStr.join(", ")}}`;}
if(slotDef&&!(ast.dynamicProps||hasSlotsProp)){this.helpers.add("markRaw");props.push(`slots: markRaw(${slotDef})`);}
let propString=this.getPropString(props,ast.dynamicProps);let propVar;if((slotDef&&(ast.dynamicProps||hasSlotsProp))||this.dev){propVar=generateId("props");this.define(propVar,propString);propString=propVar;}
if(slotDef&&(ast.dynamicProps||hasSlotsProp)){this.helpers.add("markRaw");this.addLine(`${propVar}.slots = markRaw(Object.assign(${slotDef}, ${propVar}.slots))`);}
let expr;if(ast.isDynamic){expr=generateId("Comp");this.define(expr,compileExpr(ast.name));}
else{expr=`\`${ast.name}\``;}
if(this.dev){this.addLine(`helpers.validateProps(${expr}, ${propVar}, this);`);}
if(block&&(ctx.forceNewBlock===false||ctx.tKeyExpr)){this.insertAnchor(block);}
let keyArg=this.generateComponentKey();if(ctx.tKeyExpr){keyArg=`${ctx.tKeyExpr} + ${keyArg}`;}
let id=generateId("comp");const propList=[];for(let p in ast.props||{}){let[name,suffix]=p.split(".");if(!suffix){propList.push(`"${name}"`);}}
this.staticDefs.push({id,expr:`app.createComponent(${ast.isDynamic ? null : expr}, ${!ast.isDynamic}, ${!!ast.slots}, ${!!ast.dynamicProps}, [${propList}])`,});if(ast.isDynamic){keyArg=`(${expr}).name + ${keyArg}`;}
let blockExpr=`${id}(${propString}, ${keyArg}, node, this, ${ast.isDynamic ? expr : null})`;if(ast.isDynamic){blockExpr=`toggler(${expr}, ${blockExpr})`;}
if(ast.on){blockExpr=this.wrapWithEventCatcher(blockExpr,ast.on);}
block=this.createBlock(block,"multi",ctx);this.insertBlock(blockExpr,block,ctx);return block.varName;}
wrapWithEventCatcher(expr,on){this.helpers.add("createCatcher");let name=generateId("catcher");let spec={};let handlers=[];for(let ev in on){let handlerId=generateId("hdlr");let idx=handlers.push(handlerId)-1;spec[ev]=idx;const handler=this.generateHandlerCode(ev,on[ev]);this.define(handlerId,handler);}
this.staticDefs.push({id:name,expr:`createCatcher(${JSON.stringify(spec)})`});return`${name}(${expr}, [${handlers.join(",")}])`;}
compileTSlot(ast,ctx){this.helpers.add("callSlot");let{block}=ctx;let blockString;let slotName;let dynamic=false;let isMultiple=false;if(ast.name.match(INTERP_REGEXP)){dynamic=true;isMultiple=true;slotName=interpolate(ast.name);}
else{slotName="'"+ast.name+"'";isMultiple=isMultiple||this.slotNames.has(ast.name);this.slotNames.add(ast.name);}
const attrs={...ast.attrs};const dynProps=attrs["t-props"];delete attrs["t-props"];let key=this.target.loopLevel?`key${this.target.loopLevel}`:"key";if(isMultiple){key=this.generateComponentKey(key);}
const props=ast.attrs?this.formatPropObject(attrs,ast.attrsTranslationCtx,ctx.translationCtx):[];const scope=this.getPropString(props,dynProps);if(ast.defaultContent){const name=this.compileInNewTarget("defaultContent",ast.defaultContent,ctx);blockString=`callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope}, ${name}.bind(this))`;}
else{if(dynamic){let name=generateId("slot");this.define(name,slotName);blockString=`toggler(${name}, callSlot(ctx, node, ${key}, ${name}, ${dynamic}, ${scope}))`;}
else{blockString=`callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope})`;}}
if(ast.on){blockString=this.wrapWithEventCatcher(blockString,ast.on);}
if(block){this.insertAnchor(block);}
block=this.createBlock(block,"multi",ctx);this.insertBlock(blockString,block,{...ctx,forceNewBlock:false});return block.varName;}
compileTTranslation(ast,ctx){if(ast.content){return this.compileAST(ast.content,Object.assign({},ctx,{translate:false}));}
return null;}
compileTTranslationContext(ast,ctx){if(ast.content){return this.compileAST(ast.content,Object.assign({},ctx,{translationCtx:ast.translationCtx}));}
return null;}
compileTPortal(ast,ctx){if(!this.staticDefs.find((d)=>d.id==="Portal")){this.staticDefs.push({id:"Portal",expr:`app.Portal`});}
let{block}=ctx;const name=this.compileInNewTarget("slot",ast.content,ctx);let ctxStr="ctx";if(this.target.loopLevel||!this.hasSafeContext){ctxStr=generateId("ctx");this.helpers.add("capture");this.define(ctxStr,`capture(ctx)`);}
let id=generateId("comp");this.staticDefs.push({id,expr:`app.createComponent(null, false, true, false, false)`,});const target=compileExpr(ast.target);const key=this.generateComponentKey();const blockString=`${id}({target: ${target},slots: {'default': {__render: ${name}.bind(this), __ctx: ${ctxStr}}}}, ${key}, node, ctx, Portal)`;if(block){this.insertAnchor(block);}
block=this.createBlock(block,"multi",ctx);this.insertBlock(blockString,block,{...ctx,forceNewBlock:false});return block.varName;}}
const cache=new WeakMap();function parse(xml,customDir){const ctx={inPreTag:false,customDirectives:customDir,};if(typeof xml==="string"){const elem=parseXML(`<t>${xml}</t>`).firstChild;return _parse(elem,ctx);}
let ast=cache.get(xml);if(!ast){ast=_parse(xml.cloneNode(true),ctx);cache.set(xml,ast);}
return ast;}
function _parse(xml,ctx){normalizeXML(xml);return parseNode(xml,ctx)||{type:0,value:""};}
function parseNode(node,ctx){if(!(node instanceof Element)){return parseTextCommentNode(node,ctx);}
return(parseTCustom(node,ctx)||parseTDebugLog(node,ctx)||parseTForEach(node,ctx)||parseTIf(node,ctx)||parseTPortal(node,ctx)||parseTCall(node,ctx)||parseTCallBlock(node)||parseTTranslation(node,ctx)||parseTTranslationContext(node,ctx)||parseTKey(node,ctx)||parseTEscNode(node,ctx)||parseTOutNode(node,ctx)||parseTSlot(node,ctx)||parseComponent(node,ctx)||parseDOMNode(node,ctx)||parseTSetNode(node,ctx)||parseTNode(node,ctx));}
function parseTNode(node,ctx){if(node.tagName!=="t"){return null;}
return parseChildNodes(node,ctx);}
const lineBreakRE=/[\r\n]/;function parseTextCommentNode(node,ctx){if(node.nodeType===Node.TEXT_NODE){let value=node.textContent||"";if(!ctx.inPreTag&&lineBreakRE.test(value)&&!value.trim()){return null;}
return{type:0,value};}
else if(node.nodeType===Node.COMMENT_NODE){return{type:1,value:node.textContent||""};}
return null;}
function parseTCustom(node,ctx){if(!ctx.customDirectives){return null;}
const nodeAttrsNames=node.getAttributeNames();for(let attr of nodeAttrsNames){if(attr==="t-custom"||attr==="t-custom-"){throw new OwlError("Missing custom directive name with t-custom directive");}
if(attr.startsWith("t-custom-")){const directiveName=attr.split(".")[0].slice(9);const customDirective=ctx.customDirectives[directiveName];if(!customDirective){throw new OwlError(`Custom directive "${directiveName}" is not defined`);}
const value=node.getAttribute(attr);const modifiers=attr.split(".").slice(1);node.removeAttribute(attr);try{customDirective(node,value,modifiers);}
catch(error){throw new OwlError(`Custom directive "${directiveName}" throw the following error: ${error}`);}
return parseNode(node,ctx);}}
return null;}
function parseTDebugLog(node,ctx){if(node.hasAttribute("t-debug")){node.removeAttribute("t-debug");const content=parseNode(node,ctx);const ast={type:12,content,};if(content===null||content===void 0?void 0:content.hasNoRepresentation){ast.hasNoRepresentation=true;}
return ast;}
if(node.hasAttribute("t-log")){const expr=node.getAttribute("t-log");node.removeAttribute("t-log");const content=parseNode(node,ctx);const ast={type:13,expr,content,};if(content===null||content===void 0?void 0:content.hasNoRepresentation){ast.hasNoRepresentation=true;}
return ast;}
return null;}
const hasDotAtTheEnd=/\.[\w_]+\s*$/;const hasBracketsAtTheEnd=/\[[^\[]+\]\s*$/;const ROOT_SVG_TAGS=new Set(["svg","g","path"]);function parseDOMNode(node,ctx){const{tagName}=node;const dynamicTag=node.getAttribute("t-tag");node.removeAttribute("t-tag");if(tagName==="t"&&!dynamicTag){return null;}
if(tagName.startsWith("block-")){throw new OwlError(`Invalid tag name: '${tagName}'`);}
ctx=Object.assign({},ctx);if(tagName==="pre"){ctx.inPreTag=true;}
let ns=!ctx.nameSpace&&ROOT_SVG_TAGS.has(tagName)?"http://www.w3.org/2000/svg":null;const ref=node.getAttribute("t-ref");node.removeAttribute("t-ref");const nodeAttrsNames=node.getAttributeNames();let attrs=null;let attrsTranslationCtx=null;let on=null;let model=null;for(let attr of nodeAttrsNames){const value=node.getAttribute(attr);if(attr==="t-on"||attr==="t-on-"){throw new OwlError("Missing event name with t-on directive");}
if(attr.startsWith("t-on-")){on=on||{};on[attr.slice(5)]=value;}
else if(attr.startsWith("t-model")){if(!["input","select","textarea"].includes(tagName)){throw new OwlError("The t-model directive only works with <input>, <textarea> and <select>");}
let baseExpr,expr;if(hasDotAtTheEnd.test(value)){const index=value.lastIndexOf(".");baseExpr=value.slice(0,index);expr=`'${value.slice(index + 1)}'`;}
else if(hasBracketsAtTheEnd.test(value)){const index=value.lastIndexOf("[");baseExpr=value.slice(0,index);expr=value.slice(index+1,-1);}
else{throw new OwlError(`Invalid t-model expression: "${value}" (it should be assignable)`);}
const typeAttr=node.getAttribute("type");const isInput=tagName==="input";const isSelect=tagName==="select";const isCheckboxInput=isInput&&typeAttr==="checkbox";const isRadioInput=isInput&&typeAttr==="radio";const hasTrimMod=attr.includes(".trim");const hasLazyMod=hasTrimMod||attr.includes(".lazy");const hasNumberMod=attr.includes(".number");const eventType=isRadioInput?"click":isSelect||hasLazyMod?"change":"input";model={baseExpr,expr,targetAttr:isCheckboxInput?"checked":"value",specialInitTargetAttr:isRadioInput?"checked":null,eventType,hasDynamicChildren:false,shouldTrim:hasTrimMod,shouldNumberize:hasNumberMod,};if(isSelect){ctx=Object.assign({},ctx);ctx.tModelInfo=model;}}
else if(attr.startsWith("block-")){throw new OwlError(`Invalid attribute: '${attr}'`);}
else if(attr==="xmlns"){ns=value;}
else if(attr.startsWith("t-translation-context-")){const attrName=attr.slice(22);attrsTranslationCtx=attrsTranslationCtx||{};attrsTranslationCtx[attrName]=value;}
else if(attr!=="t-name"){if(attr.startsWith("t-")&&!attr.startsWith("t-att")){throw new OwlError(`Unknown QWeb directive: '${attr}'`);}
const tModel=ctx.tModelInfo;if(tModel&&["t-att-value","t-attf-value"].includes(attr)){tModel.hasDynamicChildren=true;}
attrs=attrs||{};attrs[attr]=value;}}
if(ns){ctx.nameSpace=ns;}
const children=parseChildren(node,ctx);return{type:2,tag:tagName,dynamicTag,attrs,attrsTranslationCtx,on,ref,content:children,model,ns,};}
function parseTEscNode(node,ctx){if(!node.hasAttribute("t-esc")){return null;}
const escValue=node.getAttribute("t-esc");node.removeAttribute("t-esc");const tesc={type:4,expr:escValue,defaultValue:node.textContent||"",};let ref=node.getAttribute("t-ref");node.removeAttribute("t-ref");const ast=parseNode(node,ctx);if(!ast){return tesc;}
if(ast.type===2){return{...ast,ref,content:[tesc],};}
return tesc;}
function parseTOutNode(node,ctx){if(!node.hasAttribute("t-out")&&!node.hasAttribute("t-raw")){return null;}
if(node.hasAttribute("t-raw")){console.warn(`t-raw has been deprecated in favor of t-out. If the value to render is not wrapped by the "markup" function, it will be escaped`);}
const expr=(node.getAttribute("t-out")||node.getAttribute("t-raw"));node.removeAttribute("t-out");node.removeAttribute("t-raw");const tOut={type:8,expr,body:null};const ref=node.getAttribute("t-ref");node.removeAttribute("t-ref");const ast=parseNode(node,ctx);if(!ast){return tOut;}
if(ast.type===2){tOut.body=ast.content.length?ast.content:null;return{...ast,ref,content:[tOut],};}
return tOut;}
function parseTForEach(node,ctx){if(!node.hasAttribute("t-foreach")){return null;}
const html=node.outerHTML;const collection=node.getAttribute("t-foreach");node.removeAttribute("t-foreach");const elem=node.getAttribute("t-as")||"";node.removeAttribute("t-as");const key=node.getAttribute("t-key");if(!key){throw new OwlError(`"Directive t-foreach should always be used with a t-key!" (expression: t-foreach="${collection}" t-as="${elem}")`);}
node.removeAttribute("t-key");const memo=node.getAttribute("t-memo")||"";node.removeAttribute("t-memo");const body=parseNode(node,ctx);if(!body){return null;}
const hasNoTCall=!html.includes("t-call");const hasNoFirst=hasNoTCall&&!html.includes(`${elem}_first`);const hasNoLast=hasNoTCall&&!html.includes(`${elem}_last`);const hasNoIndex=hasNoTCall&&!html.includes(`${elem}_index`);const hasNoValue=hasNoTCall&&!html.includes(`${elem}_value`);return{type:9,collection,elem,body,memo,key,hasNoFirst,hasNoLast,hasNoIndex,hasNoValue,};}
function parseTKey(node,ctx){if(!node.hasAttribute("t-key")){return null;}
const key=node.getAttribute("t-key");node.removeAttribute("t-key");const content=parseNode(node,ctx);if(!content){return null;}
const ast={type:10,expr:key,content,};if(content.hasNoRepresentation){ast.hasNoRepresentation=true;}
return ast;}
function parseTCall(node,ctx){if(!node.hasAttribute("t-call")){return null;}
const subTemplate=node.getAttribute("t-call");const context=node.getAttribute("t-call-context");node.removeAttribute("t-call");node.removeAttribute("t-call-context");if(node.tagName!=="t"){const ast=parseNode(node,ctx);const tcall={type:7,name:subTemplate,body:null,context};if(ast&&ast.type===2){ast.content=[tcall];return ast;}
if(ast&&ast.type===11){return{...ast,slots:{default:{content:tcall,scope:null,on:null,attrs:null,attrsTranslationCtx:null,},},};}}
const body=parseChildren(node,ctx);return{type:7,name:subTemplate,body:body.length?body:null,context,};}
function parseTCallBlock(node,ctx){if(!node.hasAttribute("t-call-block")){return null;}
const name=node.getAttribute("t-call-block");return{type:15,name,};}
function parseTIf(node,ctx){if(!node.hasAttribute("t-if")){return null;}
const condition=node.getAttribute("t-if");node.removeAttribute("t-if");const content=parseNode(node,ctx)||{type:0,value:""};let nextElement=node.nextElementSibling;const tElifs=[];while(nextElement&&nextElement.hasAttribute("t-elif")){const condition=nextElement.getAttribute("t-elif");nextElement.removeAttribute("t-elif");const tElif=parseNode(nextElement,ctx);const next=nextElement.nextElementSibling;nextElement.remove();nextElement=next;if(tElif){tElifs.push({condition,content:tElif});}}
let tElse=null;if(nextElement&&nextElement.hasAttribute("t-else")){nextElement.removeAttribute("t-else");tElse=parseNode(nextElement,ctx);nextElement.remove();}
return{type:5,condition,content,tElif:tElifs.length?tElifs:null,tElse,};}
function parseTSetNode(node,ctx){if(!node.hasAttribute("t-set")){return null;}
const name=node.getAttribute("t-set");const value=node.getAttribute("t-value")||null;const defaultValue=node.innerHTML===node.textContent?node.textContent||null:null;let body=null;if(node.textContent!==node.innerHTML){body=parseChildren(node,ctx);}
return{type:6,name,value,defaultValue,body,hasNoRepresentation:true};}
const directiveErrorMap=new Map([["t-ref","t-ref is no longer supported on components. Consider exposing only the public part of the component's API through a callback prop.",],["t-att","t-att makes no sense on component: props are already treated as expressions"],["t-attf","t-attf is not supported on components: use template strings for string interpolation in props",],]);function parseComponent(node,ctx){let name=node.tagName;const firstLetter=name[0];let isDynamic=node.hasAttribute("t-component");if(isDynamic&&name!=="t"){throw new OwlError(`Directive 't-component' can only be used on <t> nodes (used on a <${name}>)`);}
if(!(firstLetter===firstLetter.toUpperCase()||isDynamic)){return null;}
if(isDynamic){name=node.getAttribute("t-component");node.removeAttribute("t-component");}
const dynamicProps=node.getAttribute("t-props");node.removeAttribute("t-props");const defaultSlotScope=node.getAttribute("t-slot-scope");node.removeAttribute("t-slot-scope");let on=null;let props=null;let propsTranslationCtx=null;for(let name of node.getAttributeNames()){const value=node.getAttribute(name);if(name.startsWith("t-translation-context-")){const attrName=name.slice(22);propsTranslationCtx=propsTranslationCtx||{};propsTranslationCtx[attrName]=value;}
else if(name.startsWith("t-")){if(name.startsWith("t-on-")){on=on||{};on[name.slice(5)]=value;}
else{const message=directiveErrorMap.get(name.split("-").slice(0,2).join("-"));throw new OwlError(message||`unsupported directive on Component: ${name}`);}}
else{props=props||{};props[name]=value;}}
let slots=null;if(node.hasChildNodes()){const clone=node.cloneNode(true);const slotNodes=Array.from(clone.querySelectorAll("[t-set-slot]"));for(let slotNode of slotNodes){if(slotNode.tagName!=="t"){throw new OwlError(`Directive 't-set-slot' can only be used on <t> nodes (used on a <${slotNode.tagName}>)`);}
const name=slotNode.getAttribute("t-set-slot");let el=slotNode.parentElement;let isInSubComponent=false;while(el&&el!==clone){if(el.hasAttribute("t-component")||el.tagName[0]===el.tagName[0].toUpperCase()){isInSubComponent=true;break;}
el=el.parentElement;}
if(isInSubComponent||!el){continue;}
slotNode.removeAttribute("t-set-slot");slotNode.remove();const slotAst=parseNode(slotNode,ctx);let on=null;let attrs=null;let attrsTranslationCtx=null;let scope=null;for(let attributeName of slotNode.getAttributeNames()){const value=slotNode.getAttribute(attributeName);if(attributeName==="t-slot-scope"){scope=value;continue;}
else if(attributeName.startsWith("t-translation-context-")){const attrName=attributeName.slice(22);attrsTranslationCtx=attrsTranslationCtx||{};attrsTranslationCtx[attrName]=value;}
else if(attributeName.startsWith("t-on-")){on=on||{};on[attributeName.slice(5)]=value;}
else{attrs=attrs||{};attrs[attributeName]=value;}}
slots=slots||{};slots[name]={content:slotAst,on,attrs,attrsTranslationCtx,scope};}
const defaultContent=parseChildNodes(clone,ctx);slots=slots||{};if(defaultContent&&!slots.default){slots.default={content:defaultContent,on,attrs:null,attrsTranslationCtx:null,scope:defaultSlotScope,};}}
return{type:11,name,isDynamic,dynamicProps,props,propsTranslationCtx,slots,on,};}
function parseTSlot(node,ctx){if(!node.hasAttribute("t-slot")){return null;}
const name=node.getAttribute("t-slot");node.removeAttribute("t-slot");let attrs=null;let attrsTranslationCtx=null;let on=null;for(let attributeName of node.getAttributeNames()){const value=node.getAttribute(attributeName);if(attributeName.startsWith("t-on-")){on=on||{};on[attributeName.slice(5)]=value;}
else if(attributeName.startsWith("t-translation-context-")){const attrName=attributeName.slice(22);attrsTranslationCtx=attrsTranslationCtx||{};attrsTranslationCtx[attrName]=value;}
else{attrs=attrs||{};attrs[attributeName]=value;}}
return{type:14,name,attrs,attrsTranslationCtx,on,defaultContent:parseChildNodes(node,ctx),};}
function wrapInTTranslationAST(r){const ast={type:16,content:r};if(r===null||r===void 0?void 0:r.hasNoRepresentation){ast.hasNoRepresentation=true;}
return ast;}
function parseTTranslation(node,ctx){if(node.getAttribute("t-translation")!=="off"){return null;}
node.removeAttribute("t-translation");const result=parseNode(node,ctx);if((result===null||result===void 0?void 0:result.type)===3){const children=result.content.map(wrapInTTranslationAST);return makeASTMulti(children);}
return wrapInTTranslationAST(result);}
function wrapInTTranslationContextAST(r,translationCtx){const ast={type:17,content:r,translationCtx,};if(r===null||r===void 0?void 0:r.hasNoRepresentation){ast.hasNoRepresentation=true;}
return ast;}
function parseTTranslationContext(node,ctx){const translationCtx=node.getAttribute("t-translation-context");if(!translationCtx){return null;}
node.removeAttribute("t-translation-context");const result=parseNode(node,ctx);if((result===null||result===void 0?void 0:result.type)===3){const children=result.content.map((c)=>wrapInTTranslationContextAST(c,translationCtx));return makeASTMulti(children);}
return wrapInTTranslationContextAST(result,translationCtx);}
function parseTPortal(node,ctx){if(!node.hasAttribute("t-portal")){return null;}
const target=node.getAttribute("t-portal");node.removeAttribute("t-portal");const content=parseNode(node,ctx);if(!content){return{type:0,value:"",};}
return{type:18,target,content,};}
function parseChildren(node,ctx){const children=[];for(let child of node.childNodes){const childAst=parseNode(child,ctx);if(childAst){if(childAst.type===3){children.push(...childAst.content);}
else{children.push(childAst);}}}
return children;}
function makeASTMulti(children){const ast={type:3,content:children};if(children.every((c)=>c.hasNoRepresentation)){ast.hasNoRepresentation=true;}
return ast;}
function parseChildNodes(node,ctx){const children=parseChildren(node,ctx);switch(children.length){case 0:return null;case 1:return children[0];default:return makeASTMulti(children);}}
function normalizeTIf(el){let tbranch=el.querySelectorAll("[t-elif], [t-else]");for(let i=0,ilen=tbranch.length;i<ilen;i++){let node=tbranch[i];let prevElem=node.previousElementSibling;let pattr=(name)=>prevElem.getAttribute(name);let nattr=(name)=>+!!node.getAttribute(name);if(prevElem&&(pattr("t-if")||pattr("t-elif"))){if(pattr("t-foreach")){throw new OwlError("t-if cannot stay at the same level as t-foreach when using t-elif or t-else");}
if(["t-if","t-elif","t-else"].map(nattr).reduce(function(a,b){return a+b;})>1){throw new OwlError("Only one conditional branching directive is allowed per node");}
let textNode;while((textNode=node.previousSibling)!==prevElem){if(textNode.nodeValue.trim().length&&textNode.nodeType!==8){throw new OwlError("text is not allowed between branching directives");}
textNode.remove();}}
else{throw new OwlError("t-elif and t-else directives must be preceded by a t-if or t-elif directive");}}}
function normalizeTEscTOut(el){for(const d of["t-esc","t-out"]){const elements=[...el.querySelectorAll(`[${d}]`)].filter((el)=>el.tagName[0]===el.tagName[0].toUpperCase()||el.hasAttribute("t-component"));for(const el of elements){if(el.childNodes.length){throw new OwlError(`Cannot have ${d} on a component that already has content`);}
const value=el.getAttribute(d);el.removeAttribute(d);const t=el.ownerDocument.createElement("t");if(value!=null){t.setAttribute(d,value);}
el.appendChild(t);}}}
function normalizeXML(el){normalizeTIf(el);normalizeTEscTOut(el);}
function compile(template,options={hasGlobalValues:false,}){const ast=parse(template,options.customDirectives);const hasSafeContext=template instanceof Node?!(template instanceof Element)||template.querySelector("[t-set], [t-call]")===null:!template.includes("t-set")&&!template.includes("t-call");const codeGenerator=new CodeGenerator(ast,{...options,hasSafeContext});const code=codeGenerator.generateCode();try{return new Function("app, bdom, helpers",code);}
catch(originalError){const{name}=options;const nameStr=name?`template "${name}"`:"anonymous template";const err=new OwlError(`Failed to compile ${nameStr}: ${originalError.message}\n\ngenerated code:\nfunction(app, bdom, helpers) {\n${code}\n}`);err.cause=originalError;throw err;}}
const version="2.8.2";class Scheduler{constructor(){this.tasks=new Set();this.frame=0;this.delayedRenders=[];this.cancelledNodes=new Set();this.processing=false;this.requestAnimationFrame=Scheduler.requestAnimationFrame;}
addFiber(fiber){this.tasks.add(fiber.root);}
scheduleDestroy(node){this.cancelledNodes.add(node);if(this.frame===0){this.frame=this.requestAnimationFrame(()=>this.processTasks());}}
flush(){if(this.delayedRenders.length){let renders=this.delayedRenders;this.delayedRenders=[];for(let f of renders){if(f.root&&f.node.status!==3&&f.node.fiber===f){f.render();}}}
if(this.frame===0){this.frame=this.requestAnimationFrame(()=>this.processTasks());}}
processTasks(){if(this.processing){return;}
this.processing=true;this.frame=0;for(let node of this.cancelledNodes){node._destroy();}
this.cancelledNodes.clear();for(let task of this.tasks){this.processFiber(task);}
for(let task of this.tasks){if(task.node.status===3){this.tasks.delete(task);}}
this.processing=false;}
processFiber(fiber){if(fiber.root!==fiber){this.tasks.delete(fiber);return;}
const hasError=fibersInError.has(fiber);if(hasError&&fiber.counter!==0){this.tasks.delete(fiber);return;}
if(fiber.node.status===3){this.tasks.delete(fiber);return;}
if(fiber.counter===0){if(!hasError){fiber.complete();}
if(fiber.appliedToDom){this.tasks.delete(fiber);}}}}
Scheduler.requestAnimationFrame=window.requestAnimationFrame.bind(window);let hasBeenLogged=false;const apps=new Set();window.__OWL_DEVTOOLS__||(window.__OWL_DEVTOOLS__={apps,Fiber,RootFiber,toRaw,reactive});class App extends TemplateSet{constructor(Root,config={}){super(config);this.scheduler=new Scheduler();this.subRoots=new Set();this.root=null;this.name=config.name||"";this.Root=Root;apps.add(this);if(config.test){this.dev=true;}
this.warnIfNoStaticProps=config.warnIfNoStaticProps||false;if(this.dev&&!config.test&&!hasBeenLogged){console.info(`Owl is running in 'dev' mode.`);hasBeenLogged=true;}
const env=config.env||{};const descrs=Object.getOwnPropertyDescriptors(env);this.env=Object.freeze(Object.create(Object.getPrototypeOf(env),descrs));this.props=config.props||{};}
mount(target,options){const root=this.createRoot(this.Root,{props:this.props});this.root=root.node;this.subRoots.delete(root.node);return root.mount(target,options);}
createRoot(Root,config={}){const props=config.props||{};const env=this.env;if(config.env){this.env=config.env;}
const restore=saveCurrent();const node=this.makeNode(Root,props);restore();if(config.env){this.env=env;}
this.subRoots.add(node);return{node,mount:(target,options)=>{App.validateTarget(target);if(this.dev){validateProps(Root,props,{__owl__:{app:this}});}
const prom=this.mountNode(node,target,options);return prom;},destroy:()=>{this.subRoots.delete(node);node.destroy();this.scheduler.processTasks();},};}
makeNode(Component,props){return new ComponentNode(Component,props,this,null,null);}
mountNode(node,target,options){const promise=new Promise((resolve,reject)=>{let isResolved=false;node.mounted.push(()=>{resolve(node.component);isResolved=true;});let handlers=nodeErrorHandlers.get(node);if(!handlers){handlers=[];nodeErrorHandlers.set(node,handlers);}
handlers.unshift((e)=>{if(!isResolved){reject(e);}
throw e;});});node.mountComponent(target,options);return promise;}
destroy(){if(this.root){for(let subroot of this.subRoots){subroot.destroy();}
this.root.destroy();this.scheduler.processTasks();}
apps.delete(this);}
createComponent(name,isStatic,hasSlotsProp,hasDynamicPropList,propList){const isDynamic=!isStatic;let arePropsDifferent;const hasNoProp=propList.length===0;if(hasSlotsProp){arePropsDifferent=(_1,_2)=>true;}
else if(hasDynamicPropList){arePropsDifferent=function(props1,props2){for(let k in props1){if(props1[k]!==props2[k]){return true;}}
return Object.keys(props1).length!==Object.keys(props2).length;};}
else if(hasNoProp){arePropsDifferent=(_1,_2)=>false;}
else{arePropsDifferent=function(props1,props2){for(let p of propList){if(props1[p]!==props2[p]){return true;}}
return false;};}
const updateAndRender=ComponentNode.prototype.updateAndRender;const initiateRender=ComponentNode.prototype.initiateRender;return(props,key,ctx,parent,C)=>{let children=ctx.children;let node=children[key];if(isDynamic&&node&&node.component.constructor!==C){node=undefined;}
const parentFiber=ctx.fiber;if(node){if(arePropsDifferent(node.props,props)||parentFiber.deep||node.forceNextRender){node.forceNextRender=false;updateAndRender.call(node,props,parentFiber);}}
else{if(isStatic){const components=parent.constructor.components;if(!components){throw new OwlError(`Cannot find the definition of component "${name}", missing static components key in parent`);}
C=components[name];if(!C){throw new OwlError(`Cannot find the definition of component "${name}"`);}
else if(!(C.prototype instanceof Component)){throw new OwlError(`"${name}" is not a Component. It must inherit from the Component class`);}}
node=new ComponentNode(C,props,this,ctx,key);children[key]=node;initiateRender.call(node,new Fiber(node,parentFiber));}
parentFiber.childrenMap[key]=node;return node;};}
handleError(...args){return handleError(...args);}}
App.validateTarget=validateTarget;App.apps=apps;App.version=version;async function mount(C,target,config={}){return new App(C,config).mount(target,config);}
const mainEventHandler=(data,ev,currentTarget)=>{const{data:_data,modifiers}=filterOutModifiersFromData(data);data=_data;let stopped=false;if(modifiers.length){let selfMode=false;const isSelf=ev.target===currentTarget;for(const mod of modifiers){switch(mod){case"self":selfMode=true;if(isSelf){continue;}
else{return stopped;}
case"prevent":if((selfMode&&isSelf)||!selfMode)
ev.preventDefault();continue;case"stop":if((selfMode&&isSelf)||!selfMode)
ev.stopPropagation();stopped=true;continue;}}}
if(Object.hasOwnProperty.call(data,0)){const handler=data[0];if(typeof handler!=="function"){throw new OwlError(`Invalid handler (expected a function, received: '${handler}')`);}
let node=data[1]?data[1].__owl__:null;if(node?node.status===1:true){handler.call(node?node.component:null,ev);}}
return stopped;};function status(component){switch(component.__owl__.status){case 0:return"new";case 2:return"cancelled";case 1:return"mounted";case 3:return"destroyed";}}
function useRef(name){const node=getCurrent();const refs=node.refs;return{get el(){const el=refs[name];return inOwnerDocument(el)?el:null;},};}
function useEnv(){return getCurrent().component.env;}
function extendEnv(currentEnv,extension){const env=Object.create(currentEnv);const descrs=Object.getOwnPropertyDescriptors(extension);return Object.freeze(Object.defineProperties(env,descrs));}
function useSubEnv(envExtension){const node=getCurrent();node.component.env=extendEnv(node.component.env,envExtension);useChildSubEnv(envExtension);}
function useChildSubEnv(envExtension){const node=getCurrent();node.childEnv=extendEnv(node.childEnv,envExtension);}
function useEffect(effect,computeDependencies=()=>[NaN]){let cleanup;let dependencies;onMounted(()=>{dependencies=computeDependencies();cleanup=effect(...dependencies);});onPatched(()=>{const newDeps=computeDependencies();const shouldReapply=newDeps.some((val,i)=>val!==dependencies[i]);if(shouldReapply){dependencies=newDeps;if(cleanup){cleanup();}
cleanup=effect(...dependencies);}});onWillUnmount(()=>cleanup&&cleanup());}
function useExternalListener(target,eventName,handler,eventParams){const node=getCurrent();const boundHandler=handler.bind(node.component);onMounted(()=>target.addEventListener(eventName,boundHandler,eventParams));onWillUnmount(()=>target.removeEventListener(eventName,boundHandler,eventParams));}
config.shouldNormalizeDom=false;config.mainEventHandler=mainEventHandler;const blockDom={config,mount:mount$1,patch,remove,list,multi,text,toggler,createBlock,html,comment,};const __info__={version:App.version,};TemplateSet.prototype._compileTemplate=function _compileTemplate(name,template){return compile(template,{name,dev:this.dev,translateFn:this.translateFn,translatableAttributes:this.translatableAttributes,customDirectives:this.customDirectives,hasGlobalValues:this.hasGlobalValues,});};exports.App=App;exports.Component=Component;exports.EventBus=EventBus;exports.OwlError=OwlError;exports.__info__=__info__;exports.batched=batched;exports.blockDom=blockDom;exports.htmlEscape=htmlEscape;exports.loadFile=loadFile;exports.markRaw=markRaw;exports.markup=markup;exports.mount=mount;exports.onError=onError;exports.onMounted=onMounted;exports.onPatched=onPatched;exports.onRendered=onRendered;exports.onWillDestroy=onWillDestroy;exports.onWillPatch=onWillPatch;exports.onWillRender=onWillRender;exports.onWillStart=onWillStart;exports.onWillUnmount=onWillUnmount;exports.onWillUpdateProps=onWillUpdateProps;exports.reactive=reactive;exports.status=status;exports.toRaw=toRaw;exports.useChildSubEnv=useChildSubEnv;exports.useComponent=useComponent;exports.useEffect=useEffect;exports.useEnv=useEnv;exports.useExternalListener=useExternalListener;exports.useRef=useRef;exports.useState=useState;exports.useSubEnv=useSubEnv;exports.validate=validate;exports.validateType=validateType;exports.whenReady=whenReady;exports.xml=xml;Object.defineProperty(exports,'__esModule',{value:true});__info__.date='2026-01-30T07:49:47.618Z';__info__.hash='52abf8d';__info__.url='https://github.com/odoo/owl';})(this.owl=this.owl||{});;

/* /web/static/lib/owl/odoo_module.js */
odoo.define("@odoo/owl",[],function(){"use strict";return owl;});;

/* /web/static/src/core/utils/functions.js */
odoo.define('@web/core/utils/functions',[],function(require){'use strict';let __exports={};__exports.memoize=memoize;function memoize(func){const cache=new Map();const funcName=func.name?func.name+" (memoized)":"memoized";return{[funcName](...args){if(!cache.has(args[0])){cache.set(args[0],func(...args));}
return cache.get(...args);},}[funcName];}
__exports.uniqueId=uniqueId;function uniqueId(prefix=""){return`${prefix}${++uniqueId.nextId}`;}
uniqueId.nextId=0;return __exports;});;

/* /web/static/src/core/utils/reactive.js */
odoo.define('@web/core/utils/reactive',['@odoo/owl'],function(require){'use strict';let __exports={};const{reactive}=require("@odoo/owl");const Reactive=__exports.Reactive=class Reactive{constructor(){return reactive(this);}}
__exports.effect=effect;function effect(cb,deps){const reactiveDeps=reactive(deps,()=>{cb(...reactiveDeps);});cb(...reactiveDeps);}
__exports.withComputedProperties=withComputedProperties;function withComputedProperties(obj,sources,descriptor){for(const[key,compute]of Object.entries(descriptor)){effect((obj,sources)=>{obj[key]=compute.call(obj,...sources);},[obj,sources]);}
return obj;}
return __exports;});;

/* /web/static/src/core/browser/browser.js */
odoo.define('@web/core/browser/browser',[],function(require){'use strict';let __exports={};let sessionStorage;let localStorage;try{sessionStorage=window.sessionStorage;localStorage=window.localStorage;localStorage.setItem("__localStorage__","true");localStorage.removeItem("__localStorage__");}catch{localStorage=makeRAMLocalStorage();sessionStorage=makeRAMLocalStorage();}
const browser=__exports.browser={addEventListener:window.addEventListener.bind(window),dispatchEvent:window.dispatchEvent.bind(window),AnalyserNode:window.AnalyserNode,Audio:window.Audio,AudioBufferSourceNode:window.AudioBufferSourceNode,AudioContext:window.AudioContext,AudioWorkletNode:window.AudioWorkletNode,BeforeInstallPromptEvent:window.BeforeInstallPromptEvent?.bind(window),GainNode:window.GainNode,MediaStreamAudioSourceNode:window.MediaStreamAudioSourceNode,removeEventListener:window.removeEventListener.bind(window),setTimeout:window.setTimeout.bind(window),clearTimeout:window.clearTimeout.bind(window),setInterval:window.setInterval.bind(window),clearInterval:window.clearInterval.bind(window),performance:window.performance,requestAnimationFrame:window.requestAnimationFrame.bind(window),cancelAnimationFrame:window.cancelAnimationFrame.bind(window),console:window.console,history:window.history,matchMedia:window.matchMedia.bind(window),navigator,Notification:window.Notification,open:window.open.bind(window),SharedWorker:window.SharedWorker,Worker:window.Worker,XMLHttpRequest:window.XMLHttpRequest,localStorage,sessionStorage,fetch:window.fetch.bind(window),innerHeight:window.innerHeight,innerWidth:window.innerWidth,ontouchstart:window.ontouchstart,BroadcastChannel:window.BroadcastChannel,visualViewport:window.visualViewport,};Object.defineProperty(browser,"location",{set(val){window.location=val;},get(){return window.location;},configurable:true,});Object.defineProperty(browser,"innerHeight",{get:()=>window.innerHeight,configurable:true,});Object.defineProperty(browser,"innerWidth",{get:()=>window.innerWidth,configurable:true,});__exports.makeRAMLocalStorage=makeRAMLocalStorage;function makeRAMLocalStorage(){let store={};return{setItem(key,value){const newValue=String(value);store[key]=newValue;window.dispatchEvent(new StorageEvent("storage",{key,newValue}));},getItem(key){return store[key]??null;},clear(){store={};},removeItem(key){delete store[key];window.dispatchEvent(new StorageEvent("storage",{key,newValue:null}));},get length(){return Object.keys(store).length;},key(){return"";},};}
return __exports;});;

/* /web/static/src/core/utils/timing.js */
odoo.define('@web/core/utils/timing',['@web/core/browser/browser','@odoo/owl'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");const{onWillUnmount,useComponent}=require("@odoo/owl");__exports.batched=batched;function batched(callback,synchronize=()=>Promise.resolve()){let scheduled=false;return async(...args)=>{if(!scheduled){scheduled=true;await synchronize();scheduled=false;callback(...args);}};}
__exports.debounce=debounce;function debounce(func,delay,options){let handle;const funcName=func.name?func.name+" (debounce)":"debounce";const useAnimationFrame=delay==="animationFrame";const setFnName=useAnimationFrame?"requestAnimationFrame":"setTimeout";const clearFnName=useAnimationFrame?"cancelAnimationFrame":"clearTimeout";let lastArgs;let leading=false;let trailing=true;if(typeof options==="boolean"){leading=options;trailing=!options;}else if(options){leading=options.leading??leading;trailing=options.trailing??trailing;}
return Object.assign({[funcName](...args){return new Promise((resolve)=>{if(leading&&!handle){Promise.resolve(func.apply(this,args)).then(resolve);}else{lastArgs=args;}
browser[clearFnName](handle);handle=browser[setFnName](()=>{handle=null;if(trailing&&lastArgs){Promise.resolve(func.apply(this,lastArgs)).then(resolve);lastArgs=null;}},delay);});},}[funcName],{cancel(execNow=false){browser[clearFnName](handle);if(execNow&&lastArgs){func.apply(this,lastArgs);}},});}
__exports.setRecurringAnimationFrame=setRecurringAnimationFrame;function setRecurringAnimationFrame(callback){const handler=(timestamp)=>{callback(timestamp-lastTimestamp);lastTimestamp=timestamp;handle=browser.requestAnimationFrame(handler);};const stop=()=>{browser.cancelAnimationFrame(handle);};let lastTimestamp=browser.performance.now();let handle=browser.requestAnimationFrame(handler);return stop;}
__exports.throttleForAnimation=throttleForAnimation;function throttleForAnimation(func){let handle=null;const calls=new Set();const funcName=func.name?`${func.name} (throttleForAnimation)`:"throttleForAnimation";const pending=()=>{if(calls.size){handle=browser.requestAnimationFrame(pending);const{args,resolve}=[...calls].pop();calls.clear();Promise.resolve(func.apply(this,args)).then(resolve);}else{handle=null;}};return Object.assign({[funcName](...args){return new Promise((resolve)=>{const isNew=handle===null;if(isNew){handle=browser.requestAnimationFrame(pending);Promise.resolve(func.apply(this,args)).then(resolve);}else{calls.add({args,resolve});}});},}[funcName],{cancel(){browser.cancelAnimationFrame(handle);calls.clear();handle=null;},});}
__exports.useDebounced=useDebounced;function useDebounced(callback,delay,{execBeforeUnmount=false,immediate=false,trailing=!immediate}={}){const component=useComponent();const debounced=debounce(callback.bind(component),delay,{leading:immediate,trailing});onWillUnmount(()=>debounced.cancel(execBeforeUnmount));return debounced;}
__exports.useThrottleForAnimation=useThrottleForAnimation;function useThrottleForAnimation(func){const component=useComponent();const throttledForAnimation=throttleForAnimation(func.bind(component));onWillUnmount(()=>throttledForAnimation.cancel());return throttledForAnimation;}
return __exports;});;

/* /web/static/src/core/template_inheritance.js */
odoo.define('@web/core/template_inheritance',[],function(require){'use strict';let __exports={};const RSTRIP_REGEXP=/(?=\n[ \t]*$)/;let translationContext=null;const TCTX="t-translation-context";function getTranslationContext(node){if(node.hasAttribute(TCTX)){return node.getAttribute(TCTX);}
return getTranslationContext(node.parentElement);}
const contextByTextNode=new Map();function setTranslationContext(node){switch(node.nodeType){case Node.TEXT_NODE:if(node.nodeValue.trim()!=""){contextByTextNode.set(node,translationContext);}
break;case Node.ELEMENT_NODE:node.setAttribute(TCTX,translationContext);break;}}
__exports.applyContextToTextNode=applyContextToTextNode;function applyContextToTextNode(){for(const[textNode,context]of contextByTextNode){const wrapper=document.createElement("t");wrapper.setAttribute(TCTX,context);textNode.before(wrapper);wrapper.appendChild(textNode);}
contextByTextNode.clear();}
__exports.deepClone=deepClone;function deepClone(node){const clone=node.cloneNode();if(node.nodeType===Node.TEXT_NODE){if(contextByTextNode.has(node)){contextByTextNode.set(clone,contextByTextNode.get(node));}}
if(node.childNodes?.length){for(const childNode of[...node.childNodes]){clone.append(deepClone(childNode));}}
return clone;}
function addBefore(target,operation){const nodes=getNodes(target,operation);if(nodes.length===0){return;}
const{previousSibling}=target;target.before(...nodes);if(previousSibling?.nodeType===Node.TEXT_NODE){const[text1,text2]=previousSibling.data.split(RSTRIP_REGEXP);previousSibling.data=text1.trimEnd();if(text2&&nodes.some((n)=>n.nodeType!==Node.TEXT_NODE)){const textNode=document.createTextNode(text2);target.before(textNode);if(textNode.previousSibling.nodeType===Node.TEXT_NODE){textNode.previousSibling.data=textNode.previousSibling.data.trimEnd();}}}}
function getRoot(element){while(element.parentElement){element=element.parentElement;}
return element;}
const HASCLASS_REGEXP=/hasclass\(([^)]*)\)/g;const CLASS_CONTAINS_REGEX=/contains\(@class.*\)/g;function getXpath(operation){const xpath=operation.getAttribute("expr");if(odoo.debug){if(CLASS_CONTAINS_REGEX.test(xpath)){const parent=operation.closest("t[t-inherit]");const templateName=parent.getAttribute("t-name")||parent.getAttribute("t-inherit");console.warn(`Error-prone use of @class in template "${templateName}" (or one of its inheritors).`+" Use the hasclass(*classes) function to filter elements by their classes");}}
return xpath.replaceAll(HASCLASS_REGEXP,(_,capturedGroup)=>capturedGroup.split(",").map((c)=>`contains(concat(' ', @class, ' '), ' ${c.trim().slice(1, -1)} ')`).join(" and "));}
function getNode(element,operation){const root=getRoot(element);const doc=new Document();doc.appendChild(root);if(operation.tagName==="xpath"){const xpath=getXpath(operation);const result=doc.evaluate(xpath,root,null,XPathResult.FIRST_ORDERED_NODE_TYPE);return result.singleNodeValue;}
const attributes=[...operation.attributes].filter((attr)=>!attr.name.startsWith(TCTX));for(const elem of root.querySelectorAll(operation.tagName)){if(attributes.every(({name,value})=>name==="position"||elem.getAttribute(name)===value)){return elem;}}
return null;}
function getElement(element,operation){const node=getNode(element,operation);if(!node){throw new Error(`Element '${operation.outerHTML}' cannot be located in element tree`);}
if(!(node instanceof Element)){throw new Error(`Found node ${node} instead of an element`);}
return node;}
function getNodes(element,operation){const nodes=[];for(const childNode of operation.childNodes){if(childNode.tagName==="xpath"&&childNode.getAttribute?.("position")==="move"){const node=getElement(element,childNode);node.setAttribute(TCTX,getTranslationContext(node));removeNode(node);nodes.push(node);}else{setTranslationContext(childNode);nodes.push(childNode);}}
return nodes;}
function splitAndTrim(str,separator){return str.split(separator).map((s)=>s.trim());}
function modifyAttributes(target,operation){for(const child of operation.children){if(child.tagName!=="attribute"){continue;}
const attributeName=child.getAttribute("name");const firstNode=child.childNodes[0];let value=firstNode?.nodeType===Node.TEXT_NODE?firstNode.data:"";const add=child.getAttribute("add")||"";const remove=child.getAttribute("remove")||"";if(add||remove){if(firstNode?.nodeType===Node.TEXT_NODE){throw new Error(`Useless element content ${firstNode.outerHTML}`);}
const separator=child.getAttribute("separator")||",";const toRemove=new Set(splitAndTrim(remove,separator));const values=splitAndTrim(target.getAttribute(attributeName)||"",separator).filter((s)=>!toRemove.has(s));values.push(...splitAndTrim(add,separator).filter((s)=>s));value=values.join(separator);}
if(value){target.setAttribute(attributeName,value);if(!(add||remove)){target.setAttribute(`t-translation-context-${attributeName}`,translationContext);}}else{target.removeAttribute(attributeName);}}}
function removeNode(node){const{nextSibling,previousSibling}=node;node.remove();if(nextSibling?.nodeType===Node.TEXT_NODE&&previousSibling?.nodeType===Node.TEXT_NODE&&previousSibling.parentElement.firstChild===previousSibling){previousSibling.data=previousSibling.data.trimEnd();}}
function replace(root,target,operation){const mode=operation.getAttribute("mode")||"outer";switch(mode){case"outer":{const result=operation.ownerDocument.evaluate(".//*[text()='$0']",operation,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);target.setAttribute(TCTX,getTranslationContext(target));for(let i=0;i<result.snapshotLength;i++){const loc=result.snapshotItem(i);loc.firstChild.replaceWith(deepClone(target));}
if(target.parentElement){const nodes=getNodes(target,operation);target.replaceWith(...nodes);}else{let operationContent=null;let comment=null;for(const child of operation.childNodes){if(child.nodeType===Node.ELEMENT_NODE){setTranslationContext(child);operationContent=child;break;}
if(child.nodeType===Node.COMMENT_NODE){comment=child;}}
root=deepClone(operationContent);if(target.hasAttribute("t-name")){root.setAttribute("t-name",target.getAttribute("t-name"));}
if(comment){root.prepend(comment);}}
break;}
case"inner":while(target.firstChild){target.removeChild(target.lastChild);}
for(const node of[...operation.childNodes]){setTranslationContext(node);target.append(node);}
break;default:throw new Error(`Invalid mode attribute: '${mode}'`);}
return root;}
__exports.applyInheritance=applyInheritance;function applyInheritance(root,operations,url=""){translationContext=url.split("/")[1]??"";for(const operation of operations.children){const target=getElement(root,operation);const position=operation.getAttribute("position")||"inside";if(odoo.debug&&url){const attributes=[...operation.attributes].map(({name,value})=>`${name}=${JSON.stringify(name === "position" ? position : value)}`);const comment=document.createComment(` From file: ${url} ; ${attributes.join(" ; ")} `);if(position==="attributes"){target.before(comment);}else{operation.prepend(comment);}}
switch(position){case"replace":{root=replace(root,target,operation);break;}
case"attributes":{modifyAttributes(target,operation);break;}
case"inside":{const sentinel=document.createElement("sentinel");target.append(sentinel);addBefore(sentinel,operation);removeNode(sentinel);break;}
case"after":{const sentinel=document.createElement("sentinel");target.after(sentinel);addBefore(sentinel,operation);removeNode(sentinel);break;}
case"before":{addBefore(target,operation);break;}
default:throw new Error(`Invalid position attribute: '${position}'`);}}
translationContext=null;return root;}
return __exports;});;

/* /web/static/src/core/templates.js */
odoo.define('@web/core/templates',['@web/core/template_inheritance'],function(require){'use strict';let __exports={};const{applyContextToTextNode,applyInheritance,deepClone,}=require("@web/core/template_inheritance");function getClone(template){const c=deepClone(template);new Document().append(c);return c;}
function getKey(args){return JSON.stringify([...args]);}
function getParsedTemplate(templateString){const doc=parser.parseFromString(templateString,"text/xml");for(const processor of templateProcessors){processor(doc);}
return doc.firstChild;}
function _getTemplate(name,blockId=null){if(!(name in parsedTemplates)){if(!(name in templates)){return null;}
const templateString=templates[name];parsedTemplates[name]=getParsedTemplate(templateString);const inheritFrom=parsedTemplates[name].getAttribute("t-inherit");if(!inheritFrom){const addon=info[name].url.split("/")[1];parsedTemplates[name].setAttribute("t-translation-context",addon);}}
let processedTemplate=parsedTemplates[name];const inheritFrom=processedTemplate.getAttribute("t-inherit");if(inheritFrom){const parentTemplate=_getTemplate(inheritFrom,blockId||info[name].blockId);if(!parentTemplate){throw new Error(`Constructing template ${name}: template parent ${inheritFrom} not found`);}
const element=getClone(processedTemplate);processedTemplate=applyInheritance(getClone(parentTemplate),element,info[name].url);if(processedTemplate.tagName!==element.tagName){const temp=processedTemplate;processedTemplate=new Document().createElement(element.tagName);processedTemplate.append(...temp.childNodes);}
for(const{name,value}of element.attributes){if(!["t-inherit","t-inherit-mode"].includes(name)){processedTemplate.setAttribute(name,value);}}}
let cloned=false;for(const otherBlockId in templateExtensions[name]||{}){if(blockId&&otherBlockId>blockId){break;}
if(!(name in parsedTemplateExtensions)){parsedTemplateExtensions[name]={};}
if(!(otherBlockId in parsedTemplateExtensions[name])){parsedTemplateExtensions[name][otherBlockId]=[];for(const{templateString,url}of templateExtensions[name][otherBlockId]){parsedTemplateExtensions[name][otherBlockId].push({template:getParsedTemplate(templateString),url,});}}
for(const{template,url}of parsedTemplateExtensions[name][otherBlockId]){if(!urlFilters.every((filter)=>filter(url))){continue;}
if(!inheritFrom&&!cloned){cloned=true;processedTemplate=getClone(processedTemplate);}
processedTemplate=applyInheritance(processedTemplate,getClone(template),url);}}
return processedTemplate;}
const info=Object.create(null);const parsedTemplateExtensions=Object.create(null);const parsedTemplates=Object.create(null);const parser=new DOMParser();const processedTemplates=new Map();const registered=new Set();const templateExtensions=Object.create(null);const templateProcessors=[];const templates=Object.create(null);let blockType=null;let blockId=0;let urlFilters=[];__exports.checkPrimaryTemplateParents=checkPrimaryTemplateParents;function checkPrimaryTemplateParents(namesToCheck){const missing=new Set(namesToCheck.filter((name)=>!(name in templates)));if(missing.size){console.error(`Missing (primary) parent templates: ${[...missing].join(", ")}`);}}
__exports.clearProcessedTemplates=clearProcessedTemplates;function clearProcessedTemplates(){processedTemplates.clear();}
__exports.getTemplate=getTemplate;function getTemplate(name){if(!processedTemplates.has(name)){processedTemplates.set(name,_getTemplate(name));applyContextToTextNode();}
return processedTemplates.get(name);}
__exports.registerTemplate=registerTemplate;function registerTemplate(name,url,templateString){const key=getKey(arguments);if(registered.has(key)){return;}
registered.add(key);if(blockType!=="templates"){blockType="templates";blockId++;}
if(name in templates&&(info[name].url!==url||templates[name]!==templateString)){throw new Error(`Template ${name} already exists`);}
templates[name]=templateString;info[name]={blockId,url};return function unregisterTemplate(){delete templates[name];delete info[name];delete parsedTemplates[name];delete parsedTemplateExtensions[name];processedTemplates.delete(name);registered.delete(key);};}
__exports.registerTemplateExtension=registerTemplateExtension;function registerTemplateExtension(inheritFrom,url,templateString){const key=getKey(arguments);if(registered.has(key)){return;}
registered.add(key);if(blockType!=="extensions"){blockType="extensions";blockId++;}
if(!templateExtensions[inheritFrom]){templateExtensions[inheritFrom]=[];}
if(!templateExtensions[inheritFrom][blockId]){templateExtensions[inheritFrom][blockId]=[];}
templateExtensions[inheritFrom][blockId].push({templateString,url,});return function unregisterTemplateExtension(){const index=templateExtensions[inheritFrom]?.[blockId]?.findIndex((ext)=>ext.templateString===templateString&&ext.url===url);if(Number.isInteger(index)&&index>-1){templateExtensions[inheritFrom][blockId].splice(index,1);}
registered.delete(key);};}
__exports.registerTemplateProcessor=registerTemplateProcessor;function registerTemplateProcessor(processor){templateProcessors.push(processor);}
__exports.setUrlFilters=setUrlFilters;function setUrlFilters(filters){const prev=urlFilters;urlFilters=filters;return function restoreUrlFilters(){urlFilters=prev;};}
return __exports;});;

/* /web/static/src/core/registry.js */
odoo.define('@web/core/registry',['@odoo/owl'],function(require){'use strict';let __exports={};const{EventBus,validate}=require("@odoo/owl");const KeyNotFoundError=__exports.KeyNotFoundError=class KeyNotFoundError extends Error{}
const DuplicatedKeyError=__exports.DuplicatedKeyError=class DuplicatedKeyError extends Error{}
const validateSchema=(name,key,value,schema)=>{if(!odoo.debug){return;}
try{validate(value,schema);}catch(error){throw new Error(`Validation error for key "${key}" in registry "${name}": ${error}`);}};const Registry=__exports.Registry=class Registry extends EventBus{constructor(name){super();this.content={};this.subRegistries={};this.elements=null;this.entries=null;this.name=name;this.validationSchema=null;this.addEventListener("UPDATE",()=>{this.elements=null;this.entries=null;});}
add(key,value,{force,sequence}={}){if(this.validationSchema){validateSchema(this.name,key,value,this.validationSchema);}
if(!force&&key in this.content){throw new DuplicatedKeyError(`Cannot add key "${key}" in the "${this.name}" registry: it already exists`);}
let previousSequence;if(force){const elem=this.content[key];previousSequence=elem&&elem[0];}
sequence=sequence===undefined?previousSequence||50:sequence;this.content[key]=[sequence,value];const payload={operation:"add",key,value};this.trigger("UPDATE",payload);return this;}
get(key,defaultValue){if(arguments.length<2&&!(key in this.content)){throw new KeyNotFoundError(`Cannot find key "${key}" in the "${this.name}" registry`);}
const info=this.content[key];return info?info[1]:defaultValue;}
contains(key){return key in this.content;}
getAll(){if(!this.elements){const content=Object.values(this.content).sort((el1,el2)=>el1[0]-el2[0]);this.elements=content.map((elem)=>elem[1]);}
return this.elements.slice();}
getEntries(){if(!this.entries){const entries=Object.entries(this.content).sort((el1,el2)=>el1[1][0]-el2[1][0]);this.entries=entries.map(([str,elem])=>[str,elem[1]]);}
return this.entries.slice();}
remove(key){const value=this.content[key];delete this.content[key];const payload={operation:"delete",key,value};this.trigger("UPDATE",payload);}
category(subcategory){if(!(subcategory in this.subRegistries)){this.subRegistries[subcategory]=new Registry(subcategory);}
return this.subRegistries[subcategory];}
addValidation(schema){if(this.validationSchema){throw new Error("Validation schema already set on this registry");}
this.validationSchema=schema;for(const[key,value]of this.getEntries()){validateSchema(this.name,key,value,schema);}}}
const registry=__exports.registry=new Registry();return __exports;});;

/* /web/static/src/session.js */
odoo.define('@web/session',[],function(require){'use strict';let __exports={};const session=__exports.session=odoo.__session_info__||{};delete odoo.__session_info__;return __exports;});;

/* /web/static/src/core/assets.js */
odoo.define('@web/core/assets',['@odoo/owl','@web/session','@web/core/registry'],function(require){'use strict';let __exports={};const{Component,onWillStart,whenReady,xml}=require("@odoo/owl");const{session}=require("@web/session");const{registry}=require("@web/core/registry");const globalBundleCache=__exports.globalBundleCache=new Map();const assetCacheByDocument=__exports.assetCacheByDocument=new WeakMap();function getGlobalBundleCache(){return globalBundleCache;}
function getAssetCache(targetDoc){if(!assetCacheByDocument.has(targetDoc)){assetCacheByDocument.set(targetDoc,new Map());}
return assetCacheByDocument.get(targetDoc);}
__exports.computeBundleCacheMap=computeBundleCacheMap;function computeBundleCacheMap(targetDoc){const cacheMap=getGlobalBundleCache();for(const script of targetDoc.head.querySelectorAll("script[src]")){cacheMap.set(script.getAttribute("src"),Promise.resolve());}
for(const link of targetDoc.head.querySelectorAll("link[rel=stylesheet][href]")){cacheMap.set(link.getAttribute("href"),Promise.resolve());}}
whenReady(()=>computeBundleCacheMap(document));const onLoadAndError=(el,onLoad,onError)=>{const onLoadListener=(event)=>{removeListeners();onLoad(event);};const onErrorListener=(error)=>{removeListeners();onError(error);};const removeListeners=()=>{el.removeEventListener("load",onLoadListener);el.removeEventListener("error",onErrorListener);};el.addEventListener("load",onLoadListener);el.addEventListener("error",onErrorListener);window.addEventListener("pagehide",()=>{removeListeners();});};__exports.getBundle=getBundle;function getBundle(){return assets.getBundle(...arguments);}
__exports.loadBundle=loadBundle;function loadBundle(){return assets.loadBundle(...arguments);}
__exports.loadJS=loadJS;function loadJS(){return assets.loadJS(...arguments);}
__exports.loadCSS=loadCSS;function loadCSS(){return assets.loadCSS(...arguments);}
const AssetsLoadingError=__exports.AssetsLoadingError=class AssetsLoadingError extends Error{}
const LazyComponent=__exports.LazyComponent=class LazyComponent extends Component{static template=xml`<t t-component="Component" t-props="componentProps"/>`;static props={Component:String,bundle:String,props:{type:[Object,Function],optional:true},};setup(){onWillStart(async()=>{await loadBundle(this.props.bundle);this.Component=registry.category("lazy_components").get(this.props.Component);});}
get componentProps(){return typeof this.props.props==="function"?this.props.props():this.props.props;}}
const assets=__exports.assets={retries:{count:3,delay:5000,extraDelay:2500,},getBundle(bundleName){const cacheMap=getGlobalBundleCache();if(cacheMap.has(bundleName)){return cacheMap.get(bundleName);}
const url=new URL(`/web/bundle/${bundleName}`,location.origin);for(const[key,value]of Object.entries(session.bundle_params||{})){url.searchParams.set(key,value);}
const promise=fetch(url).then(async(response)=>{const cssLibs=[];const jsLibs=[];if(!response.bodyUsed){const result=await response.json();for(const{src,type}of Object.values(result)){if(type==="link"&&src){cssLibs.push(src);}else if(type==="script"&&src){jsLibs.push(src);}}}
return{cssLibs,jsLibs};}).catch((reason)=>{cacheMap.delete(bundleName);throw new AssetsLoadingError(`The loading of ${url} failed`,{cause:reason});});cacheMap.set(bundleName,promise);return promise;},loadBundle(bundleName,{targetDoc=document,css=true,js=true}={}){if(typeof bundleName!=="string"){throw new Error(`loadBundle(bundleName:string) accepts only bundleName argument as a string ! Not ${JSON.stringify(
                    bundleName
                )} as ${typeof bundleName}`);}
return getBundle(bundleName).then(({cssLibs,jsLibs})=>{const promises=[];if(css&&cssLibs){promises.push(...cssLibs.map((url)=>assets.loadCSS(url,{targetDoc})));}
if(js&&jsLibs){promises.push(...jsLibs.map((url)=>assets.loadJS(url,{targetDoc})));}
return Promise.all(promises);});},loadCSS(url,{retryCount=0,targetDoc=document}={}){const cacheMap=getAssetCache(targetDoc);if(cacheMap.has(url)){return cacheMap.get(url);}
const linkEl=targetDoc.createElement("link");linkEl.setAttribute("href",url);linkEl.type="text/css";linkEl.rel="stylesheet";const promise=new Promise((resolve,reject)=>onLoadAndError(linkEl,resolve,async(error)=>{cacheMap.delete(url);if(retryCount<assets.retries.count){const delay=assets.retries.delay+assets.retries.extraDelay*retryCount;await new Promise((res)=>setTimeout(res,delay));linkEl.remove();loadCSS(url,{retryCount:retryCount+1,targetDoc}).then(resolve).catch((reason)=>{cacheMap.delete(url);reject(reason);});}else{reject(new AssetsLoadingError(`The loading of ${url} failed`,{cause:error}));}}));cacheMap.set(url,promise);targetDoc.head.appendChild(linkEl);return promise;},loadJS(url,{targetDoc=document}={}){const cacheMap=getAssetCache(targetDoc);if(cacheMap.has(url)){return cacheMap.get(url);}
const scriptEl=targetDoc.createElement("script");scriptEl.setAttribute("src",url);scriptEl.type=url.includes("web/static/lib/pdfjs/")?"module":"text/javascript";const promise=new Promise((resolve,reject)=>onLoadAndError(scriptEl,resolve,(error)=>{cacheMap.delete(url);reject(new AssetsLoadingError(`The loading of ${url} failed`,{cause:error}));}));cacheMap.set(url,promise);targetDoc.head.appendChild(scriptEl);return promise;},};return __exports;});;

/* /web/static/src/core/code_editor/code_editor.js */
odoo.define('@web/core/code_editor/code_editor',['@odoo/owl','@web/core/assets'],function(require){'use strict';let __exports={};const{Component,onMounted,onWillStart,useEffect,useRef,useState,status}=require("@odoo/owl");const{loadBundle}=require("@web/core/assets");const CodeEditor=__exports.CodeEditor=class CodeEditor extends Component{static template="web.CodeEditor";static components={};static props={mode:{type:String,optional:true,validate:(mode)=>CodeEditor.MODES.includes(mode),},value:{validate:(v)=>typeof v==="string",optional:true},readonly:{type:Boolean,optional:true},onChange:{type:Function,optional:true},onBlur:{type:Function,optional:true},class:{type:String,optional:true},theme:{type:String,optional:true,validate:(theme)=>CodeEditor.THEMES.includes(theme),},maxLines:{type:Number,optional:true},sessionId:{type:[Number,String],optional:true},initialCursorPosition:{type:Object,optional:true},showLineNumbers:{type:Boolean,optional:true},};static defaultProps={readonly:false,value:"",onChange:()=>{},class:"",theme:"",sessionId:1,showLineNumbers:true,};static MODES=["javascript","xml","qweb","scss","python"];static THEMES=["","monokai"];setup(){this.editorRef=useRef("editorRef");this.state=useState({activeMode:undefined,});onWillStart(async()=>await loadBundle("web.ace_lib"));const sessions={};let ignoredAceChange=false;useEffect((el)=>{if(!el){return;}
const aceEditor=window.ace.edit(el);this.aceEditor=aceEditor;this.aceEditor.setOptions({maxLines:this.props.maxLines,showPrintMargin:false,useWorker:false,});this.aceEditor.$blockScrolling=true;this.aceEditor.on("changeMode",()=>{this.state.activeMode=this.aceEditor.getSession().$modeId.split("/").at(-1);});const session=aceEditor.getSession();if(!sessions[this.props.sessionId]){sessions[this.props.sessionId]=session;}
session.setValue(this.props.value);session.on("change",()=>{if(this.props.onChange&&!ignoredAceChange){this.props.onChange(this.aceEditor.getValue(),this.aceEditor.getCursorPosition());}});this.aceEditor.on("blur",()=>{if(this.props.onBlur){this.props.onBlur();}});return()=>{aceEditor.destroy();};},()=>[this.editorRef.el]);useEffect((theme)=>this.aceEditor.setTheme(theme?`ace/theme/${theme}`:""),()=>[this.props.theme]);useEffect((readonly,showLineNumbers)=>{this.aceEditor.setOptions({readOnly:readonly,highlightActiveLine:!readonly,highlightGutterLine:!readonly,});this.aceEditor.renderer.setOptions({displayIndentGuides:!readonly,showGutter:!readonly&&showLineNumbers,});this.aceEditor.renderer.$cursorLayer.element.style.display=readonly?"none":"block";},()=>[this.props.readonly,this.props.showLineNumbers]);useEffect((sessionId,mode,value)=>{let session=sessions[sessionId];if(session){if(session.getValue()!==value){ignoredAceChange=true;session.setValue(value);ignoredAceChange=false;}}else{session=new window.ace.EditSession(value);session.setUndoManager(new window.ace.UndoManager());session.setOptions({useWorker:false,tabSize:2,useSoftTabs:true,});session.on("change",()=>{if(this.props.onChange&&!ignoredAceChange){this.props.onChange(this.aceEditor.getValue(),this.aceEditor.getCursorPosition());}});sessions[sessionId]=session;}
session.setMode(mode?`ace/mode/${mode}`:"");this.aceEditor.setSession(session);},()=>[this.props.sessionId,this.props.mode,this.props.value]);const initialCursorPosition=this.props.initialCursorPosition;if(initialCursorPosition){onMounted(()=>{window.requestAnimationFrame(()=>{if(status(this)!="destroyed"&&this.aceEditor){this.aceEditor.focus();const{row,column}=initialCursorPosition;const pos={row:row||0,column:column||0,};this.aceEditor.selection.moveToPosition(pos);this.aceEditor.renderer.scrollCursorIntoView(pos,0.5);}});});}}}
return __exports;});;

/* /api_doc/static/src/components/doc_error_dialog.js */
odoo.define('@api_doc/components/doc_error_dialog',['@odoo/owl','@web/core/browser/browser'],function(require){'use strict';let __exports={};const{Component,useState,xml}=require("@odoo/owl");const{browser}=require("@web/core/browser/browser");const DocErrorDialog=__exports.DocErrorDialog=class DocErrorDialog extends Component{static template=xml`
        <div class="alert error mt-1 d-flex flex-column" role="alert">
            <div class="d-flex align-items-center mb-2">
                <i class="pe-2 fa fa-exclamation-triangle fa-lg" aria-hidden="true"/>
                <h5 class="m-0 text-danger">Error while loading models: <strong t-out="props.name"/></h5>
            </div>
            <t t-if="props.traceback">
                <div t-if="state.showTraceback" class="overflow-auto position-relative" style="max-height: 500px;">
                    <button
                        class="btn bg-100 position-absolute top-0 end-0"
                        t-ref="copyButton"
                        t-on-click="onClickClipboard"
                    >
                        <span class="fa fa-clipboard"/>
                    </button>
                    <pre class="small text-break p-4" t-out="props.traceback"/>
                </div>
                <button
                    class="btn btn-sm mt-2 align-self-center"
                    t-on-click="toggleTraceback"
                    t-out="state.showTraceback ? 'Hide Details' : 'Show Technical Details'"
                />
            </t>
        </div>
    `;static props={name:{type:String},status:{type:Number,optional:true},traceback:{type:String,optional:true},};setup(){this.state=useState({showTraceback:false});}
toggleTraceback(){this.state.showTraceback=!this.state.showTraceback;}
onClickClipboard(){browser.navigator.clipboard.writeText(`${this.props.name}\n\n${this.props.message}\n\n${this.contextDetails}\n\n${this.props.traceback}`);}}
return __exports;});;

/* /api_doc/static/src/components/doc_loading_indicator.js */
odoo.define('@api_doc/components/doc_loading_indicator',['@odoo/owl'],function(require){'use strict';let __exports={};const{Component,xml}=require("@odoo/owl");const DocLoadingIndicator=__exports.DocLoadingIndicator=class DocLoadingIndicator extends Component{static template=xml`
        <div t-if="!props.isLoaded" class="o-doc-load-wrapper o-fade-in position-relative h-100 w-100 bg-2 rounded">
            <div class="o-doc-load-activity position-absolute h-100"></div>
        </div>
        <div t-else="" t-att-class="props.class">
            <t t-slot="default"/>
        </div>
    `;static components={};static props={isLoaded:{type:Boolean},class:{type:String,optional:true},slots:true,};static defaultProps={class:"",};}
return __exports;});;

/* /api_doc/static/src/components/doc_method.js */
odoo.define('@api_doc/components/doc_method',['@odoo/owl','@api_doc/components/doc_request','@api_doc/components/doc_table','@api_doc/utils/doc_model_utils','@api_doc/utils/doc_ui_store'],function(require){'use strict';let __exports={};const{Component,useState,markup}=require("@odoo/owl");const{DocRequest}=require("@api_doc/components/doc_request");const{DocTable,TABLE_TYPES}=require("@api_doc/components/doc_table");const{getParameterDefaultValue}=require("@api_doc/utils/doc_model_utils");const{useDocUI}=require("@api_doc/utils/doc_ui_store");const DocMethod=__exports.DocMethod=class DocMethod extends Component{static template="web.DocMethod";static components={DocRequest,DocTable,};static props={method:Object,class:String,};setup(){this.ui=useDocUI();this.state=useState({open:true});this.parametersData={headers:["Name","Type","Default Value","Description"],items:Object.entries(this.method.parameters).map(([name,options])=>[{type:TABLE_TYPES.Code,value:name},{type:TABLE_TYPES.Code,value:"annotation"in options?options.annotation:"-",},{type:TABLE_TYPES.Code,value:this.getDefaultValue(options)},{type:TABLE_TYPES.Tooltip,value:options.doc?markup(options.doc):""},]),};}
get method(){return this.props.method;}
get parameters(){return this.method.parameters.filter((a)=>a!=="self");}
get doc(){return this.method.doc;}
get isVertical(){return this.ui.size<1400;}
getDefaultValue(param){if("default"in param){return typeof param.default==="string"?`"${param.default}"`:param.default;}else{return"-";}}
get request(){if(this.method.request){return this.method.request;}
const request={ids:[],context:{},};if(this.method.api){delete request.ids;}
for(const paramName in this.method.parameters){const param=this.method.parameters[paramName];request[paramName]=getParameterDefaultValue(paramName,param);}
return request;}}
return __exports;});;

/* /api_doc/static/src/components/doc_modal_api_key.js */
odoo.define('@api_doc/components/doc_modal_api_key',['@odoo/owl'],function(require){'use strict';let __exports={};const{Component,useExternalListener,useRef}=require("@odoo/owl");const ApiKeyModal=__exports.ApiKeyModal=class ApiKeyModal extends Component{static template="web.DocApiKeyModal";static components={};static props={};setup(){this.modalRef=useRef("modalRef");useExternalListener(window,"keydown",(event)=>{if(event.key==="Escape"){this.cancel();}});useExternalListener(window,"click",(event)=>{if(!this.modalRef.el.contains(event.target)){this.cancel();}});}
save(){this.env.modelStore.setAPIKey(this.modalRef.el.querySelector(":scope input").value.trim());this.env.modelStore.showApiKeyModal=false;}
cancel(){this.env.modelStore.showApiKeyModal=false;}
async openAPIKeyForm(){window.open(`${window.location.origin}/odoo/action-doc_api_key_wizard`,"_blank");}}
return __exports;});;

/* /api_doc/static/src/components/doc_modal_search.js */
odoo.define('@api_doc/components/doc_modal_search',['@odoo/owl','@web/core/utils/timing','@api_doc/utils/doc_model_search'],function(require){'use strict';let __exports={};const{Component,useRef,onMounted,useExternalListener,useState}=require("@odoo/owl");const{useDebounced}=require("@web/core/utils/timing");const{search}=require("@api_doc/utils/doc_model_search");const SearchModal=__exports.SearchModal=class SearchModal extends Component{static template="web.DocSearchModal";static components={};static props={close:{type:Function},};setup(){this.seachRef=useRef("seachRef");this.modalRef=useRef("modalRef");this.scrollRef=useRef("scrollRef");this.results=[];this.itemHeight=45;this.itemMargin=10;this.state=useState({resultCount:0,results:[],activeFilters:{models:true,methods:true,fields:true,},});this.search=useDebounced((query)=>{this.results=search(this.env.modelStore.models,query,this.state.activeFilters);this.state.resultCount=this.results.length;this.scrollRef.el.scrollTop=0;this.onScroll(this.scrollRef.el);},300);useExternalListener(window,"keydown",(event)=>{if(event.key==="Escape"){this.props.close();}});useExternalListener(window,"click",(event)=>{if(!this.modalRef.el.contains(event.target)){this.props.close();}});onMounted(()=>{this.seachRef.el.focus();});}
onInput(event){if(event.target.value.trim()){this.search(event.target.value.trim());}}
onSelect(result){this.env.modelStore.setActiveModel(result);this.props.close();}
onFilterClick(filter){this.state.activeFilters[filter]=!this.state.activeFilters[filter];this.search(this.seachRef.el.value.trim());}
onScroll(container){const rowHeight=this.itemHeight+this.itemMargin;const nodePadding=10;let startIndex=Math.floor(container.scrollTop/rowHeight)-nodePadding;startIndex=Math.max(0,startIndex);const viewportHeight=container.getBoundingClientRect().height;let visibleCount=Math.ceil(viewportHeight/rowHeight)+2*nodePadding;visibleCount=Math.min(this.results.length-startIndex,visibleCount);this.state.scrollHeight=this.results.length*rowHeight;this.state.scrollOffsetY=startIndex*rowHeight;this.state.results=this.results.slice(startIndex,startIndex+visibleCount);}}
return __exports;});;

/* /api_doc/static/src/components/doc_model.js */
odoo.define('@api_doc/components/doc_model',['@odoo/owl','@api_doc/components/doc_table','@api_doc/utils/doc_model_utils','@api_doc/components/doc_method','@api_doc/components/doc_loading_indicator','@api_doc/utils/doc_ui_store','@api_doc/components/doc_error_dialog'],function(require){'use strict';let __exports={};const{Component,useState,useEffect,onPatched,markup}=require("@odoo/owl");const{DocTable,TABLE_TYPES}=require("@api_doc/components/doc_table");const{getCrudMethodsExamples}=require("@api_doc/utils/doc_model_utils");const{DocMethod}=require("@api_doc/components/doc_method");const{DocLoadingIndicator}=require("@api_doc/components/doc_loading_indicator");const{useDocUI}=require("@api_doc/utils/doc_ui_store");const{DocErrorDialog}=require("@api_doc/components/doc_error_dialog");const TYPE_COLORS={"text-success":["integer","char","boolean","selection","float"],"text-info":["html","datetime","date","binary"],"text-warning":["many2one","many2many","one2many","many2one_reference"],};function getTypeColor(type){for(const key in TYPE_COLORS){if(TYPE_COLORS[key].includes(type)){return key;}}}
function getTypeData(fieldData){const data={type:TABLE_TYPES.Code,value:fieldData.type,class:getTypeColor(fieldData.type),};if(fieldData.type==="selection"){data.subData={headers:["Value","Label"],items:fieldData.selection,};}
if(fieldData.relation){data.relation=fieldData.relation;}
return data;};const DocModel=__exports.DocModel=class DocModel extends Component{static template="web.DocModel";static components={DocTable,DocMethod,DocLoadingIndicator,DocErrorDialog,};static props={};setup(){this.state=useState({model:undefined,modelData:{items:[]},crudMethods:[],methods:[],fields:{data:{items:[]}},modules:[],activeModules:{core:true,base:false,},showModulesFilter:true,});this.ui=useDocUI();this.modelStore=useState(this.env.modelStore);this.update();useEffect(()=>{this.update();},()=>[this.modelStore.activeModel,this.modelStore.activeMethod,this.modelStore.activeField,],);let lastFocusedElement=null
onPatched(()=>{let el=null;if(this.modelStore.activeMethod){el=document.getElementById(this.modelStore.activeMethod);}
if(this.modelStore.activeField){el=document.getElementById(this.modelStore.activeField);}
if(el&&el!=lastFocusedElement){lastFocusedElement=el;el.scrollIntoView({behavior:"smooth"});}});}
get modelName(){return this.state.model?.name??"";}
async update(){if(!this.state.model||this.state.model.model!==this.modelStore.activeModel.model){this.updateModel(this.modelStore.activeModel);}
this.updateActives();}
updateModel(model){const modelId=model.model;this.state.model={model:modelId,name:model.name,doc:"",fields:null,error:null,};this.state.modelData={items:[]};this.state.methods=[];this.state.modules=[];this.modelStore.loadModel(modelId).then((model)=>{if(this.state.model.model!==model.model){return;}
this.state.model=model;this.state.modelData={items:[["Model Name",{type:"code",value:model.model}],...(model.doc?[["Description",model.doc]]:[]),]};this.updateModules();this.updateMethods();this.updateFields();const crudExamples=getCrudMethodsExamples(model);for(const method of this.state.methods){if(method.name in crudExamples){method.request=crudExamples[method.name].request;method.responseCode=crudExamples[method.name].responseCode;}}
this.updateActives();}).catch((error)=>{console.error(error);this.state.error=error;});}
isModuleActive(module){return!module||this.state.activeModules[module];}
updateModules(){const model=this.state.model;let modules=new Set();Object.values(model.fields).forEach((f)=>f.module&&modules.add(f.module));Object.values(model.methods).forEach((m)=>m.module&&modules.add(m.module));modules=[...modules];modules.sort((a,b)=>(a==="core"?-1:b==="core"?1:a.localeCompare(b)));this.state.modules=modules;}
updateMethods(){const model=this.state.model;const methods=[];for(const methodName in model.methods){const method=model.methods[methodName];let returnDoc="";let returnAnnotation="";if(method.return){returnDoc=method.return.doc?markup(method.return.doc):"";returnAnnotation=method.return.annotation;}
methods.push({name:methodName,module:method.module,api:method.api,doc:method.doc,model:model.model,parameters:method.parameters,url:`/json/2/${model.model}/${methodName}`,returnDoc:returnDoc,returnAnnotation:returnAnnotation,});}
const crudOrder=["search_read","search","read","create","write","unlink"];methods.sort((a,b)=>{const aIndex=crudOrder.indexOf(a.name);const bIndex=crudOrder.indexOf(b.name);if(aIndex>=0&&bIndex>=0){return aIndex-bIndex;}else if(aIndex>=0){return-1;}else if(bIndex>=0){return 1;}
return a.name.localeCompare(b.name)});this.state.methods=methods;}
updateFields(){const model=this.state.model;let fields=[];let activeIndex=-1;if(model&&model.fields){fields=Object.values(model.fields);}
fields=fields.filter((fieldData)=>this.isModuleActive(fieldData.module)).map((fieldData,index)=>{if(fieldData.name===this.modelStore.activeField){activeIndex=index}
return[{type:TABLE_TYPES.Code,value:fieldData.name},getTypeData(fieldData),fieldData.string,{type:TABLE_TYPES.Code,value:fieldData.required?"required":"optional",class:fieldData.required?"text-danger":"text-muted",},{type:TABLE_TYPES.Tooltip,value:fieldData.help||"",},{type:TABLE_TYPES.Code,value:fieldData.module||"",},]});fields.sort((a,b)=>a[0].value.localeCompare(b[0].value));this.state.fields={activeIndex,data:{headers:["Name","Type","Description","Required","Help","Module"],items:fields,},};}
async updateActives(){const method=this.state.model.methods?.[this.modelStore.activeMethod];const activeModules=[];if(method){activeModules.push(method.module);}
const fieldData=this.state.model.fields?.[this.modelStore.activeField];if(fieldData){activeModules.push(fieldData.module);}
this.setActiveModules(activeModules,true);}
setActiveModules(modules,active){for(const module of modules){this.state.activeModules[module]=active;}
this.updateFields();}
toggleAllModules(select){this.setActiveModules(this.state.modules,select);}}
return __exports;});;

/* /api_doc/static/src/components/doc_request.js */
odoo.define('@api_doc/components/doc_request',['@odoo/owl','@api_doc/utils/doc_code_gen','@web/core/code_editor/code_editor','@web/core/browser/browser'],function(require){'use strict';let __exports={};const{Component,useState}=require("@odoo/owl");const{LANGUAGES,createRequestCode}=require("@api_doc/utils/doc_code_gen");const{CodeEditor}=require("@web/core/code_editor/code_editor");const{browser}=require("@web/core/browser/browser");class CopyableCodeEditor extends CodeEditor{static template="web.DocRequest.CodeEditor";copyToClipboard(){navigator?.clipboard?.writeText(this.aceEditor.getValue());this.state.copied=true;setTimeout(()=>{this.state.copied=false;},1000);}}
const DocRequest=__exports.DocRequest=class DocRequest extends Component{static template="web.DocRequest";static components={CodeEditor:CopyableCodeEditor,};static props={url:String,request:{optional:true},method:{type:String,optional:true},};static defaultProps={httpMethod:"POST",};setup(){this.maxLines=Infinity;this.LANGUAGES=LANGUAGES;this.state=useState({exampleLanguage:LANGUAGES.json,exampleCode:"",requestCode:this.createRequestCode(LANGUAGES.json),response:{},requestTab:0,showTraceback:false});this.selectLanguage(localStorage.getItem("doc/code-lang")||LANGUAGES.json);}
selectLanguage(language){localStorage.setItem("doc/code-lang",language);this.state.exampleLanguage=language;this.state.exampleCode=this.createRequestCode(language);}
createRequestCode(language){return createRequestCode({language,url:window.location.origin+this.props.url,apiKey:this.env.modelStore.apiKey,requestObj:this.props.request,});}
get responseText(){const response=this.state.response;return response.error||response.body;}
get hasResponse(){return this.state.response.error||this.state.response.body;}
async execute(){this.state.response={};const result=await this.env.modelStore.executeRequest(this.props.url,this.state.requestCode);if(result){this.state.response=result;}}
toggleTraceback(){this.state.showTraceback=!this.state.showTraceback;}
onClickClipboard(){browser.navigator.clipboard.writeText(`Error ${this.state.response.status}:\n\n${this.responseText.title}\n\n${this.responseText.traceback}`);}}
return __exports;});;

/* /api_doc/static/src/components/doc_sidebar.js */
odoo.define('@api_doc/components/doc_sidebar',['@odoo/owl','@api_doc/utils/doc_model_search'],function(require){'use strict';let __exports={};const{Component,useEffect,useRef,useState}=require("@odoo/owl");const{simplifyString}=require("@api_doc/utils/doc_model_search");const DocSidebar=__exports.DocSidebar=class DocSidebar extends Component{static template="web.DocSidebar";static components={};static props={};setup(){this.containerRef=useRef("containerRef");this.modelStore=useState(this.env.modelStore);this.state=useState({collapseAddons:{},searchValue:"",});useEffect(()=>{this.containerRef.el?.querySelector(":scope .o_active")?.scrollIntoView();},()=>[this.containerRef.el]);for(const addon of this.filteredAddons){if(!(addon.name in this.state.collapseAddons)){this.state.collapseAddons[addon.name]=false;}}}
onSearchInput(event){this.state.searchValue=event.target.value;this.containerRef.el.scrollTop=0;}
_toggleAllAddons(isCollapsed){const allAddons=this.filteredAddons;allAddons.forEach((a)=>this.state.collapseAddons[a.name]=!isCollapsed);}
toggleAddon(event,addonName){const isCollapsed=this.isCollapsed(addonName);if(event.altKey&&event.ctrlKey){this._toggleAllAddons(isCollapsed);}else{this.state.collapseAddons[addonName]=!isCollapsed;}}
isCollapsed(addonName){return this.state.collapseAddons[addonName];}
isActiveItem(model){return(this.modelStore.activeModel&&model.name===this.modelStore.activeModel.name&&model.model==this.modelStore.activeModel.model);}
get filteredAddons(){const queryStr=simplifyString(this.state.searchValue);if(queryStr<=0){return[...this.modelStore.addons];}else{const visibleAddons=[];for(const addon of this.modelStore.addons){let models=addon.models;if(!addon.name.includes(queryStr)){models=addon.models.filter((model)=>simplifyString(model.name).includes(queryStr)||simplifyString(model.model).includes(queryStr));}
if(models.length>0){visibleAddons.push({name:addon.name,models,});}}
return visibleAddons;}}}
return __exports;});;

/* /api_doc/static/src/components/doc_table.js */
odoo.define('@api_doc/components/doc_table',['@odoo/owl'],function(require){'use strict';let __exports={};const{Component,useState,useExternalListener,useRef,onWillRender}=require("@odoo/owl");const TABLE_TYPES=__exports.TABLE_TYPES={Id:"id",Code:"code-like",Tooltip:"tooltip",};const DocTable=__exports.DocTable=class DocTable extends Component{static components={DocTable};static template="web.DocTable";static props={data:true,};setup(){this.subTableRef=useRef("subTableRef");this.tooltipRef=useRef("tooltipRef");this.state=useState({sortBy:0,sortOrder:"desc",subTable:undefined,tooltipContent:"",tooltipStyle:"",});this.isHovering=false;this.hideTimeout=null;this.requestAnim=null;onWillRender(()=>{this.items=this.computeItems();});useExternalListener(window,"click",(event)=>{if(this.subTableRef.el&&this.subTableRef.el!==event.target&&!this.subTableRef.el.contains(event.target)){this.state.subTable=null;}});useExternalListener(window,"scroll",()=>(this.state.subTable=null));}
showDynamicTooltip(event,content){if(this.requestAnim)cancelAnimationFrame(this.requestAnim);if(this.hideTimeout)clearTimeout(this.hideTimeout);this.activeHoverTarget=event.target;this.isHovering=true;const triggerRect=event.target.getBoundingClientRect();this.requestAnim=requestAnimationFrame(()=>{if(!this.tooltipRef.el||!this.isHovering){return;}
const top=triggerRect.top;const left=triggerRect.left+20;this.state.tooltipContent=content;this.state.tooltipStyle=`
                top: ${top}px;
                left: ${left}px;
                opacity: 1;
                pointer-events: auto;
            `;});}
scheduleHide(event){if(this.hideTimeout)clearTimeout(this.hideTimeout);const currentTarget=event.target;this.isHovering=false;this.hideTimeout=setTimeout(()=>{if(!this.isHovering){this.state.tooltipStyle=`
                    top: ${this.tooltipRef.el ? this.tooltipRef.el.style.top : 0};
                    left: ${this.tooltipRef.el ? this.tooltipRef.el.style.left : 0};
                    opacity: 0;
                    pointer-events: none;
                `;setTimeout(()=>{if(currentTarget===this.activeHoverTarget){this.state.tooltipContent="";}},200);}},100);}
keepAlive(){if(this.hideTimeout)clearTimeout(this.hideTimeout);this.isHovering=true;}
computeItems(){if(this.state.sortBy>=0){const items=[...this.props.data.items];items.sort((itemA,itemB)=>{const a=this.getValue(itemA[this.state.sortBy]);const b=this.getValue(itemB[this.state.sortBy]);if(this.state.sortOrder==="asc"){return b.localeCompare(a);}else{return a.localeCompare(b);}});return items;}else{return this.props.data.items;}}
showSubTable(event,subData){if(subData){this.state.subTable=subData;const rect=event.target.getBoundingClientRect();this.state.subTableStyle=`top: ${rect.bottom + 3}px; left: ${
                rect.left
            }px; z-index: 50;`;}}
getId(values){return values.find((v)=>v.type===TABLE_TYPES.Id)?.value;}
getTag(row){return row&&typeof row==="object"&&row.type==="code"?"pre":"span";}
getValue(row){return String(row&&typeof row==="object"?row.value:row);}
getClass(row){const classList=[];if(row&&typeof row==="object"){if(row.type==="code"){classList.push("font-monospace");}
if(row.class){classList.push(row.class);}}
return classList.join(" ");}
onRowHeaderClick(rowIndex){if(this.state.sortBy===rowIndex){this.state.sortOrder=this.state.sortOrder==="asc"?"desc":"asc";}
this.state.sortBy=rowIndex;}
getSortIcon(rowIndex){if(this.state.sortBy!==rowIndex){return"fa fa-sort";}else if(this.state.sortOrder==="asc"){return"fa fa-sort-asc";}else{return"fa fa-sort-desc";}}
goToModel(model){this.env.modelStore.setActiveModel({model});}}
return __exports;});;

/* /api_doc/static/src/doc_client.js */
odoo.define('@api_doc/doc_client',['@odoo/owl','@api_doc/doc_model_store','@api_doc/utils/doc_ui_store','@api_doc/components/doc_modal_api_key','@api_doc/components/doc_modal_search','@api_doc/components/doc_sidebar','@api_doc/components/doc_model','@api_doc/components/doc_error_dialog'],function(require){'use strict';let __exports={};const{Component,useState,onMounted,useSubEnv}=require("@odoo/owl");const{ModelStore}=require("@api_doc/doc_model_store");const{useDocUI}=require("@api_doc/utils/doc_ui_store");const{ApiKeyModal}=require("@api_doc/components/doc_modal_api_key");const{SearchModal}=require("@api_doc/components/doc_modal_search");const{DocSidebar}=require("@api_doc/components/doc_sidebar");const{DocModel}=require("@api_doc/components/doc_model");const{DocErrorDialog}=require("@api_doc/components/doc_error_dialog");const DocClient=__exports.DocClient=class DocClient extends Component{static template="api_doc.DocClient";static components={DocSidebar,DocModel,ApiKeyModal,SearchModal,DocErrorDialog,};static props={};setup(){this.setTheme(localStorage.getItem("theme")||"odoo-dark");this.ui=useDocUI();this.modelStore=useState(new ModelStore());useSubEnv({modelStore:this.modelStore});this.state=useState({showSearchModal:false});onMounted(async()=>{await this.modelStore.loadModels();this.selectUrlModel();});window.addEventListener("popstate",()=>{this.selectUrlModel();});}
selectUrlModel(){const actives={};const parts=window.location.pathname.split("/");const docIndex=parts.indexOf("doc");const urlModel=parts[docIndex+1];if(urlModel){const model=this.modelStore.getBasicModelData(urlModel);if(model){actives.model=model;}}
const hash=window.location.hash.substring(1);const model=actives.model;if(model&&hash){if(model.methods.includes(hash)){actives.method=hash;}else if(model.fields[hash]){actives.field=hash;}}
this.modelStore.setActiveModel(actives);}
toggleTheme(){this.setTheme(this.theme==="odoo-dark"?"odoo-light":"odoo-dark");}
setTheme(theme){this.theme=theme;localStorage.setItem("theme",theme);document.body.setAttribute("theme",theme);}}
return __exports;});;

/* /api_doc/static/src/doc_model_store.js */
odoo.define('@api_doc/doc_model_store',['@odoo/owl','@web/core/utils/reactive'],function(require){'use strict';let __exports={};const{markRaw,markup}=require("@odoo/owl");const{Reactive}=require("@web/core/utils/reactive");function tryParseJSON(jsonString){try{const json=JSON.parse(jsonString);return json&&typeof json==="object"?json:null;}catch{return null;}}
async function tryFetch(input){try{const response=await fetch(input);let responseJson;try{responseJson=await response.json();}catch(err){throw new DocAPIError({name:"Invalid JSON Response",status:response.status,traceback:err,});}
if(!response.ok){throw new DocAPIError({name:response.status===500?"Internal Server Error":`HTTP $(response.status)`,status:response.status,traceback:responseJson.debug,});}
return responseJson;}catch(err){if(err instanceof DocAPIError)throw err;throw new DocAPIError({name:"Network Error",status:null,traceback:err,});}}
class DocAPIError extends Error{constructor({name,status,traceback}={}){super(name);this.name=name;this.status=status??null;this.traceback=traceback??null;}}
const ModelStore=__exports.ModelStore=class ModelStore extends Reactive{constructor(){super();this.models=[];this._addons={};this.apiKey=null;this.showApiKeyModal=false;this.activeModel=null;this.activeField=null;this.activeMethod=null;this.error=null;}
get addons(){return Object.values(this._addons);}
async loadModels(){try{console.info("Loading Models...");const response=await tryFetch(`/doc/index.json`);const{models}=response;console.info("Models List Loaded",models);models.sort((a,b)=>a.model.localeCompare(b.model));const addons={};for(const model of models){const addonName=model.model.split(".")[0];if(addons[addonName]){addons[addonName].models.push(model);}else{addons[addonName]={name:addonName,models:[model],};}}
const other={name:"other",models:[]};for(const category in addons){const models=addons[category].models;if(models.length<=3){other.models.push(...models);delete addons[category];}}
addons["other"]=other;this.models=markRaw(models);this._addons=markRaw(addons);}catch(e){this.error=e;}}
async loadModel(modelId){try{const model=await tryFetch(`/doc/${modelId}.json`);if(model.doc){model.doc=markup(model.doc);}
Object.values(model.methods).forEach((method)=>{method.doc=method.doc?markup(method.doc):null;});console.info("Model Loaded: ",model);return model;}catch(e){this.error=e;}}
getBasicModelData(modelId){return this.models.find((m)=>m.model===modelId);}
setAPIKey(apiKey){if(typeof apiKey==="string"&&apiKey.length>0){this.apiKey=apiKey;}}
setActiveModel({model,method=null,field=null}){if(typeof model==="string"){model=this.getBasicModelData(model);}
if(model){this.activeModel=model;this.activeMethod=method;this.activeField=field;let url=`/doc/${model.model}`;if(method||field){url+="#"+(method||field);}
window.history.pushState({},"",url);}}
async executeRequest(url,requestBody){if(!this.apiKey){this.showApiKeyModal=true;return null;}
const result={status:null,body:null,error:null,};try{const request={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,},body:requestBody,};const response=await fetch(url,request);result.status=response.status;const body=await response.text();const json=tryParseJSON(body);if(response.ok){result.body=json?JSON.stringify(json,null,2):body;}else{result.error=!json?body:{title:json.message,traceback:json.debug,};}}catch(error){result.error=error;}
return result;}}
return __exports;});;

/* /api_doc/static/src/start_doc_client.js */
odoo.define('@api_doc/start_doc_client',['@odoo/owl','@web/core/templates','@api_doc/doc_client'],function(require){'use strict';let __exports={};const{App,whenReady}=require("@odoo/owl");const{getTemplate}=require("@web/core/templates");const{DocClient}=require("@api_doc/doc_client");__exports.startDocClient=startDocClient;async function startDocClient(){await whenReady();const app=new App(DocClient,{getTemplate,});app.mount(document.body);}
startDocClient();return __exports;});;

/* /api_doc/static/src/utils/doc_code_gen.js */
odoo.define('@api_doc/utils/doc_code_gen',[],function(require){'use strict';let __exports={};const LANGUAGES=__exports.LANGUAGES={json:"json",javascript:"javascript",python:"python",cURL:"bash",};function noQuotesStringify(obj){var json=JSON.stringify(obj,null,4);return json.replace(/^[\t ]*"[^:\n\r]+(?<!\\)":/gm,(m)=>m.replace(/"/g,""));}
__exports.createRequestCode=createRequestCode;function createRequestCode({language,url,requestObj}){if(LANGUAGES[language]===LANGUAGES.json){const replacer=(key,value)=>{if(key==="domain"&&Array.isArray(value)){return{__inline_json__:JSON.stringify(value)};}
return value;};let json=JSON.stringify(requestObj,replacer,4);json=json.replace(/{\s*"__inline_json__":\s*"(.+?)"\s*}/g,(match,p1)=>JSON.parse(`"${p1}"`));return json;}else if(LANGUAGES[language]===LANGUAGES.javascript){const objStr=noQuotesStringify(requestObj).replace(/\n/gm,"\n    ");return`\
(async () => {
    // You MUST store this key securely. Place it in an
    // environment variable or in in a file outside of
    // git (e.g. your home directory).
    const apiKey = "YOUR_API_KEY";

    const request = {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + apiKey,
            // "X-Odoo-Database": "...",
        },
        body: JSON.stringify(${objStr}),
    };

    const response = await fetch("${url}", request);
    if (response.ok) {
        const data = await response.json();
        console.log(data)
    } else {
        // Handle errors
    }
})();`;}else if(LANGUAGES[language]===LANGUAGES.cURL){const objStr=JSON.stringify(requestObj);return`\
curl '${url}'\\
  -X POST \\
  --oauth2-bearer YOUR_API_KEY \\
# -H "X-Odoo-Database: ..." \\
  -H "Content-Type: application/json" \\
  -d '${objStr}'
`;}else if(LANGUAGES[language]===LANGUAGES.python){const objStr=JSON.stringify(requestObj,null,4).replace(/\bnull\b/g,"None").replaceAll("\n","\n    ").trim();return`\
# You MUST store this key securely. Place it in an
# environment variable or in in a file outside of
# git (e.g. your home directory).
api_key = "YOUR_API_KEY"

${"import"} requests
response = requests.post(
    "${url}",
    headers={
        "Authorization": f"Bearer {api_key}",
        # "X-Odoo-Database": "...",
    },
    json=${objStr},
)
response.raise_for_status()
data = response.json()
print(data)
`;}}
return __exports;});;

/* /api_doc/static/src/utils/doc_model_search.js */
odoo.define('@api_doc/utils/doc_model_search',[],function(require){'use strict';let __exports={};__exports.simplifyString=simplifyString;function simplifyString(str){return(str?.trim().toLowerCase().replace(/[^a-zA-Z\d]/g,"")??"");}
function stringMatch(query,str){if(simplifyString(str).includes(query)){return query.length/str.length;}else{return 0;}}
__exports.search=search;function search(models,query,filters){query=simplifyString(query);const results=[];for(const model of models){const modelMatch=stringMatch(query,model.model);const modelNameMatch=stringMatch(query,model.name);if(filters.models&&(modelMatch>0||modelNameMatch>0)){results.push({priority:10*Math.max(modelMatch,modelNameMatch),model,type:"model",label:model.name,path:model.model,});}
if(filters.fields){for(const field in model.fields){const path=`${model.model}/${field}`;const pathMatch=stringMatch(query,path);const fieldMatch=stringMatch(query,field);const labelMatch=stringMatch(query,model.fields[field].string);if(pathMatch>0||fieldMatch>0||labelMatch>0){results.push({priority:5*Math.max(pathMatch,fieldMatch,labelMatch),model,field,type:"field",label:model.fields[field].string,path,});}}}
if(filters.methods){for(const method of model.methods){const path=`${model.model}/${method}`;const pathMatch=stringMatch(query,path);const methodMatch=stringMatch(query,method);if(pathMatch>0||methodMatch>0){results.push({priority:5*Math.max(pathMatch,methodMatch),model,method,type:"method",label:method,path:path,});}}}}
results.sort((a,b)=>{if(a.priority===b.priority){return a.label.localeCompare(b.label);}else{return b.priority-a.priority;}});return results;}
return __exports;});;

/* /api_doc/static/src/utils/doc_model_utils.js */
odoo.define('@api_doc/utils/doc_model_utils',[],function(require){'use strict';let __exports={};const FIELDS_DEFAULT=[{types:["integer","float","many2one_reference"],value:0,},{types:["char","selection","html"],value:"",},{types:["boolean","many2one"],value:false,},{types:["datetime","date"],value:Date.now.toString(),},{types:["binary"],value:null,},{types:["one2many","many2many"],value:"[]",},];function getFieldDefaultValue(field){for(const fieldDefault of FIELDS_DEFAULT){if(fieldDefault.types.includes(field.type)){return fieldDefault.value;}}
return null;}
__exports.getCreateDict=getCreateDict;function getCreateDict(model){const value={};for(const fieldName in model.fields){if(model.fields[fieldName].required){value[fieldName]=getFieldDefaultValue(model.fields[fieldName]);}}
return value;}
__exports.getCrudMethodsExamples=getCrudMethodsExamples;function getCrudMethodsExamples(model){return{create:{responseCode:`true`,request:{vals_list:[getCreateDict(model)],},},read:{request:{ids:[0,1],fields:["display_name","name","create_date"],},},search:{responseCode:`\
[
    1,
    2
]`,request:{domain:[["display_name","ilike","a%"]],},},search_count:{responseCode:`10`,request:{domain:[["display_name","ilike","a%"]],},},search_read:{responseCode:`10`,request:{domain:[["display_name","ilike","a%"]],fields:["display_name"],limit:20,},},unlink:{responseCode:`true`,request:{ids:[],},},write:{responseCode:`true`,request:{ids:[0],vals:{display_name:"Dope New Name",},},},name_search:{request:{domain:[["display_name","ilike","a%"]],},responseCode:`\
[
    [
        1,
        "Record 1 Name"
    ],
    [
        2,
        "Record 2 Name"
    ]
]`,},read_group:{name:"read_group",request:{fields:["id","display_name","write_date"],groupby:"write_date",domain:[["display_name","ilike","a%"]],},},};}
__exports.getParameterDefaultValue=getParameterDefaultValue;function getParameterDefaultValue(name,parameter){if("default"in parameter){return parameter.default;}else if(/\bdomaintype\b/i.test(parameter.type)){return[["display_name","ilike","a%"]];}else if(/\bstr\b/i.test(parameter.type)){return"";}else if(/\b(int|float|complex)\b/i.test(parameter.type)){return 0;}else if(/\bbool\b/i.test(parameter.type)){return false;}else if(/args/i.test(name)||/\b(list|sequence|collection|tuple|range|set)\b/i.test(parameter.annotation)){return[];}else if(/dict/i.test(parameter.annotation)){return{};}else{return"";}}
return __exports;});;

/* /api_doc/static/src/utils/doc_ui_store.js */
odoo.define('@api_doc/utils/doc_ui_store',['@odoo/owl'],function(require){'use strict';let __exports={};const{useEnv,useExternalListener,useState,useSubEnv}=require("@odoo/owl");function isSmall(){return window.innerWidth<960;}
__exports.useDocUI=useDocUI;function useDocUI(){const env=useEnv();if(env.ui){return useState(env.ui);}
const ui=useState({isSmall:isSmall(),size:window.innerWidth,});useSubEnv({ui});useExternalListener(window,"resize",()=>{ui.size=window.innerWidth;ui.isSmall=isSmall();});return ui;}
return __exports;});

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

                    odoo.define("api_doc.assets.bundle.xml", ["@web/core/templates"], function(require) {
                        "use strict";
                        const { checkPrimaryTemplateParents, registerTemplate, registerTemplateExtension } = require("@web/core/templates");
                        /* api_doc.assets */
                        registerTemplate("web.CodeEditor", `/web/static/src/core/code_editor/code_editor.xml`, `<t t-name="web.CodeEditor" xml:space="preserve">
        <div t-ref="editorRef" class="w-100" t-att-class="props.class" t-att-data-mode="state.activeMode"/>
    </t>

`);
registerTemplate("web.DocMethod", `/api_doc/static/src/components/doc_method.xml`, `<t t-name="web.DocMethod" xml:space="preserve">
    <article class="o-doc-method mb-2 rounded" t-att-class="props.class" t-att-id="this.method.name">
        <div class="o-doc-method-header position-sticky d-flex flex-nowrap w-100 cursor-pointer rounded bg-1" t-on-click="() =&gt; this.state.open = !this.state.open" t-att-class="{ ['border-bottom']: this.state.open, o_collapsed: !this.state.open }" role="button">
            <div class="icon-btn" role="button" t-att-class="{ o_collapsed: !this.state.open }">
                <i class="fa fa-angle-right ps-1 pt-1" aria-hidden="true"/>
            </div>
            <h4 class="flex-grow ms-1" t-out="this.method.name"/>
            <a class="ms-2 fs-5" t-att-href="'#' + method.name" t-on-click.stop="">#</a>
            <div class="text-muted align-self-center ms-auto" t-out="this.method.module"/>
        </div>

        <div t-if="state.open" class="o-doc-method-content p-3 bg-1 d-flex flex-nowrap" t-att-class="{ 'flex-column': isVertical }">
            <div t-att-class="{ 'w-100': isVertical, 'w-50 pe-2': !isVertical }">
                <h4>Route</h4>
                <pre t-out="this.method.url" class="mb-2"/>

                <t t-if="doc">
                    <h4 class="mt-2">Description</h4>
                    <p class="doc_method_description mb-2" t-out="doc"/>
                </t>
                <h4 class="mt-2">Parameters</h4>
                <DocTable t-if="parametersData.items.length &gt; 0" data="parametersData"/>
                <div class="text-muted" t-else="">There's no parameters for this method</div>
                <t t-if="(method.returnAnnotation || method.returnDoc)">
                    <h4 class="mt-2">Return</h4>
                    <pre t-if="method.returnAnnotation" t-out="method.returnAnnotation"/>
                    <p class="doc_method_description mb-2" t-if="method.returnDoc" t-out="method.returnDoc"/>
                </t>
            </div>
            <div t-att-class="{ 'w-100 pt-2 mt-2 border-top': isVertical, 'w-50 ps-3 border-start': !isVertical }">
                <DocRequest url="method.url" request="request" method="method"/>
            </div>
        </div>
    </article>
</t>
`);
registerTemplate("web.DocApiKeyModal", `/api_doc/static/src/components/doc_modal_api_key.xml`, `<t t-name="web.DocApiKeyModal" xml:space="preserve">
    <div class="modal-bg d-flex flex-nowrap justify-content-center align-items-center">
        <div class="modal h-auto p-3 d-flex flex-nowrap flex-column mb-2" style="width: 25rem" t-ref="modalRef">
            <h2 class="mb-2">API key</h2>

            <p class="mb-1">To try the API, please insert your API key here</p>
            <a href="#" t-on-click="openAPIKeyForm">Generate a new API key here</a>
            <input class="mt-2 w-100" type="password" name="api-key" autocorrect="off" autocomplete="one-time-code"/>

            <div class="d-flex flex-nowrap flex-content-between mt-2">
                <button class="btn me-1" t-on-click="save">Save</button>
                <button class="btn" t-on-click="cancel">Cancel</button>
            </div>
        </div>
    </div>
</t>

`);
registerTemplate("web.DocSearchModal", `/api_doc/static/src/components/doc_modal_search.xml`, `<t t-name="web.DocSearchModal" xml:space="preserve">
    <div class="modal-bg d-flex flex-nowrap justify-content-center align-items-center">
        <div class="modal p-2 d-flex flew-nowrap flex-column mb-2" style="height: 40rem; width: 40rem" t-ref="modalRef">
            <input class="mb-2" type="text" autocorrect="off" placeholder="Find anything..." t-on-input="onInput" t-ref="seachRef"/>

            <div class="d-flex flex-nowrap mb-2 align-items-center">
                <div t-foreach="state.activeFilters" t-as="filter" t-key="filter" class="d-flex flex-nowrap ms-2 align-items-center cursor-pointer btn o-doc-modal-checkbox" t-on-click="() =&gt; this.onFilterClick(filter)">
                    <input class="me-2" type="checkbox" t-att-id="filter" t-att-checked="state.activeFilters[filter]"/>
                    <label class="text-truncate" t-att-for="filter" t-out="filter" t-on-click.prevent=""/>
                </div>
                <div class="text-muted ms-2 me-2">
                    <t t-out="this.state.resultCount"/>
                    results
                </div>
            </div>

            <div class="d-flex flex-nowrap flex-column w-100 overflow-auto flex-grow" t-ref="scrollRef" t-on-scroll="(ev) =&gt; this.onScroll(ev.target)">
                <div class="overflow-hidden" t-att-style="\`min-height: \${this.state.scrollHeight}px\`">
                    <div t-att-style="\`transform: translateY(\${this.state.scrollOffsetY}px)\`">
                        <button t-foreach="state.results" t-as="result" t-key="result_index + result.type + '/' + result.label + '/' + result.path" class="btn mb-2 text-start w-100 d-flex flex-nowrap flex-row o-doc-modal-checkbox justify-content-between" t-on-click="() =&gt; this.onSelect(result)" t-att-style="\`min-height: \${itemHeight}px; max-height: \${itemHeight}px; margin-bottom: \${itemMargin}px\`">
                            <div class="h-100 flex-grow-1 me-2">
                                <h5 t-out="result.label" class="text-truncate mb-0"/>
                                <div class="text-muted text-truncate" t-out="result.path"/>
                            </div>
                            <span class="text-muted h-100 align-self-center" t-out="result.type"/>
                        </button>
                    </div>
                </div>
            </div>
        </div>
    </div>
</t>

`);
registerTemplate("web.DocModel", `/api_doc/static/src/components/doc_model.xml`, `<t t-name="web.DocModel" xml:space="preserve">
    <div t-if="!state.error" class="o-doc-model position-relative d-flex flex-nowrap flex-fill flex-column p-3">
        <h2 class="w-100 mb-2 mt-2" t-out="this.state.model?.name ?? ''"/>
        <DocTable data="state.modelData"/>

        <h3 class="mt-3 mb-2" id="fields">Fields</h3>
        <DocLoadingIndicator isLoaded="this.state.model and this.state.model.fields != null and this.state.fields.data" class="'o-fade-in'">
            <DocTable data="this.state.fields.data" activeIndex="this.state.fields.activeIndex"/>
        </DocLoadingIndicator>

        <h3 class="mt-3 mb-2" id="methods">Methods</h3>
        <DocLoadingIndicator isLoaded="this.state.methods and this.state.methods.length &gt; 0" class="'o-fade-in position-relative'">
            <DocMethod t-foreach="state.methods" t-as="method" t-key="method.model + '/' + method.name" t-if="isModuleActive(method.module)" method="method" class="modelStore.activeMethod === method.name ? 'o-doc-active' : ''"/>
        </DocLoadingIndicator>
        <div style="min-height: 30vh"/>
    </div>

    <aside t-if="!ui.isSmall and !state.error" class="o-doc-model-aside overflow-auto position-sticky d-block flex-fill bg-default pt-2 pb-2 ps-3 pe-3 border-start">
        <div class="d-flex flex-nowrap w-100 cursor-pointer text-capitalize align-items-center" t-on-click="() =&gt; this.state.showModulesFilter = !this.state.showModulesFilter" role="button">
            <div class="icon-btn ps-1" role="button" t-att-class="{ o_collapsed: !state.showModulesFilter}">
                <i class="fa fa-angle-right" aria-hidden="true"/>
            </div>
            <h3 class="ms-2">Modules</h3>
        </div>
        <t t-if="this.state.showModulesFilter">
            <span>
                <a class="me-1" href="#" t-on-click="() =&gt; this.toggleAllModules(true)">
                    Select all
                </a>
                <a href="#" t-on-click="() =&gt; this.toggleAllModules(false)">
                    Deselect all
                </a>
            </span>
            <div t-foreach="state.modules" t-as="module" t-key="module" class="d-flex flex-nowrap align-items-center mb-2 cursor-pointer btn o-doc-module-checks" t-on-click="() =&gt; this.setActiveModules([module], !this.state.activeModules[module])">
                <input class="me-1" type="checkbox" t-att-id="module" t-att-checked="state.activeModules[module]"/>
                <label class="text-truncate" t-att-for="module" t-out="module" t-on-click.prevent=""/>
            </div>
        </t>

        <h3 class="mt-2">On This Page</h3>
        <a t-foreach="state.methods" t-as="method" t-key="method.model + '/' + method.name" t-out="method.name" t-if="isModuleActive(method.module)" t-att-href="'#' + method.name" class="d-block w-100 text-truncate">
        </a>
    </aside>

    <div t-if="state.error and !modelStore.activeModel" class="d-flex flex-nowrap align-items-center justify-content-center w-100 h-100">
        <DocErrorDialog name="modelStore.error.name" status="modelStore.error.status" traceback="modelStore.error.traceback"/>
    </div>
</t>

`);
registerTemplate("web.DocRequest", `/api_doc/static/src/components/doc_request.xml`, `<t t-name="web.DocRequest" xml:space="preserve">
    <div class="o_doc_request h-100">
        <div class="d-flex flex-nowrap justify-content-between align-items-center mb-1">
            <h4>Request</h4>
            <div class="d-flex flex-nowrap">
                <select class="me-1" t-on-change="event =&gt; this.selectLanguage(event.target.value)">
                    <option t-foreach="LANGUAGES" t-as="lang" t-key="lang" t-att-selected="state.exampleLanguage === lang" t-att-value="lang" t-out="lang"/>
                </select>
                <button class="btn primary d-flex flex-nowrap align-items-center" t-on-click="execute" t-att-disabled="state.exampleLanguage !== 'json'">
                    <span>Run</span>
                    <i class="fa fa-play ms-2" aria-hidden="true"/>
                </button>
            </div>
        </div>

        <CodeEditor mode="LANGUAGES[state.exampleLanguage]" value="state.exampleLanguage === 'json' ? state.requestCode : state.exampleCode" readonly="state.exampleLanguage !== 'json'" onChange="value =&gt; this.state.requestCode = value" maxLines="maxLines" theme="'monokai'" showLineNumbers="false"/>

        <div class="mt-2 d-flex flex-nowrap align-items-center mb-1">
            <h4>Response</h4>
            <span t-if="hasResponse and !state.response.error" class="badge success ms-1 mb-1">Success</span>
            <span t-if="hasResponse and state.response.error" class="badge error ms-1 mb-1">Failed</span>
        </div>

        <t t-if="hasResponse">
            <CodeEditor t-if="!state.response.error" mode="'json'" value="state.response.body" readonly="true" maxLines="maxLines" theme="'monokai'" showLineNumbers="false"/>
            <div t-else="" class="alert error mt-1 d-flex flex-nowrap flex-column">
                <h5 class="mb-2 d-flex flex-nowrap align-items-center">
                    <i class="pe-1 fa fa-exclamation-triangle" aria-hidden="true"/>
                    <span>Error <t t-out="state.response.status"/> while executing request</span>
                </h5>
                <div t-if="state.showTraceback">
                    <button class="btn bg-100 position-absolute top-0 end-0 p-1" t-ref="copyButton" t-on-click="onClickClipboard">
                        <span class="fa fa-clipboard"/>
                    </button>
                    <span t-out="responseText.title"/>
                    <pre class="p-2 mt-2" style="max-height: 500px" t-out="responseText.traceback"/>
                </div>
                <button class="btn btn-sm mt-2 align-self-center" t-on-click="toggleTraceback" t-out="state.showTraceback ? 'Hide Details' : 'Show Technical Details'"/>
            </div>
        </t>
        <p t-else="" class="text-muted">Run to get a response</p>
    </div>
</t>

`);
registerTemplate("web.DocRequest.CodeEditor", `/api_doc/static/src/components/doc_request.xml`, `<t t-name="web.DocRequest.CodeEditor" xml:space="preserve">
    <div class="o-doc-code-editor position-relative p-2 rounded w-100">
        <t t-call="web.CodeEditor"/>
        <button class="position-absolute p-1 top-0 end-0 d-flex align-items-center cursor-pointer" t-on-click="copyToClipboard" type="button">
            <i t-if="!state.copied" class="fa fa-clipboard fs-6 text-light"/>
            <span t-else="" class="fs-6 text-light">Copied!</span>
        </button>
    </div>
</t>

`);
registerTemplate("web.DocSidebar", `/api_doc/static/src/components/doc_sidebar.xml`, `<t t-name="web.DocSidebar" xml:space="preserve">
    <div class="o-doc-sidebar pt-3 ps-3 position-sticky bg-1 border-end d-flex flex-nowrap flex-column">
        <div class="pe-4 pb-4">
            <input t-on-input="onSearchInput" class="w-100" placeholder="Search for models..."/>
        </div>
        <div class="o-doc-sidebar-content h-100 flex-fill d-flex flex-nowrap flex-column gap-1" t-ref="containerRef">
            <t t-foreach="filteredAddons" t-as="addon" t-key="addon.name">
                <div class="position-sticky o-doc-sidebar-header top-0 d-flex flex-nowrap w-100 cursor-pointer text-capitalize user-select-none" t-on-click="(ev) =&gt; this.toggleAddon(ev, addon.name)" role="button">
                    <div class="icon-btn ps-2 pt-2" role="button" t-att-class="{ o_collapsed: isCollapsed(addon.name)}">
                        <i class="fa fa-angle-right" aria-hidden="true"/>
                    </div>
                    <h4 class="ms-2" t-out="addon.name"/>
                </div>

                <div t-if="!isCollapsed(addon.name)" class="ms-2 ps-2 border-start">
                    <t t-foreach="addon.models" t-as="model" t-key="model.model">
                        <a class="btn d-block bg-none text-start" href="#" t-on-click="() =&gt; this.modelStore.setActiveModel({ model })" t-att-class="{ o_active: isActiveItem(model) }" role="button">
                            <div t-out="model.name"/>
                            <small class="d-block" t-out="model.model"/>
                        </a>
                    </t>
                </div>
            </t>
        </div>
    </div>
</t>

`);
registerTemplate("web.DocTable", `/api_doc/static/src/components/doc_table.xml`, `<t t-name="web.DocTable" xml:space="preserve">
    <div class="overflow-auto w-100 p-1">
        <table class="o-doc-table rounded bg-1 w-100">
            <tr t-if="props.data.headers" class="bg-1">
                <th t-foreach="props.data.headers" t-as="header" t-key="header_index" t-on-click="() =&gt; this.onRowHeaderClick(header_index)" class="position-relative text-nowrap text-start cursor-pointer user-select-none pt-1 pb-1 ps-2" t-attf-style="width: {{ 100 / props.data.headers.length }}%">
                    <span class="me-2" t-out="header"/>
                    <i t-att-class="getSortIcon(header_index)" aria-hidden="true"/>
                </th>
            </tr>

            <tr t-foreach="items" t-as="rows" t-key="rows_index" class="bg-1" t-att-class="{ 'o-doc-active': rows_index === props.activeIndex }" t-att-id="getId(rows)">
                <td t-foreach="rows" t-as="row" t-key="row_index" class="text-start">
                    <i t-if="row.subData" class="fa fa-bars o-doc-sub-table-btn d-inline me-1 cursor-pointer" aria-hidden="true" t-on-click="(ev) =&gt; this.showSubTable(ev, row.subData)"/>

                    <t t-if="row and row.type == 'tooltip' and row.value">
                        <i class="fa fa-question-circle p-1 " aria-hidden="true" t-if="row.value" t-on-mouseenter="(ev) =&gt; this.showDynamicTooltip(ev, row.value)" t-on-mouseleave="(ev) =&gt; this.scheduleHide(ev)"/>
                    </t>
                    <t t-else="" t-tag="getTag(row)" t-att-class="getClass(row)" t-out="getValue(row)"/>

                    <a t-if="row.relation" class="cursor-pointer text-muted ms-1" href="#" t-on-click="() =&gt; this.goToModel(row.relation)">
                        <t t-out="row.relation"/>
                        <i class="fa fa-external-link ps-1 d-inline" aria-hidden="true"/>
                    </a>
                </td>
            </tr>

            <tr t-if="items.length === 0 and props.data.headers" class="bg-1">
                <td t-foreach="props.data.headers" t-as="row" t-key="row_index" t-attf-style="width: {{ 100 / props.data.headers.length }}%" class="text-start text-muted">
                    <t t-if="row_index === 0">
                        No Data
                    </t>
                </td>
            </tr>
        </table>
    </div>

    <div t-if="state.subTable" class="o-doc-sub-table overflow-auto position-fixed bg-1 p-1 shadow border z-index-1 rounded" t-att-style="state.subTableStyle" t-ref="subTableRef">
        <DocTable data="state.subTable"/>
    </div>
    <div class="o-doc-dynamic-tooltip p-3 border overflow-auto" t-att-style="state.tooltipStyle" t-ref="tooltipRef" t-on-mouseenter="() =&gt; this.keepAlive()" t-on-mouseleave="(ev) =&gt; this.scheduleHide(ev)">
        <t t-out="state.tooltipContent"/>
    </div>
</t>

`);
registerTemplate("api_doc.DocClient", `/api_doc/static/src/doc_client.xml`, `<t t-name="api_doc.DocClient" xml:space="preserve">
    <header class="position-fixed bg-1 d-flex flex-nowrap gap-1 align-items-center justify-content-between w-100">
        <div class="d-flex flex-nowrap">
            <h2>Odoo Runtime Doc</h2>
        </div>
        <div>
            <input t-on-click="() =&gt; this.state.showSearchModal = true" placeholder="Find anything..."/>
        </div>
        <div class="d-flex flex-nowrap gap-1">
            <button class="btn" role="button" t-on-click="() =&gt; this.env.modelStore.showApiKeyModal = true">
                <i class="fa fa-key" aria-hidden="true"/>
            </button>
            <button class="btn" role="button" t-on-click="() =&gt; this.toggleTheme()">
                <i class="fa fa-moon-o" aria-hidden="true"/>
            </button>
        </div>
    </header>
    <main class="position-relative d-flex flex-nowrap">
        <DocSidebar t-if="!ui.isSmall"/>
        <t t-if="modelStore.models.length &gt; 0">
            <DocModel t-if="modelStore.activeModel"/>
        </t>
        <div t-elif="!modelStore.error" class="h-100 w-100 d-flex flex-nowrap align-items-center justify-content-center gap-1">
            <i class="fa fa-spinner o-doc-spinner" aria-hidden="true"/>
            <div>Loading Models</div>
        </div>

        <div t-if="modelStore.error" class="d-flex flex-column align-items-center justify-content-center w-100 h-100">
            <DocErrorDialog name="modelStore.error.name" status="modelStore.error.status" traceback="modelStore.error.traceback"/>
        </div>
    </main>
    <ApiKeyModal t-if="modelStore.showApiKeyModal"/>
    <SearchModal t-if="state.showSearchModal" close="() =&gt; this.state.showSearchModal = false"/>
</t>
`);
                    });
