!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e=e||self)["zh-tw"]={})}(this,function(e){"use strict";var n="undefined"!=typeof window&&window.flatpickr!==undefined?window.flatpickr:{l10ns:{}},t={weekdays:{shorthand:["週日","週一","週二","週三","週四","週五","週六"],longhand:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"]},months:{shorthand:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],longhand:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"]},rangeSeparator:" 至 ",weekAbbreviation:"週",scrollTitle:"滾動切換",toggleTitle:"點擊切換 12/24 小時時制"};n.l10ns.zh_tw=t;var o=n.l10ns;e.MandarinTraditional=t,e["default"]=o,Object.defineProperty(e,"__esModule",{value:!0})});!function(e){"use strict";ElementsKit_Helper.registerWidget("elementskit-image-accordion.default",(function(i){const t=i.find(".elementskit-single-image-accordion");let n;for(let i=0;iFor example:“I want to share my photography work. I’d like a minimal, modern look with a photo gallery and an About me page.”","chatbot.widget.onboarding.question.business.name":"Got it! And how would you like to call your online store? This is the name visitors will see on your site.","chatbot.widget.onboarding.question.website.name":"Got it! What’s the name of your business or project? This is the name visitors will see on your site.","chatbot.widget.onboarding.option.portfolio":"Portfolio","chatbot.widget.onboarding.option.business":"Business & services","chatbot.widget.onboarding.option.blog":"Blog","chatbot.widget.onboarding.option.online.store":"Online store","chatbot.widget.onboarding.option.link.in.bio":"Landing page","chatbot.widget.onboarding.confirm.business.name":'I confirm that "{name}" is my site name',"chatbot.widget.suggestions":"Suggestions","chatbot.widget.ticketStatus.inProgress":"Ticket {ticketNumber} is currently in progress, you will be notified on this banner of any updates. {issueType}","chatbot.widget.ticketStatus.waitingCustomer":"Ticket {ticketNumber} is currently waiting for your response. Click below to provide more details. {issueType}","chatbot.widget.ticketStatus.closed":"Ticket {ticketNumber} has been closed. If the issue persists, please reach out to us again to review it. {issueType}","chatbot.widget.ticketStatus.waitingCustomerPrompt":"I have a waiting ticket #{ticketNumber} for {issueType} and would like to add details","chatbot.widget.ticketStatus.provideDetails":"Provide details","chatbot.widget.onboarding.startScreen.title":"Hi, I’m Kodee! 👋","chatbot.widget.onboarding.startScreen.subTitle":"I’ll help you get your site up and running. Who is this website for?","chatbot.widget.onboarding.secondaryStartScreen.title":"Got it! Let's get started.","chatbot.widget.onboarding.secondaryStartScreen.subTitle":"Do you want to create or migrate a site?","chatbot.widget.onboarding.surveyTitles.myself":"Myself or my business","chatbot.widget.onboarding.surveyTitles.others":"Someone else","chatbot.widget.onboarding.surveyTitles.create":"Create a new site","chatbot.widget.onboarding.surveyTitles.migrate":"Migrate an existing site","chatbot.widget.onboarding.surveyTitles.professional":"I hired someone to help me with my site","chatbot.widget.onboarding.startScreenCreateOrMigrate.title":"Hi, I’m Kodee! 👋","chatbot.widget.onboarding.startScreenCreateOrMigrate.subTitle":"I’ll help you get your site up and running. Where would you like to start?","chatbot.widget.onboarding.confirm.business.name.short":"I confirm that’s the correct name","chatbot.widget.onboarding.clarify.business.name":"Just to double-check – is '{name}' the name you'd like to use? Just confirm below if that's right. If I got it wrong, go ahead and share the correct one – I'll make sure to update it!","chatbot.widget.try.now":"Try now","chatbot.widget.main.closedConversation":"Closed","chatbot.widget.main.you":"You","chatbot.widget.you.are.in.queue":"You are in queue","chatbot.widget.reconnecting.failedToConnect":"Failed to connect. Please","chatbot.widget.reconnecting.refreshThePage":"refresh the page.","chatbot.widget.reconnecting.reconnecting":"Reconnecting","chatbot.widget.reconnecting.connected":"Connected","chatbot.widget.main.go.back":"Go back","chatbot.widget.voice.record.title":"Listening...","chatbot.widget.voice.record.send":"Send","chatbot.widget.voice.record.cancel":"Cancel","chatbot.widget.voice.stop.playback":"Stop playback","chatbot.widget.voice.record.permission.denied":"Microphone access is required. Please allow microphone permissions in your browser settings.","chatbot.widget.voice.voice.message.sent":"Voice message sent","chatbot.widget.voice.start.playback":"Start playback","chatbot.widget.feedback.howWouldYouRate":"How would you rate your conversation?","chatbot.widget.feedback.giveFeedback":"Give feedback","chatbot.widget.survey.yes":"Yes","chatbot.widget.survey.no":"No","chatbot.widget.survey.thankYou":"Thank you for your input","chatbot.widget.voice.loading":"Loading voice response","chatbot.widget.systemMessages.previous.message.being.processed":"Your previous message is still being processed. Please wait before sending a new one.","chatbot.widget.a11y.loading":"Kodee is generating a response","chatbot.widget.a11y.responded":"{name} says","chatbot.widget.a11y.navigationTabs":"Chat navigation","chatbot.widget.a11y.chatMessages":"Chat messages","chatbot.widget.a11y.widget.title":"Kodee AI Assistant","chatbot.widget.a11y.input.label":"Send message to AI","chatbot.widget.send.voice":"Send voice message","chatbot.widget.a11y.history.unread":"Unread","chatbot.widget.a11y.history.list":"Previous conversations","chatbot.widget.feedback.comment.label":"Comments","chatbot.widget.about.your.goals.input.placeholder":"e.g. I want to attract more customers to my bike store","chatbot.widget.suggestions.salesN8nChoosePlan.title":"Help me choose a plan for n8n","chatbot.widget.suggestions.salesN8nChoosePlan.prompt":"Hi! I'm planning to run n8n workflows and I'm not sure which plan fits. Can you recommend a plan based on how I'll use n8n?","chatbot.widget.suggestions.salesN8nInstallOnHostinger.title":"How do I install n8n on Hostinger?","chatbot.widget.suggestions.salesN8nInstallOnHostinger.prompt":"Hi! I want to install n8n on Hostinger. Can you guide me through the easiest setup step by step?","chatbot.widget.suggestions.salesN8nMonthlyCost.title":"How much will n8n cost monthly?","chatbot.widget.suggestions.salesN8nMonthlyCost.prompt":"Hi! What's the total monthly cost to run self-hosted n8n on Hostinger (hosting + any recommended add-ons), and what's the best-value option?","chatbot.widget.suggestions.salesN8nWorkflowVolume.title":"Which n8n plan should I choose to handle my workflow volume?","chatbot.widget.suggestions.salesN8nWorkflowVolume.prompt":"Hi! I plan to run multiple workflows and integrations. Ask me questions to help decide what resources (RAM/CPU/storage) I should choose so n8n stays reliable?","chatbot.widget.suggestions.salesOpenclawIsRightForMe.title":"Is OpenClaw right for what I want to build?","chatbot.widget.suggestions.salesOpenclawIsRightForMe.prompt":"Hi! I'm looking at OpenClaw, but I'm not sure if it fits my use case. I want to use AI across messaging apps (like WhatsApp/Telegram/Slack/Discord). Can you ask a few questions and tell me if OpenClaw is the right choice—and what I should buy to get started on Hostinger?","chatbot.widget.suggestions.salesOpenclawVpsPlan.title":"Which VPS plan do I need for OpenClaw?","chatbot.widget.suggestions.salesOpenclawVpsPlan.prompt":"Hi! I want to deploy OpenClaw on Hostinger. What VPS plan/specs (CPU/RAM/storage) do you recommend based on how many channels and users I'll have, and whether I'll use voice/browser control?","chatbot.widget.suggestions.salesOpenclawAiCredits.title":"How do AI credits/tokens work on Hostinger?","chatbot.widget.suggestions.salesOpenclawAiCredits.prompt":"Hi! I saw that I can buy AI credits/tokens for OpenClaw. Can you explain how that works (nexos.ai access, top-ups, usage), and what I should choose to start with?","chatbot.widget.suggestions.salesOpenclawSecurity.title":"Is self-hosted OpenClaw secure and private?","chatbot.widget.suggestions.salesOpenclawSecurity.prompt":"Hi! Privacy matters to me. If I run OpenClaw on a Hostinger VPS, where do my chat logs and data live, how do I keep them under my control, and what security best practices should I enable before going live?","chatbot.widget.suggestions.salesHorizonsIsRight.title":"Is Horizons right for my idea?","chatbot.widget.suggestions.salesHorizonsIsRight.prompt":"Hi! I'm looking at Horizons and I have an idea for a website or web app. Can you tell me if Horizons is a good fit and what plan I should choose?","chatbot.widget.suggestions.salesHorizonsVsWebsiteBuilder.title":"Horizons vs Website Builder","chatbot.widget.suggestions.salesHorizonsVsWebsiteBuilder.prompt":"Hi! I'm deciding between Horizons and Website Builder. Can you explain the difference and recommend which one I should buy for my project?","chatbot.widget.suggestions.salesHorizonsChoosePlan.title":"Help me choose a Horizons plan","chatbot.widget.suggestions.salesHorizonsChoosePlan.prompt":"Hi! I want to try Horizons but I'm not sure which plan to choose. Can you recommend the best plan for a first-time project?","chatbot.widget.suggestions.salesHorizonsLoginsPayments.title":"Can I build features like logins/payments?","chatbot.widget.suggestions.salesHorizonsLoginsPayments.prompt":"Hi! My project needs features like user accounts and/or payments. Can Horizons handle that, and what would the setup look like?","chatbot.widget.suggestions.salesHorizonsPublish.title":"How do I publish what I build?","chatbot.widget.suggestions.salesHorizonsPublish.prompt":"Hi! If I build something with Horizons, how do I publish it online and connect a domain? What do I need to purchase to go live?","chatbot.widget.suggestions.salesHorizonsCost.title":"What's the real cost to get started?","chatbot.widget.suggestions.salesHorizonsCost.prompt":"Hi! Can you explain the total cost to get started with Horizons (what's included in the plan, renewals, and anything else I might need) and recommend the best-value option?","chatbot.widget.suggestions.salesWebHostingChoosePlan.title":"Which hosting plan should I buy?","chatbot.widget.suggestions.salesWebHostingChoosePlan.prompt":"Hi! I want to create a website (business/blog/portfolio). Can you recommend the best web hosting plan for me and explain why?","chatbot.widget.suggestions.salesWebHostingWhatsIncluded.title":"What's included in web hosting?","chatbot.widget.suggestions.salesWebHostingWhatsIncluded.prompt":"Hi! What exactly is included with your web hosting plans (SSL, email, backups, domain options, etc.) and which plan is the best value?","chatbot.widget.suggestions.salesWebHostingOnlineStore.title":"Is web hosting enough for an online store?","chatbot.widget.suggestions.salesWebHostingOnlineStore.prompt":"Hi! I want to sell online. Is regular web hosting enough, and which plan should I choose to start?","chatbot.widget.suggestions.salesWebHostingTransfer.title":"I have a site elsewhere — can I transfer it?","chatbot.widget.suggestions.salesWebHostingTransfer.prompt":"Hi! I already have a website with another provider. Can you tell me how moving to Hostinger works and which hosting plan I should buy?","chatbot.widget.suggestions.salesBusinessEmailProfessional.title":"I want a professional email address","chatbot.widget.suggestions.salesBusinessEmailProfessional.prompt":"Hi! I want an email like name{'@'}mydomain.com. Which Business Email plan should I choose and how do I set it up?","chatbot.widget.suggestions.salesBusinessEmailUseDomain.title":"Can I use my domain for email?","chatbot.widget.suggestions.salesBusinessEmailUseDomain.prompt":"Hi! I already have a domain name. Can I connect it to Business Email, and what steps do I need to take?","chatbot.widget.suggestions.salesBusinessEmailForTeam.title":"Email for my team","chatbot.widget.suggestions.salesBusinessEmailForTeam.prompt":"Hi! I need email accounts for a small team. How do I choose the right plan and how many mailboxes do I need?","chatbot.widget.suggestions.salesBusinessEmailGmailOutlook.title":"Can I use your email in Gmail or Outlook?","chatbot.widget.suggestions.salesBusinessEmailGmailOutlook.prompt":"Hi! If I buy Business Email, can I use it in Gmail or Outlook apps? How would I log in and set it up?","chatbot.widget.suggestions.salesBusinessEmailMigrate.title":"Can I move my existing email?","chatbot.widget.suggestions.salesBusinessEmailMigrate.prompt":"Hi! I already have email with another provider. Can you explain how migration works and which plan I should buy?","chatbot.widget.suggestions.salesBusinessEmailWhatsIncluded.title":"What's included in Business Email?","chatbot.widget.suggestions.salesBusinessEmailWhatsIncluded.prompt":"Hi! What features are included in your Business Email plans (storage, security, spam protection, etc.) and which plan is best value?","chatbot.widget.suggestions.salesVpsDoINeed.title":"Do I need VPS hosting?","chatbot.widget.suggestions.salesVpsDoINeed.prompt":"Hi! I'm looking at VPS hosting but I'm not sure if it's the right choice for me. Can you ask a few questions about my project and recommend the best option?","chatbot.widget.suggestions.salesVpsChoosePlan.title":"Help me choose a VPS plan","chatbot.widget.suggestions.salesVpsChoosePlan.prompt":"Hi! I want to buy a VPS but I don't know which plan to pick. Can you recommend the right VPS plan based on what I'm building and my budget?","chatbot.widget.suggestions.salesVpsVsWebHosting.title":"VPS vs Web Hosting","chatbot.widget.suggestions.salesVpsVsWebHosting.prompt":"Hi! Should I choose VPS hosting or regular web hosting for my website/project? Please compare them and tell me what you recommend for my situation.","chatbot.widget.suggestions.salesVpsTooTechnical.title":"Is VPS too technical for me?","chatbot.widget.suggestions.salesVpsTooTechnical.prompt":"Hi! I'm interested in VPS. How does management work, and what help or guidance do you provide?","chatbot.widget.suggestions.salesWordpressChoosePlan.title":"Which WordPress plan should I buy?","chatbot.widget.suggestions.salesWordpressChoosePlan.prompt":"Hi! I want to build a WordPress website. Can you recommend the right WordPress hosting plan after figuring out my needs and budget?","chatbot.widget.suggestions.salesWordpressVsWebHosting.title":"WordPress hosting vs web hosting","chatbot.widget.suggestions.salesWordpressVsWebHosting.prompt":"Hi! What's the difference between WordPress hosting and regular web hosting, and which one should I choose?","chatbot.widget.suggestions.salesWordpressSetup.title":"Can you help me set up WordPress?","chatbot.widget.suggestions.salesWordpressSetup.prompt":"Hi! I'm new to WordPress. Can you guide me on how to get started and tell me which plan I should buy?","chatbot.widget.suggestions.salesWordpressSpeed.title":"Will my WordPress site be fast?","chatbot.widget.suggestions.salesWordpressSpeed.prompt":"Hi! Speed matters to me. Which WordPress hosting plan should I choose to keep my site fast, and what features help with performance?","chatbot.widget.suggestions.salesWordpressTransfer.title":"Can I transfer my WordPress site to Hostinger?","chatbot.widget.suggestions.salesWordpressTransfer.prompt":"Hi! I already have a WordPress site with another provider. Can you explain the migration options and recommend the best plan for moving?","chatbot.widget.suggestions.salesWebsiteBuilderOrWordpress.title":"Should I choose Builder or WordPress?","chatbot.widget.suggestions.salesWebsiteBuilderOrWordpress.prompt":"Hi! I want to build a website but I'm not sure if I should use Website Builder or WordPress. Can you help me choose based on what I'm trying to make?","chatbot.widget.suggestions.salesWebsiteBuilderChoosePlan.title":"Help me pick a Website Builder plan","chatbot.widget.suggestions.salesWebsiteBuilderChoosePlan.prompt":"Hi! I want to use your Website Builder. Can you recommend the right plan for my site and explain the differences between the options?","chatbot.widget.suggestions.salesWebsiteBuilderOnlineStore.title":"Can I build an online store with Website Builder?","chatbot.widget.suggestions.salesWebsiteBuilderOnlineStore.prompt":"Hi! I want to sell products or services online. Can I do that with your Website Builder, and which plan do I need?","chatbot.widget.suggestions.salesWebsiteBuilderWhatsIncluded.title":"What do I get with the plan?","chatbot.widget.suggestions.salesWebsiteBuilderWhatsIncluded.prompt":"Hi! Before I buy, can you explain what's included in the Website Builder plan (features, limits, and anything extra I might need)?","chatbot.widget.suggestions.salesWebsiteBuilderProfessional.title":"I want a site that looks professional","chatbot.widget.suggestions.salesWebsiteBuilderProfessional.prompt":"Hi! I want a professional-looking website but don't know what layout or sections I need. Can you guide me on what to include and recommend the best plan to start?","chatbot.widget.suggestion.category.salesN8n":"n8n","chatbot.widget.suggestion.category.salesOpenclaw":"OpenClaw","chatbot.widget.suggestion.category.salesHorizons":"Horizons","chatbot.widget.suggestion.category.salesWebHosting":"Web Hosting","chatbot.widget.suggestion.category.salesBusinessEmail":"Business Email","chatbot.widget.suggestion.category.salesVpsHosting":"VPS Hosting","chatbot.widget.suggestion.category.salesWordpressHosting":"WordPress Hosting","chatbot.widget.suggestion.category.salesWebsiteBuilder":"Website Builder","chatbot.widget.requestHumanAssistance":"Request human assistance","chatbot.widget.voice.record.input.placeholder":"Recording your message...","chatbot.widget.agentRedirect.badge":"AI Agent","chatbot.widget.agentRedirect.tryButton":"Try {agentName}","chatbot.widget.agentRedirect.scout.description":"Scout can run a comprehensive SEO audit of your website, analyze your keyword rankings, identify technical issues, and create an actionable optimization plan — going much deeper than I can in a chat.","chatbot.widget.agentRedirect.north.description":"North can analyze your business model, evaluate market opportunities, construct detailed financial forecasts, and develop a strategic growth roadmap — going much deeper than I can in a chat.","chatbot.widget.agentRedirect.quill.description":"Quill can draft compelling blog posts, develop engaging brand narratives, write long-form articles, and refine your overall content strategy — going much deeper than I can in a chat.","chatbot.widget.agentRedirect.buzz.description":"Buzz can design multi-channel marketing campaigns, allocate your advertising budget, map out promotional calendars, and define your target audience segments — going much deeper than I can in a chat.","chatbot.widget.agentRedirect.shield.description":"Shield can review your business contracts, highlight potential compliance risks, outline standard legal frameworks, and help draft basic terms of service — going much deeper than I can in a chat.","chatbot.widget.agentRedirect.ally.description":"Ally can craft empathetic customer service responses, develop comprehensive FAQ documentation, design email onboarding sequences, and standardize your support tone — going much deeper than I can in a chat.","chatbot.widget.agentRedirect.arrow.description":"Arrow can build targeted prospect lists, write personalized cold email sequences, formulate objection-handling scripts, and design your sales funnel — going much deeper than I can in a chat.","chatbot.widget.startScreen.titleNoName":"Hello 👋","chatbot.widget.a11y.suggestions.list":"Suggested replies","chatbot.widget.a11y.suggestions.categories":"Suggestion categories","chatbot.widget.a11y.suggestions.listWithCategory":"Suggested messages for {category}","chatbot.widget.costLimit.banner.title":"You’ve reached your weekly Kodee limit.","chatbot.widget.costLimit.banner.description":"You can still chat with Kodee using a lighter version until {resetDate}","chatbot.widget.costLimit.banner.cta":"Upgrade","chatbot.widget.costLimit.modal.title":"Higher limits are coming","chatbot.widget.costLimit.modal.description":"We’re working on upgrade options to increase your weekly Kodee limit. You’ll be able to get higher limits and improved performance soon.","chatbot.widget.costLimit.modal.cancel":"Cancel","chatbot.widget.costLimit.modal.notifyMe":"Notify me","chatbot.widget.agentResponse.viewWork":"View {agentName}'s work","chatbot.widget.agentsTopUp.title":"You've run out of Agent credits","chatbot.widget.agentsTopUp.description":"Top up your Agent credits or upgrade your plan to keep going.","chatbot.widget.agentsTopUp.cta":"Top up credits","chatbot.widget.agentInProgress.status":"{agentName} is working on it…","chatbot.widget.banner.message.generic":"Some Hostinger services may be experiencing issues. Our team is working to restore normal functionality.","chatbot.widget.v2.header.title":"Kodee","chatbot.widget.v2.header.newChat":"Start new chat","chatbot.widget.v2.header.close":"Close chat","chatbot.widget.v2.modal.close":"Close","chatbot.widget.v2.welcome.heading":"What are you looking to create?","chatbot.widget.v2.welcome.intro":"I'm {name} — I'll match you with the right Hostinger plan in under 2 minutes.","chatbot.widget.v2.actions.orExplore":"or explore","chatbot.widget.v2.actions.buildWebsite.title":"Build my website","chatbot.widget.v2.actions.buildWebsite.subtitle":"Most popular takes 2 min","chatbot.widget.v2.actions.webHosting.title":"Get web hosting","chatbot.widget.v2.actions.webHosting.prompt":"Help me choose webhosting plan that is right for me","chatbot.widget.v2.actions.findDomain.title":"Find a domain","chatbot.widget.v2.actions.findDomain.prompt":"Help me find a domain","chatbot.widget.v2.actions.businessEmail.title":"Business email","chatbot.widget.v2.actions.businessEmail.prompt":"Help me purchase an email plan for my business","chatbot.widget.v2.input.placeholder":"Message Kodee…","chatbot.widget.v2.input.sendButton":"Send message","chatbot.widget.v2.feedback.goodResponse":"Good response","chatbot.widget.v2.feedback.badResponse":"Bad response","chatbot.widget.v2.feedback.leaveComment":"Leave comment","chatbot.widget.v2.feedback.editComment":"Edit comment","chatbot.widget.v2.comment.placeholderPositive":"What worked well?","chatbot.widget.v2.comment.placeholderNegative":"What could be better?","chatbot.widget.v2.comment.cancel":"Cancel","chatbot.widget.v2.comment.send":"Send","chatbot.widget.v2.restart.title":"Start a new chat?","chatbot.widget.v2.restart.description":"This will clear your current conversation with Kodee, including anything you've shared. You can't undo this.","chatbot.widget.v2.restart.keepChatting":"Keep chatting","chatbot.widget.v2.restart.confirm":"Start new chat","chatbot.widget.v2.flow.intro":"What are we building today? Pick a category or describe your own.","chatbot.widget.v2.flow.charCounter":"{remaining} to go","chatbot.widget.v2.flow.category.onlineStore.title":"Online Store","chatbot.widget.v2.flow.category.onlineStore.subtitle":"Sell products online","chatbot.widget.v2.flow.category.onlineStore.promptLabel":"an Online Store","chatbot.widget.v2.flow.category.onlineStore.inputTitle":"Tell me about your store","chatbot.widget.v2.flow.category.onlineStore.inputSubtitle":"A few words about what you sell and the vibe you want.","chatbot.widget.v2.flow.category.onlineStore.inputPlaceholder":"e.g. 'Bloom Cafe — cozy coffee shop, warm earth tones, minimal.'","chatbot.widget.v2.flow.category.onlineStore.submitLabel":"Bring my store to life","chatbot.widget.v2.flow.category.portfolio.title":"Portfolio / Blog","chatbot.widget.v2.flow.category.portfolio.subtitle":"Showcase your work","chatbot.widget.v2.flow.category.portfolio.promptLabel":"a Portfolio / Blog","chatbot.widget.v2.flow.category.portfolio.inputTitle":"Tell me about your portfolio","chatbot.widget.v2.flow.category.portfolio.inputSubtitle":"What do you want to showcase and who is it for?","chatbot.widget.v2.flow.category.portfolio.inputPlaceholder":"e.g. 'Freelance photographer — moody editorial style, dark theme.'","chatbot.widget.v2.flow.category.portfolio.submitLabel":"Bring my vision to life","chatbot.widget.v2.flow.category.business.title":"Business Site","chatbot.widget.v2.flow.category.business.subtitle":"Establish your brand","chatbot.widget.v2.flow.category.business.promptLabel":"a Business Site","chatbot.widget.v2.flow.category.business.inputTitle":"Tell me about your business","chatbot.widget.v2.flow.category.business.inputSubtitle":"What you do, who you serve, and the feel you want.","chatbot.widget.v2.flow.category.business.inputPlaceholder":"e.g. 'Family-run plumbing service — trustworthy, local, simple.'","chatbot.widget.v2.flow.category.business.submitLabel":"Bring my brand to life","chatbot.widget.v2.flow.category.other.title":"Something Else","chatbot.widget.v2.flow.category.other.subtitle":"Tell us what you need","chatbot.widget.v2.flow.category.other.promptLabel":"something custom","chatbot.widget.v2.flow.category.other.inputTitle":"Tell me about your idea","chatbot.widget.v2.flow.category.other.inputSubtitle":"Describe what you have in mind and I will take it from there.","chatbot.widget.v2.flow.category.other.inputPlaceholder":"e.g. 'A booking page for my yoga classes with a calm, airy feel.'","chatbot.widget.v2.flow.category.other.submitLabel":"Bring my idea to life","chatbot.widget.v2.visual.plan.bestMatch":"Best match","chatbot.widget.v2.visual.plan.pricePerMonth":"/month","chatbot.widget.v2.visual.preview.alt":"Preview of your website","chatbot.widget.v2.visual.preview.accept":"Love it, continue","chatbot.widget.v2.visual.preview.acceptPrompt":"Man tai patinka, tęskime","chatbot.widget.outOfScopeDescriptionForm.descriptionLabel":"Add a description","chatbot.widget.outOfScopeDescriptionForm.descriptionPlaceholder":"e.g. I can't access my control panel after the password reset","chatbot.widget.outOfScopeDescriptionForm.submit":"Submit details","chatbot.widget.outOfScopeHandoffChoice.intro":"Form has been successfully submitted. Thank you for filling in the details.","chatbot.widget.outOfScopeHandoffChoice.outro":"Before we queue a specialist. I can resolve the issue and save you the wait.","chatbot.widget.outOfScopeHandoffChoice.goToHuman":"Go to human","chatbot.widget.outOfScopeHandoffChoice.continueWithKodee":"Continue with Kodee","chatbot.widget.outOfScopeHandoffChoice.handoffMessage":"I want to continue with a human","chatbot.widget.outOfScopeHandoffChoice.kodeeContinueReply":"Thank you for choosing to continue with me, how can I help you further?","chatbot.widget.outOfScopeDescriptionForm.minCharsHint":"Please add at least {count} characters ({current}/{count}).","chatbot.widget.code.block.copy":"Copy","chatbot.widget.code.block.copied":"Copied"};export{t as default}; /*! elementor-pro - v3.34.0 - 26-01-2026 */ "use strict"; (self["webpackChunkelementor_pro"] = self["webpackChunkelementor_pro"] || []).push([["mega-menu"],{ /***/ "../assets/dev/js/frontend/utils/anchor-link.js": /*!******************************************************!*\ !*** ../assets/dev/js/frontend/utils/anchor-link.js ***! \******************************************************/ /***/ ((__unused_webpack_module, exports) => { Object.defineProperty(exports, "__esModule", ({ value: true })); exports["default"] = void 0; class AnchorLinks { observer = null; constructor($anchorLinks, classes) { this.$anchorLinks = $anchorLinks; this.activeAnchorClass = classes.activeAnchorItem; this.anchorClass = classes.anchorItem; } getViewportHeight() { return window.innerHeight; } bindEvents() { this.onResize = this.onResize.bind(this); window.addEventListener('resize', this.onResize); } initialize() { this.viewPortHeight = this.getViewportHeight(); this.followMenuAnchors(); this.bindEvents(); } followMenuAnchors() { this.$anchorLinks.each((index, anchorLink) => { if (location.pathname === anchorLink.pathname && '' !== anchorLink.hash) { this.followMenuAnchor(jQuery(anchorLink)); } }); } followMenuAnchor($element) { const $targetElement = $element.hasClass(this.anchorClass) ? $element : $element.closest(`.${this.anchorClass}`); const anchorElement = this.getAnchorElement($element); if (!anchorElement) { return; } const options = this.getObserverOptions(anchorElement); this.observer = this.createObserver($targetElement, $element, options); this.observer.observe(anchorElement); } getAnchorElement($element) { const anchorSelector = $element[0].hash; try { // `decodeURIComponent` for UTF8 characters in the hash. const decodedSelector = decodeURIComponent(anchorSelector); return document.querySelector(decodedSelector); } catch (e) { return null; } } getObserverOptions(element) { return { root: null, rootMargin: this.calculateRootMargin(element) }; } calculateRootMargin(element) { const anchorHeight = element?.offsetHeight || 0; const isAnchorHeightLargerThanHalfViewport = anchorHeight > this.viewPortHeight / 2; const rootMarginBlockEnd = -1 * this.viewPortHeight / 2; const rootMarginBlockStart = isAnchorHeightLargerThanHalfViewport ? rootMarginBlockEnd : 0; return `${rootMarginBlockStart}px 0px ${rootMarginBlockEnd}px 0px`; } createObserver($targetElement, $element, options) { return new IntersectionObserver(entries => { entries.forEach(entry => { $targetElement.toggleClass(this.activeAnchorClass, entry.isIntersecting); $element.attr('aria-current', entry.isIntersecting ? 'location' : ''); }); }, options); } onResize() { this.viewPortHeight = this.getViewportHeight(); if (this.observer) { this.observer.disconnect(); } this.followMenuAnchors(); } } exports["default"] = AnchorLinks; /***/ }), /***/ "../assets/dev/js/frontend/utils/flex-horizontal-scroll.js": /*!*****************************************************************!*\ !*** ../assets/dev/js/frontend/utils/flex-horizontal-scroll.js ***! \*****************************************************************/ /***/ ((__unused_webpack_module, exports) => { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.changeScrollStatus = changeScrollStatus; exports.setHorizontalScrollAlignment = setHorizontalScrollAlignment; exports.setHorizontalTitleScrollValues = setHorizontalTitleScrollValues; function changeScrollStatus(element, event) { if ('mousedown' === event.type) { element.classList.add('e-scroll'); element.dataset.pageX = event.pageX; } else { element.classList.remove('e-scroll', 'e-scroll-active'); element.dataset.pageX = ''; } } // This function was written using this example https://codepen.io/thenutz/pen/VwYeYEE. function setHorizontalTitleScrollValues(element, horizontalScrollStatus, event) { const isActiveScroll = element.classList.contains('e-scroll'), isHorizontalScrollActive = 'enable' === horizontalScrollStatus, headingContentIsWiderThanWrapper = element.scrollWidth > element.clientWidth; if (!isActiveScroll || !isHorizontalScrollActive || !headingContentIsWiderThanWrapper) { return; } event.preventDefault(); const previousPositionX = parseFloat(element.dataset.pageX), mouseMoveX = event.pageX - previousPositionX, maximumScrollValue = 5, stepLimit = 20; let toScrollDistanceX = 0; if (stepLimit < mouseMoveX) { toScrollDistanceX = maximumScrollValue; } else if (stepLimit * -1 > mouseMoveX) { toScrollDistanceX = -1 * maximumScrollValue; } else { toScrollDistanceX = mouseMoveX; } element.scrollLeft = element.scrollLeft - toScrollDistanceX; element.classList.add('e-scroll-active'); } function setHorizontalScrollAlignment({ element, direction, justifyCSSVariable, horizontalScrollStatus }) { if (!element) { return; } if (isHorizontalScroll(element, horizontalScrollStatus)) { initialScrollPosition(element, direction, justifyCSSVariable); } else { element.style.setProperty(justifyCSSVariable, ''); } } function isHorizontalScroll(element, horizontalScrollStatus) { return element.clientWidth < getChildrenWidth(element.children) && 'enable' === horizontalScrollStatus; } function getChildrenWidth(children) { let totalWidth = 0; const parentContainer = children[0].parentNode, computedStyles = getComputedStyle(parentContainer), gap = parseFloat(computedStyles.gap) || 0; // Get the gap value or default to 0 if it's not specified for (let i = 0; i < children.length; i++) { totalWidth += children[i].offsetWidth + gap; } return totalWidth; } function initialScrollPosition(element, direction, justifyCSSVariable) { const isRTL = elementorFrontend.config.is_rtl; switch (direction) { case 'end': element.style.setProperty(justifyCSSVariable, 'start'); element.scrollLeft = isRTL ? -1 * getChildrenWidth(element.children) : getChildrenWidth(element.children); break; default: element.style.setProperty(justifyCSSVariable, 'start'); element.scrollLeft = 0; } } /***/ }), /***/ "../modules/mega-menu/assets/js/frontend/handlers/mega-menu.js": /*!*********************************************************************!*\ !*** ../modules/mega-menu/assets/js/frontend/handlers/mega-menu.js ***! \*********************************************************************/ /***/ ((__unused_webpack_module, exports, __webpack_require__) => { var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "../node_modules/@babel/runtime/helpers/interopRequireDefault.js"); Object.defineProperty(exports, "__esModule", ({ value: true })); exports["default"] = void 0; var _utils = __webpack_require__(/*! ../utils */ "../modules/mega-menu/assets/js/frontend/utils.js"); var _anchorLink = _interopRequireDefault(__webpack_require__(/*! ../../../../../../assets/dev/js/frontend/utils/anchor-link */ "../assets/dev/js/frontend/utils/anchor-link.js")); var _flexHorizontalScroll = __webpack_require__(/*! elementor-pro/frontend/utils/flex-horizontal-scroll */ "../assets/dev/js/frontend/utils/flex-horizontal-scroll.js"); class MegaMenu extends elementorModules.frontend.handlers.Base { constructor(...args) { super(...args); if (elementorFrontend.isEditMode()) { this.lifecycleChangeListener = null; } this.resizeListener = null; this.prevMouseY = null; this.isKeyboardNavigation = false; } getDefaultSettings() { return { selectors: { elementorWidgetWrapper: '.elementor-widget-n-menu', widgetContainer: '.e-n-menu', dropdownMenuToggle: '.e-n-menu-toggle', menuWrapper: '.e-n-menu-wrapper', headingContainer: '.e-n-menu-heading', menuItem: '.e-n-menu-item', tabTitle: '.e-n-menu-title', tabTitleText: '.e-n-menu-title-text', directTabTitle: ':scope > .elementor-widget-container > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-n-menu-item > .e-n-menu-title, :scope > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-n-menu-item > .e-n-menu-title', tabClickableTitle: '.e-n-menu-title.e-click', tabDropdown: '.e-n-menu-dropdown-icon', menuContent: '.e-n-menu-content', tabContent: '.e-n-menu-content > .e-con, .e-n-menu-heading > .e-con', directTabContent: ':scope > .elementor-widget-container > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-n-menu-item > .e-n-menu-content > .e-con, :scope > .elementor-widget-container > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-con, :scope > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-n-menu-item > .e-n-menu-content > .e-con, :scope > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-con', tabContentBeforeInterlacing: '> .elementor-widget-container > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-con, > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-con', newContainerAfterRepeaterAction: '> .elementor-widget-container > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-con, > .elementor-widget-container > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-n-menu-item > .e-n-menu-content > .e-con:nth-child(2), > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-con, > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-n-menu-item > .e-n-menu-content > .e-con:nth-child(2)', anchorLink: '.e-anchor a' }, classes: { active: 'e-active', anchorItem: 'e-anchor', activeAnchorItem: 'e-current' }, dataAttributes: { tabIndex: 'data-tab-index' }, ariaAttributes: { titleStateAttribute: 'aria-expanded', activeTitleSelector: '[aria-expanded="true"]' }, autoExpand: false, autoFocus: false, showTabFn: 'show', hideTabFn: 'hide', toggleSelf: false, hidePrevious: true, postUrl: 'post-url', internalUrl: 'internal-url' }; } getDefaultElements() { const selectors = this.getSettings('selectors'); return { $tabContents: this.findElement(selectors.tabContent), $widgetContainer: this.findElement(selectors.widgetContainer), $dropdownMenuToggle: this.findElement(selectors.dropdownMenuToggle), $menuWrapper: this.findElement(selectors.menuWrapper), $menuContent: this.findElement(selectors.menuContent), $headingContainer: this.findElement(selectors.headingContainer), $menuItems: this.findElement(selectors.menuItem), $tabTitles: this.findElement(selectors.tabTitle), $tabDropdowns: this.findElement(selectors.tabDropdown), $anchorLink: this.findElement(selectors.anchorLink), $tabContentsBeforeInterlacing: this.findElement(selectors.tabContentBeforeInterlacing) }; } getTabTitleFilterSelector(tabIndex) { return `[${this.getSettings('dataAttributes').tabIndex}="${tabIndex}"]`; } getTabIndex(tabTitleElement) { return tabTitleElement.getAttribute(this.getSettings('dataAttributes').tabIndex); } setKeyboardNavigation(event) { if ('Tab' === event.key) { this.isKeyboardNavigation = true; } } dropdownMenuHeightControllerConfig() { const selectors = this.getSettings('selectors'); return { elements: { $element: this.$element, $dropdownMenuContainer: this.$element.find(selectors.menuWrapper), $menuToggle: this.$element.find(selectors.dropdownMenuToggle) }, attributes: { menuToggleState: 'aria-expanded' }, settings: { dropdownMenuContainerMaxHeight: 'auto', menuHeightCssVarName: '--n-menu-dropdown-content-box-height' } }; } handleContentContainerPosition($contentContainer = null) { this.resetContentContainersPosition(); // If no container is passed as an argument, check if there is an active container. const activeTitleSelector = this.getSettings('ariaAttributes').activeTitleSelector, tabIndex = this.elements.$tabDropdowns.filter(activeTitleSelector).attr('data-tab-index'); $contentContainer = $contentContainer || this.elements.$tabContents.filter(this.getTabContentFilterSelector(tabIndex)); if (!$contentContainer.length) { return; } this.setContentContainerAbsolutePosition($contentContainer); } setContentContainerAbsolutePosition($contentContainer) { const elementSettings = this.getElementSettings(), isFitToContent = 'fit_to_content' === elementSettings.content_width; if ((0, _utils.isMenuInDropdownMode)(elementSettings)) { return; } if (isFitToContent) { const direction = elementorFrontend.config.is_rtl ? 'right' : 'left', menuItemContainerOffset = 0 < this.getMenuItemContainerAbsolutePosition($contentContainer) ? this.getMenuItemContainerAbsolutePosition($contentContainer) : 0; $contentContainer.css(direction, menuItemContainerOffset); } const headingsHeight = this.elements.$headingContainer[0].getBoundingClientRect().height; if (this.shouldPositionContentAbove($contentContainer, headingsHeight)) { const contentContainerBoundingBox = $contentContainer[0].getBoundingClientRect(); $contentContainer.css({ width: isFitToContent ? 'max-content' : '', 'max-width': contentContainerBoundingBox.width }); this.elements.$widgetContainer.addClass('content-above'); } } getMenuItemContainerAbsolutePosition($contentContainer) { const tabIndex = $contentContainer.data('tab-index'), $activeDropdown = this.elements.$tabDropdowns.filter(this.getTabTitleFilterSelector(tabIndex))[0], $titleElement = $activeDropdown.closest(this.getSettings('selectors').tabTitle), titleBoundingBox = $titleElement.getBoundingClientRect(), contentContainerWidth = $contentContainer[0].clientWidth; let menuItemContainerOffset = null; switch (this.getElementSettings('content_horizontal_position')) { case 'left': menuItemContainerOffset = this.getLeftDirectionContainerOffset(contentContainerWidth, titleBoundingBox); break; case 'right': menuItemContainerOffset = this.getRightDirectionContainerOffset(contentContainerWidth, titleBoundingBox); break; default: menuItemContainerOffset = this.getCenteredContainerOffset(contentContainerWidth, titleBoundingBox); } return menuItemContainerOffset; } getCenteredContainerOffset(contentContainerWidth, titleBoundingBox) { const menuItemContentContainerHalfWidth = contentContainerWidth / 2, bodyWidth = elementorFrontend.elements.$body[0].clientWidth; let titleMiddleOffset = this.adjustForScrollbarIfNeeded(titleBoundingBox.left + titleBoundingBox.width / 2); if (elementorFrontend.config.is_rtl) { titleMiddleOffset = bodyWidth - titleMiddleOffset; } let offset = titleMiddleOffset - menuItemContentContainerHalfWidth; if (titleMiddleOffset + menuItemContentContainerHalfWidth > bodyWidth) { offset = bodyWidth - contentContainerWidth; } else if (menuItemContentContainerHalfWidth > titleMiddleOffset) { offset = 0; } return offset; } getLeftDirectionContainerOffset(contentContainerWidth, titleBoundingBox) { return elementorFrontend.config.is_rtl ? this.getRtlLeftDirectionContainerOffset(contentContainerWidth, titleBoundingBox) : this.getLtrLeftDirectionContainerOffset(contentContainerWidth, titleBoundingBox); } getRtlLeftDirectionContainerOffset(contentContainerWidth, titleBoundingBox) { const bodyWidth = elementorFrontend.elements.$body[0].clientWidth, titleLeftOffset = this.adjustForScrollbarIfNeeded(titleBoundingBox.left); let offset = bodyWidth - titleLeftOffset - contentContainerWidth; // If the content container doesn't fit in the viewport, align its right edge with the viewport's right edge. if (-offset + contentContainerWidth > bodyWidth) { offset = 0; } return offset; } getLtrLeftDirectionContainerOffset(contentContainerWidth, titleBoundingBox) { let offset = this.adjustForScrollbarIfNeeded(titleBoundingBox.left); offset = this.adjustStartOffsetToViewport(offset, contentContainerWidth); return offset; } getRightDirectionContainerOffset(contentContainerWidth, titleBoundingBox) { return elementorFrontend.config.is_rtl ? this.getRtlRightDirectionContainerOffset(contentContainerWidth, titleBoundingBox) : this.getLtrRightDirectionContainerOffset(contentContainerWidth, titleBoundingBox); } getRtlRightDirectionContainerOffset(contentContainerWidth, titleBoundingBox) { const bodyWidth = elementorFrontend.elements.$body[0].clientWidth; let offset = bodyWidth - this.adjustForScrollbarIfNeeded(titleBoundingBox.right); offset = this.adjustStartOffsetToViewport(offset, contentContainerWidth); return offset; } /** * If the content container doesn't fit in the viewport, align its right edge with the viewport's right edge. * * @param {number} offset * @param {number} contentContainerWidth */ adjustStartOffsetToViewport(offset, contentContainerWidth) { const bodyWidth = elementorFrontend.elements.$body[0].clientWidth; if (offset + contentContainerWidth > bodyWidth) { offset = bodyWidth - contentContainerWidth; } return offset; } getLtrRightDirectionContainerOffset(contentContainerWidth, titleBoundingBox) { return contentContainerWidth > titleBoundingBox.right ? 0 : titleBoundingBox.right - contentContainerWidth; } adjustForScrollbarIfNeeded(offset) { if (elementorFrontend.config.is_rtl && elementorFrontend.isEditMode()) { const scrollbarWidth = window.innerWidth - elementorFrontend.elements.$body[0].clientWidth; offset -= scrollbarWidth; } return offset; } getMenuContainerOffset() { const menuContainerBoundingBox = this.elements.$widgetContainer[0].getBoundingClientRect(); return elementorFrontend.config.is_rtl ? this.getMenuContainerOffsetRtl(menuContainerBoundingBox) : menuContainerBoundingBox.left; } getMenuContainerOffsetRtl(menuContainerBoundingBox) { const bodyWidth = elementorFrontend.elements.$body[0].clientWidth; let menuContainerOffset = bodyWidth - menuContainerBoundingBox.right; if (elementorFrontend.isEditMode()) { // In RTL mode, the editor's scrollbar is on the left side, so we need to add its width to the offset. const scrollbarWidth = window.innerWidth - bodyWidth; menuContainerOffset += scrollbarWidth; } return menuContainerOffset; } resetContentContainersPosition() { this.elements.$tabContents.css({ left: '', right: '', bottom: '', position: 'var(--position)', 'max-width': '', width: 'var(--width)' }); this.elements.$widgetContainer.removeClass('content-above'); } getTabContentFilterSelector(tabIndex) { return `[data-tab-index="${tabIndex}"]`; } isActiveTab(tabIndex) { return 'true' === this.elements.$tabDropdowns.filter('[data-tab-index="' + tabIndex + '"]').attr(this.getSettings('ariaAttributes').titleStateAttribute); } activateDefaultTab() { const settings = this.getSettings(); const defaultActiveTab = this.getEditSettings('activeItemIndex') || 1, originalToggleMethods = { showTabFn: settings.showTabFn, hideTabFn: settings.hideTabFn }; // Toggle tabs without animation to avoid jumping this.setSettings({ showTabFn: 'show', hideTabFn: 'hide' }); this.changeActiveTab(defaultActiveTab); // Return back original toggle effects this.setSettings(originalToggleMethods); this.elements.$widgetContainer.addClass('e-activated'); } activateTab(tabIndex) { const settings = this.getSettings(), activeClass = settings.classes.active, childMenuDropdownSelector = `.elementor-element-${this.getID()} .e-n-menu .e-n-menu .e-n-menu-dropdown-icon`, childMenuContentSelector = `.elementor-element-${this.getID()} .e-n-menu .e-n-menu .e-n-menu-content > .e-con`, $requestedTitle = this.elements.$tabDropdowns.filter(this.getTabTitleFilterSelector(tabIndex)).not(childMenuDropdownSelector), animationDuration = 'show' === settings.showTabFn ? 0 : 400, $requestedContent = this.elements.$tabContents.filter(this.getTabContentFilterSelector(tabIndex)).not(childMenuContentSelector); this.addAnimationToContentIfNeeded(tabIndex); $requestedContent[settings.showTabFn](animationDuration, () => this.onShowTabContent($requestedContent)); $requestedTitle.attr(this.getTitleActivationAttributes()); $requestedTitle.prev('.e-n-menu-title-container').find('a').attr(this.getTitleActivationAttributes('link')); $requestedContent.addClass(activeClass).parent().addClass(activeClass); $requestedContent.css({ display: 'var(--display)' }); $requestedContent.removeAttr('display'); if (elementorFrontend.isEditMode() && !!$requestedContent.length) { this.activeContainerWidthListener($requestedContent); } this.menuHeightController.reassignMenuHeight($requestedContent); } deactivateActiveTab() { const settings = this.getSettings(), activeClass = settings.classes.active, activeTitleFilter = settings.ariaAttributes.activeTitleSelector, activeContentFilter = '.' + activeClass, $activeTitle = this.elements.$tabDropdowns.filter(activeTitleFilter), $activeContent = this.elements.$tabContents.filter(activeContentFilter); this.setTabDeactivationAttributes($activeTitle); this.elements.$menuContent.removeClass(activeClass); $activeContent.removeClass(activeClass); $activeContent[settings.hideTabFn](0, () => this.onHideTabContent($activeContent)); this.removeAnimationFromContentIfNeeded(); if (elementorFrontend.isEditMode() && !!$activeContent.length) { this.observedContainer?.unobserve($activeContent[0]); } this.menuHeightController.resetMenuHeight($activeContent); this.clickInProgress = true; } getTitleActivationAttributes(elementType = 'tab') { const titleAttributes = {}; if ('tab' === elementType) { titleAttributes['aria-expanded'] = 'true'; } return titleAttributes; } setTabDeactivationAttributes($activeTitle) { const titleStateAttribute = this.getSettings('ariaAttributes').titleStateAttribute; $activeTitle.attr(`${titleStateAttribute}`, 'false'); } shouldPositionContentAbove($contentContainer, offset = 0) { const contentDimensions = $contentContainer[0].getBoundingClientRect(); return this.isContentShorterThanItsTopOffset(contentDimensions, offset) && this.isContentTallerThanItsBottomOffset(contentDimensions); } isContentShorterThanItsTopOffset(contentDimensions, offset) { return contentDimensions.height < contentDimensions.top - offset; } isContentTallerThanItsBottomOffset(contentDimensions) { return window.innerHeight - contentDimensions.top < contentDimensions.height; } onShowTabContent($requestedContent) { this.handleContentContainerPosition($requestedContent); elementorFrontend.elements.$window.trigger('elementor-pro/motion-fx/recalc'); elementorFrontend.elements.$window.trigger('elementor/nested-tabs/activate', $requestedContent); elementorFrontend.elements.$window.trigger('elementor/bg-video/recalc'); } onHideTabContent() { if (this.elements.$widgetContainer.hasClass('content-above')) { this.resetContentContainersPosition(); } } changeActiveTab(tabIndex, fromUser = true, byKeyboard = false) { if (this.clickInProgress && elementorFrontend.isEditMode() && !byKeyboard) { return; } const isActiveTab = this.isActiveTab(tabIndex); this.deactivateActiveTab(); if (!isActiveTab || isActiveTab && !fromUser) { this.clickInProgress = true; this.activateTab(tabIndex); } setTimeout(() => { this.clickInProgress = false; }); } changeActiveTabByKeyboard(event, settings) { if (settings.widgetId.toString() !== this.getID().toString()) { return; } if (!settings.titleIndex) { this.changeActiveTab('', true, true); return; } const $focusableElement = this.$element.find(`[data-focus-index="${settings.titleIndex}"]`), isLinkElement = 'a' === $focusableElement[0].tagName.toLowerCase(), dropdownSelector = this.getSettings('selectors.tabDropdown'), $tabDropdown = isLinkElement ? $focusableElement.next(dropdownSelector) : $focusableElement, tabIndex = this.getTabIndex($tabDropdown[0]); this.changeActiveTab(tabIndex, true, true); event.stopPropagation(); } onTabClick(event) { if (elementorFrontend.isEditMode()) { event.preventDefault(); } const hasNoDropdown = event?.currentTarget?.classList?.contains('link-only'); // Tweak for NVDA screen reader with Windows Edge. // Ref: https://github.com/nvaccess/nvda/issues/7898 const dropdownOpensWithHover = !this.isNeedToOpenOnClick(), blockMouseClickEvents = dropdownOpensWithHover && !this.isKeyboardNavigation; if (hasNoDropdown || blockMouseClickEvents) { return; } const selectors = this.getSettings('selectors'), getClickedMenuId = event?.target?.closest(selectors.elementorWidgetWrapper)?.getAttribute('data-id'), getWidgetId = this.getID().toString(); if (getClickedMenuId !== getWidgetId) { return; } const clickedElement = event?.currentTarget, dropdownElement = clickedElement?.querySelector(selectors.tabDropdown), tabIndex = this.getTabIndex(dropdownElement); this.changeActiveTab(tabIndex, true); } bindEvents() { this.elements.$tabTitles.on(this.getTabEvents()); this.elements.$dropdownMenuToggle.on('click', this.onClickToggleDropdownMenu.bind(this)); this.elements.$tabContents.on(this.getContentEvents()); this.elements.$menuContent.on(this.getContentEvents()); this.elements.$headingContainer.on(this.getHeadingEvents()); elementorFrontend.addListenerOnce(this.getModelCID(), 'scroll', elementorFrontend.debounce(this.menuHeightController.reassignMobileMenuHeight.bind(this.menuHeightController), 250)); elementorFrontend.elements.$window.on('elementor/nested-tabs/activate', this.reInitSwipers); elementorFrontend.elements.$window.on('elementor/nested-elements/activate-by-keyboard', this.changeActiveTabByKeyboard.bind(this)); elementorFrontend.elements.$window.on('elementor/mega-menu/dropdown-toggle-by-keyboard', this.onClickToggleDropdownMenuByKeyboard.bind(this)); elementorFrontend.elements.$window.on('resize', this.resizeEventHandler.bind(this)); if (elementorFrontend.isEditMode()) { this.addChildLifeCycleEventListeners(); elementorFrontend.elements.$window.on('elementor/dynamic/url_change', this.changeMegaMenuTitleContainerTag.bind(this)); } elementorFrontend.elements.$window.on('elementor/nested-container/atomic-repeater', this.linkContainer.bind(this)); } unbindEvents() { this.elements.$tabTitles.off(); this.elements.$menuContent.off(); this.elements.$tabContents.off(); this.elements.$headingContainer.off(); elementorFrontend.elements.$window.off('resize'); if (elementorFrontend.isEditMode()) { this.removeChildLifeCycleEventListeners(); elementorFrontend.elements.$window.on('elementor/dynamic/url_change', this.changeMegaMenuTitleContainerTag.bind(this)); } elementorFrontend.elements.$window.off('elementor/nested-tabs/activate', this.reInitSwipers); elementorFrontend.elements.$window.off('elementor/nested-elements/activate-by-keyboard', this.changeActiveTabByKeyboard.bind(this)); elementorFrontend.elements.$window.off('elementor/mega-menu/dropdown-toggle-by-keyboard', this.onClickToggleDropdownMenuByKeyboard.bind(this)); elementorFrontend.elements.$window.off('resize', this.resizeEventHandler.bind(this)); elementorFrontend.elements.$window.off('elementor/nested-container/atomic-repeater', this.linkContainer.bind(this)); } /** * Fixes issues where Swipers that have been initialized while a tab is not visible are not properly rendered * and when switching to the tab the swiper will not respect any of the chosen `autoplay` related settings. * * This is triggered when switching to a nested tab, looks for Swipers in the tab content and reinitializes them. * * @param {Object} event - Incoming event. * @param {Object} content - Active nested tab dom element. */ reInitSwipers(event, content) { const swiperElements = content.querySelectorAll('.swiper'); for (const element of swiperElements) { if (!element.swiper) { return; } element.swiper.initialized = false; element.swiper.init(); } } resizeEventHandler() { this.resizeListener = this.handleContentContainerPosition(); this.setLayoutType(); this.setTouchMode(); this.menuHeightController.reassignMobileMenuHeight(); this.setScrollPosition(); const activeTitleSelector = this.getSettings('ariaAttributes').activeTitleSelector, tabIndex = this.elements.$tabDropdowns.filter(activeTitleSelector).attr('data-tab-index'), childMenuContentSelector = `.elementor-element-${this.getID()} .e-n-menu .e-n-menu .e-n-menu-content > .e-con`, $requestedContent = this.elements.$tabContents.filter(this.getTabContentFilterSelector(tabIndex)).not(childMenuContentSelector); this.menuHeightController.resetMenuHeight($requestedContent); this.menuHeightController.reassignMenuHeight($requestedContent); } /** * Add Child Lifecycle Event Listeners * * This method adds event listeners for the elementor/editor/element-rendered and elementor/editor/element-destroyed * events. These events are fired when an element is rendered or destroyed in the editor. The callback functions * check if the rendered/destroyed element is nested in this mega-menu instance, and if it is, triggers the * recalculation of the mega-menu's content containers position. */ addChildLifeCycleEventListeners() { this.lifecycleChangeListener = this.handleContentContainerChildrenChanges.bind(this); window.addEventListener('elementor/editor/element-rendered', this.lifecycleChangeListener); window.addEventListener('elementor/editor/element-destroyed', this.lifecycleChangeListener); } removeChildLifeCycleEventListeners() { window.removeEventListener('elementor/editor/element-rendered', this.lifecycleChangeListener); window.removeEventListener('elementor/editor/element-destroyed', this.lifecycleChangeListener); } handleContentContainerChildrenChanges(event) { if (!this.isNestedElementRenderedInContentContainer(event.detail.elementView)) { return; } this.handleContentContainerPosition(); } isNestedElementRenderedInContentContainer(elementView) { const elementContainer = elementView?.getContainer(); if (!elementContainer) { return false; } const elementAncestors = elementContainer.getParentAncestry(); return elementAncestors.some(parent => this.getID().toString() === parent.model.get('id').toString()); } getTabEvents() { const tabEvents = { click: this.onTabClick.bind(this) }; return this.isNeedToOpenOnClick() ? tabEvents : this.replaceClickWithHover(tabEvents); } getContentEvents() { return this.isNeedToOpenOnClick() ? {} : { mouseleave: this.onMouseLeave.bind(this), mousemove: this.trackMousePosition.bind(this) }; } isNeedToOpenOnClick() { const elementSettings = this.getElementSettings(); return this.isEdit || this.isMobileDevice() || 'hover' !== elementSettings.open_on || 'dropdown' === elementSettings.item_layout; } isMobileDevice() { const mobileDevices = ['mobile', 'mobile_extra', 'tablet', 'tablet_extra']; return mobileDevices.includes(elementorFrontend.getCurrentDeviceMode()); } replaceClickWithHover(tabEvents) { tabEvents.mouseenter = this.onMouseTitleEnter.bind(this); tabEvents.mouseleave = this.onMouseLeave.bind(this); tabEvents.keyup = this.setKeyboardNavigation.bind(this); return tabEvents; } onMouseTitleEnter(event) { event.preventDefault(); const settings = this.getSettings(), currentTarget = event?.currentTarget, currentTargetWidgetId = currentTarget?.closest(settings.selectors.elementorWidgetWrapper)?.getAttribute('data-id'), widgetId = this.$element[0].getAttribute('data-id'); if (widgetId !== currentTargetWidgetId) { return; } const titleStateAttribute = settings.ariaAttributes.titleStateAttribute, dropdownSelector = settings.selectors.tabDropdown, activeDropdownElement = currentTarget?.querySelector(dropdownSelector), isActiveTabTitle = 'true' === activeDropdownElement?.getAttribute(titleStateAttribute); if (isActiveTabTitle) { return; } const tabIndex = activeDropdownElement?.getAttribute('data-tab-index'); this.changeActiveTab(tabIndex, true); } onClickToggleDropdownMenu(show) { this.elements.$widgetContainer.attr('data-layout', 'dropdown'); const titleStateAttribute = this.getSettings('ariaAttributes').titleStateAttribute, isDropdownVisible = 'true' === this.elements.$dropdownMenuToggle.attr(titleStateAttribute); if ('boolean' !== typeof show) { show = !isDropdownVisible; } const activeTabTitleValue = show ? 'true' : 'false'; this.elements.$dropdownMenuToggle.attr(titleStateAttribute, activeTabTitleValue); elementorFrontend.utils.events.dispatch(window, 'elementor-pro/mega-menu/dropdown-open'); this.menuHeightController.reassignMobileMenuHeight(); } onClickOutsideDropdownMenu(event) { if (!this.isNeedToOpenOnClick()) { return; } const settings = this.getSettings(), selectors = settings.selectors, widgetWrapper = `.elementor-element-${this.getID()}`, activeClass = settings.classes.active, activeContentFilter = `> .e-con.${activeClass}`, $activeContent = this.elements.$menuContent.find(activeContentFilter), isMenuDropdownsClosed = 0 === $activeContent.length, isElementRemovedFromDOM = elementorFrontend.isEditMode() && !document.body.contains(event?.target), isClickedInsideCurrentMenu = !!event?.target?.closest(`${widgetWrapper} ${selectors.widgetContainer}`), isMenuContentWrapperClicked = event?.target?.classList?.contains(selectors.menuContent.replace('.', '')); if (isMenuContentWrapperClicked) { this.deactivateActiveTab(); return; } if (isMenuDropdownsClosed || isClickedInsideCurrentMenu || isElementRemovedFromDOM) { return; } this.deactivateActiveTab(); } onClickToggleDropdownMenuByKeyboard(event, settings) { if (settings.widgetId.toString() !== this.getID().toString()) { return; } this.onClickToggleDropdownMenu(settings.show); } addAnimationToContentIfNeeded(tabIndex) { const openAnimation = this.getElementSettings('open_animation'); if ('none' === openAnimation || '' === openAnimation) { return; } const $requestedContent = this.elements.$tabContents.filter(this.getTabContentFilterSelector(tabIndex)); $requestedContent.addClass(`animated ${openAnimation}`); } removeAnimationFromContentIfNeeded() { const openAnimation = this.getElementSettings('open_animation'); if ('none' === openAnimation || '' === openAnimation) { return; } this.elements.$tabContents.removeClass(`animated ${openAnimation}`); } /** * Store the current Y-coordinate of the mouse cursor. * * @param {Event} event - The mouse event object. */ trackMousePosition(event) { this.prevMouseY = event?.clientY; } /** * Check if the menu content is currently hovered. * * @return {boolean} - True if menu content is hovered, otherwise false. */ isMenuContentHovered() { const settings = this.getSettings(), $widget = this.$element; return $widget.find(`${settings.selectors.menuContent}:hover`).length > 0; } isCursorInBetweenMenuTitleAndContent(event) { const settings = this.getSettings(); const selectors = settings.selectors; const currentElement = event?.currentTarget; const activeContent = currentElement?.closest(selectors.menuItem)?.querySelector(selectors.menuContent); const isMouseLeavingTabTitle = currentElement.classList?.contains(selectors.tabTitle.replace('.', '')); const hasActiveTabTitle = activeContent?.classList?.contains(settings.classes.active); if (!isMouseLeavingTabTitle || !hasActiveTabTitle) { return false; } const titleBoundingClientRect = currentElement.getBoundingClientRect(); const contentBoundingClientRect = activeContent.getBoundingClientRect(); const mouseY = event.clientY; const isTitleAboveContent = titleBoundingClientRect.bottom <= contentBoundingClientRect.top; return isTitleAboveContent ? mouseY >= titleBoundingClientRect.bottom && mouseY < contentBoundingClientRect.top : mouseY <= titleBoundingClientRect.top && mouseY > contentBoundingClientRect.bottom; } /** * Determines whether the cursor moved sideways or downwards. * * @param {Event} event - The mouse event object. * @return {boolean} - True if the cursor moved sideways or downwards, otherwise false. */ didCursorMoveSidewaysOrDown(event) { // Detects if the Y-coordinate of the mouse has not decreased (i.e., either remained the same or increased). return this.prevMouseY !== null && event?.clientY >= this.prevMouseY; } /** * Check whether the dropdown menu should remain open based on hover and cursor movement. * * @param {boolean} isMouseLeavingTabContent - True if the mouse is leaving the tab content. * @param {Event} event - The mouse event object. * @return {boolean} - True if dropdown should be considered as hovered, otherwise false. */ isHoveredDropdownMenu(isMouseLeavingTabContent, event) { // If the mouse is leaving the tab content and it moved sideways or downwards, close the dropdown. if (isMouseLeavingTabContent && this.didCursorMoveSidewaysOrDown(event)) { return false; } // Otherwise, return true if the menu content is hovered. return this.isMenuContentHovered(); } /** * Handle the event when the mouse leaves the dropdown. * * @param {Event} event - The mouse event object. */ onMouseLeave(event) { event.preventDefault(); const isMouseLeavingTabContent = event?.currentTarget?.classList?.contains('e-con'); if (!this.isHoveredDropdownMenu(isMouseLeavingTabContent, event) && !this.isCursorInBetweenMenuTitleAndContent(event)) { this.deactivateActiveTab(); } } onInit(...args) { this.menuHeightController = new elementorProFrontend.utils.DropdownMenuHeightController(this.dropdownMenuHeightControllerConfig()); super.onInit(...args); if (this.getSettings('autoExpand')) { this.activateDefaultTab(); } (0, _flexHorizontalScroll.setHorizontalScrollAlignment)(this.getHorizontalScrollingSettings()); this.setTouchMode(); if (!elementorFrontend.isEditMode()) { const classes = this.getSettings('classes'); this.anchorLinks = new _anchorLink.default(this.elements.$anchorLink, classes); this.anchorLinks.initialize(); elementorFrontend.elements.$window.on('elementor/dynamic/url_change', this.changeMegaMenuTitleContainerTag.bind(this)); } this.menuToggleVisibilityListener(this.elements.$dropdownMenuToggle); this.setScrollPosition(); this.onClickOutsideDropdownMenu = this.onClickOutsideDropdownMenu.bind(this); document.addEventListener('click', this.onClickOutsideDropdownMenu); this.clickInProgress = false; } onDestroy() { document.removeEventListener('click', this.onClickOutsideDropdownMenu); elementorFrontend.elements.$window.off('elementor/dynamic/url_change'); } setScrollPosition() { const settingsObject = { element: this.elements.$headingContainer[0], direction: this.getItemPosition(), justifyCSSVariable: '--n-menu-heading-justify-content', horizontalScrollStatus: this.getHorizontalScrollSetting() }; (0, _flexHorizontalScroll.setHorizontalScrollAlignment)(settingsObject); } getPropsThatTriggerContentPositionCalculations() { return ['content_horizontal_position', 'content_position', 'item_position_horizontal', 'content_width', 'item_layout']; } activeContainerWidthListener($activeContainer) { let previousWidth = 0; this.observedContainer = new ResizeObserver(activeContainer => { const currentWidth = activeContainer[0].borderBoxSize?.[0].inlineSize; if (!!currentWidth && currentWidth !== previousWidth) { previousWidth = currentWidth; if (0 !== previousWidth) { this.handleContentContainerPosition(); } } }); this.observedContainer.observe($activeContainer[0]); } menuToggleVisibilityListener($menuToggle) { let previousWidth; this.observedContainer = new ResizeObserver(menuToggle => { const currentWidth = menuToggle[0].borderBoxSize?.[0].inlineSize; if (currentWidth !== previousWidth) { previousWidth = currentWidth; this.setLayoutType(); } }); this.observedContainer.observe($menuToggle[0]); } onElementChange(propertyName) { if (this.getPropsThatTriggerContentPositionCalculations().includes(propertyName)) { this.handleContentContainerPosition(); } this.setLayoutType(); } onEditSettingsChange(propertyName, value) { const settings = this.getSettings(); if (settings.autoFocus && 'activeItemIndex' === propertyName) { this.changeActiveTab(value, false); } this.setLayoutType(); } /** * Sets the layout type as a data attribute, so that it can be use for the responsive or dropdown menu styling. * * Originally this styling was handled by the distinction between the heading and the content styling elements. * Since we removed the title duplication, we needed another way to distinguish between the horizontal and the dropdown styling. */ setLayoutType() { const layoutType = 'none' === this.elements.$dropdownMenuToggle.css('display') ? 'horizontal' : 'dropdown'; this.elements.$widgetContainer.attr('data-layout', layoutType); } getHeadingEvents() { const navigationWrapper = this.elements.$headingContainer[0]; return { mousedown: this.changeScrollStatusAndDispatch.bind(this, navigationWrapper), mouseup: this.changeScrollStatusAndDispatch.bind(this, navigationWrapper), mouseleave: this.changeScrollStatusAndDispatch.bind(this, navigationWrapper), mousemove: this.setHorizontalTitleScrollValuesAndDispatch.bind(this, navigationWrapper) }; } getHorizontalScrollSetting() { const currentDevice = elementorFrontend.getCurrentDeviceMode(); return elementorFrontend.utils.controls.getResponsiveControlValue(this.getElementSettings(), 'horizontal_scroll', '', currentDevice); } getItemPosition() { const currentDevice = elementorFrontend.getCurrentDeviceMode(); return elementorFrontend.utils.controls.getResponsiveControlValue(this.getElementSettings(), 'item_position_horizontal', '', currentDevice); } changeScrollStatusAndDispatch(navigationWrapper, event) { (0, _flexHorizontalScroll.changeScrollStatus)(navigationWrapper, event); elementorFrontend.elements.$window.trigger('elementor-pro/mega-menu/heading-mouse-event'); } setHorizontalTitleScrollValuesAndDispatch(navigationWrapper, event) { (0, _flexHorizontalScroll.setHorizontalTitleScrollValues)(navigationWrapper, this.getHorizontalScrollSetting(), event); elementorFrontend.elements.$window.trigger('elementor-pro/mega-menu/heading-mouse-event'); } linkContainer(event) { const { container } = event.detail, id = container.model.get('id'), currentId = String(this.$element.data('id')), view = container.view.$el; if (id === currentId) { this.updateIndexValues(view); this.updateListeners(view); } } updateIndexValues(view) { const { selectors: { directTabTitle, directTabContent } } = this.getDefaultSettings(), currentMenu = view[0], tabsContents = currentMenu.querySelectorAll(directTabContent), tabTitles = currentMenu.querySelectorAll(directTabTitle), settings = this.getSettings(), itemIdBase = tabTitles[0].getAttribute('id').slice(0, -1); tabTitles.forEach((element, index) => { const newIndex = index + 1, updatedTabID = itemIdBase + newIndex, updatedContainerID = updatedTabID.replace('e-n-menu-title-', 'e-n-menu-content-'), updatedTabDropdownID = updatedTabID.replace('e-n-menu-title-', 'e-n-menu-dropdown-icon-'); element.setAttribute('id', updatedTabID); element.querySelector(settings.selectors.tabDropdown)?.setAttribute('data-tab-index', newIndex); element.querySelector(settings.selectors.tabDropdown)?.setAttribute('id', updatedTabDropdownID); element.querySelector(settings.selectors.tabDropdown)?.setAttribute('aria-controls', updatedContainerID); element.querySelector(settings.selectors.tabTitleText)?.setAttribute('data-binding-index', newIndex); tabsContents[index]?.setAttribute('aria-labelledby', updatedTabDropdownID); tabsContents[index]?.setAttribute('data-tab-index', newIndex); tabsContents[index]?.setAttribute('id', updatedContainerID); }); } updateListeners(view) { const { selectors: { tabClickableTitle, tabDropdown, tabContent, tabTitle } } = this.getSettings(), $tabTitles = view.find(tabTitle), $tabClickableTitle = view.find(tabClickableTitle); this.elements.$tabTitles = view.find(tabClickableTitle); this.elements.$tabDropdowns = view.find(tabDropdown); this.elements.$tabContents = view.find(tabContent); $tabTitles.off(); $tabClickableTitle.on(this.getTabEvents()); this.clickInProgress = false; } /** * Toggle the container tag of the mega menu title. * Needs to be places in pro Mega Menu frontend handler * * @param {Event} event * @return {undefined} */ changeMegaMenuTitleContainerTag(event) { const { element, actionName, value } = event.detail, elementParent = element.parentNode, closestMenuItemTitle = elementParent.parentNode, newElement = this.maybeCreateNewElement(elementParent, value), elementToUpdate = this.maybeReplaceMenuItemTitleContent(elementParent, newElement, closestMenuItemTitle), currentUrl = element.dataset?.currentUrl || null; this.maybeUpdateNewElementsHref(value, elementToUpdate); this.eCurrentClassHandler(actionName, closestMenuItemTitle, currentUrl === value); return undefined; } maybeReplaceMenuItemTitleContent(elementParent, newElement, closestMenuItemTitle) { if (!newElement) { return elementParent; } Array.from(elementParent.attributes).forEach(attr => { newElement.setAttribute(attr.name, attr.value); }); if ('A' === newElement.tagName) { newElement.classList.add('e-link', 'e-focus'); } else if ('DIV' === newElement.tagName) { newElement.classList.remove('e-link', 'e-focus'); } newElement.innerHTML = elementParent.innerHTML; closestMenuItemTitle.replaceChild(newElement, elementParent); return newElement; } maybeCreateNewElement(elementParent, value) { if (!value) { return document.createElement('div'); } if (value && 'DIV' === elementParent.tagName) { return document.createElement('a'); } } maybeUpdateNewElementsHref(value, newElement) { if (value) { newElement.setAttribute('href', value); } else { newElement.removeAttribute('href'); } } eCurrentClassHandler(actionName, closestMenuItemTitle, isCurrentUrl) { const settings = this.getSettings(), { classes: { activeAnchorItem: eCurrentClassName }, postUrl, internalUrl } = settings; switch (actionName) { case postUrl: closestMenuItemTitle.classList.add(eCurrentClassName); break; case internalUrl: if (isCurrentUrl) { closestMenuItemTitle.classList.add(eCurrentClassName); } else { closestMenuItemTitle.classList.remove(eCurrentClassName); } break; default: if (closestMenuItemTitle.classList.contains(eCurrentClassName) && postUrl !== actionName) { closestMenuItemTitle.classList.remove(eCurrentClassName); } break; } } setTouchMode() { const widgetSelector = this.getSettings('selectors').widgetContainer; if (elementorFrontend.isEditMode() || 'resize' === event?.type) { const responsiveDevices = ['mobile', 'mobile_extra', 'tablet', 'tablet_extra'], currentDevice = elementorFrontend.getCurrentDeviceMode(); if (-1 !== responsiveDevices.indexOf(currentDevice)) { this.$element.find(widgetSelector).attr('data-touch-mode', 'true'); return; } } else if ('ontouchstart' in window) { this.$element.find(widgetSelector).attr('data-touch-mode', 'true'); return; } this.$element.find(widgetSelector).attr('data-touch-mode', 'false'); } getTabsDirection() { const currentDevice = elementorFrontend.getCurrentDeviceMode(); return elementorFrontend.utils.controls.getResponsiveControlValue(this.getElementSettings(), 'tabs_justify_horizontal', '', currentDevice); } getHorizontalScrollingSettings() { return { element: this.elements.$headingContainer[0], direction: this.getTabsDirection(), justifyCSSVariable: '--n-tabs-heading-justify-content', horizontalScrollStatus: this.getHorizontalScrollSetting() }; } } exports["default"] = MegaMenu; /***/ }), /***/ "../modules/mega-menu/assets/js/frontend/utils.js": /*!********************************************************!*\ !*** ../modules/mega-menu/assets/js/frontend/utils.js ***! \********************************************************/ /***/ ((__unused_webpack_module, exports) => { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.isMenuInDropdownMode = isMenuInDropdownMode; function isMenuInDropdownMode(elementSettings) { if ('dropdown' === elementSettings.item_layout) { return true; } const activeBreakpointsList = elementorFrontend.breakpoints.getActiveBreakpointsList({ withDesktop: true }), breakpointIndex = activeBreakpointsList.indexOf(elementSettings.breakpoint_selector), currentDeviceModeIndex = activeBreakpointsList.indexOf(elementorFrontend.getCurrentDeviceMode()); return currentDeviceModeIndex <= breakpointIndex; } /***/ }) }]); //# sourceMappingURL=mega-menu.595ee0dffef2bd038c6b.bundle.js.map